From 99758dade94fe30ce93f510962c040f33b9ea765 Mon Sep 17 00:00:00 2001 From: bhoff Date: Thu, 29 Aug 2024 07:46:46 -0700 Subject: [PATCH 01/37] PLFM-8554: initial commit --- .github/workflows/aws-deploy.yml | 29 +++++++++++------------ .github/workflows/main.yml | 4 ++-- README.md | 3 ++- cdk.json | 32 +++++++++++--------------- docker_fargate/docker_fargate_stack.py | 10 +++++++- 5 files changed, 41 insertions(+), 37 deletions(-) diff --git a/.github/workflows/aws-deploy.yml b/.github/workflows/aws-deploy.yml index c93ea5f..63a0657 100644 --- a/.github/workflows/aws-deploy.yml +++ b/.github/workflows/aws-deploy.yml @@ -26,18 +26,17 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 -# Uncomment for deployment to AWS -# - name: Assume AWS Role -# uses: aws-actions/configure-aws-credentials@v1 -# with: -# aws-region: us-east-1 -# role-to-assume: ${{inputs.ROLE_TO_ASSUME }} -# role-session-name: GitHubActions-${{ github.repository_owner }}-${{ github.event.repository.name }}-${{ github.run_id }} -# role-duration-seconds: 1200 -# -# - name: cdk deploy -# uses: youyo/aws-cdk-github-actions@v2 -# with: -# cdk_subcommand: 'deploy' -# cdk_args: '--require-approval never --context env=${{ inputs.CONTEXT }} --progress events --debug' -# actions_comment: false + - name: Assume AWS Role + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-region: us-east-1 + role-to-assume: ${{inputs.ROLE_TO_ASSUME }} + role-session-name: GitHubActions-${{ github.repository_owner }}-${{ github.event.repository.name }}-${{ github.run_id }} + role-duration-seconds: 1200 + + - name: cdk deploy + uses: youyo/aws-cdk-github-actions@v2 + with: + cdk_subcommand: 'deploy' + cdk_args: '--require-approval never --context env=${{ inputs.CONTEXT }} --progress events --debug' + actions_comment: false diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 94600d8..899d125 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -44,7 +44,7 @@ jobs: secrets: inherit with: CONTEXT: dev - ROLE_TO_ASSUME: arn:aws:iam:::role/ + ROLE_TO_ASSUME: arn:aws:iam::449435941126:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry cdk-deploy-prod: if: ${{github.ref == 'refs/heads/prod'}} @@ -53,4 +53,4 @@ jobs: secrets: inherit with: CONTEXT: prod - ROLE_TO_ASSUME: arn:aws:iam:::role/ + ROLE_TO_ASSUME: arn:aws:iam::325565585839:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry diff --git a/README.md b/README.md index cc84a25..3157a56 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# aws-application-deployment-template +# synapse-docker-registry CDK-based template for deploying a containerized application to AWS @@ -133,6 +133,7 @@ messages from AWS Each new environment (dev/staging/prod/etc..) may require adding secrets. If a secret is not created for the environment you may get an error with the following stack trace.. + ``` Resource handler returned message: "Error occurred during operation 'ECS Deployment Circuit Breaker was triggered'." (RequestToken: d180e115-ba94-d8a2-acf9-abe17a3aaed9, HandlerErrorCode: GeneralServiceException) new BaseService (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/jsii-kernel-4PEWmj/node_modules/aws-cdk-lib/aws-ecs/lib/base/base-service.js:1:3583) diff --git a/cdk.json b/cdk.json index c3d0444..96f3d2a 100644 --- a/cdk.json +++ b/cdk.json @@ -31,36 +31,32 @@ "aws-cn" ], "dev": { - "IMAGE_PATH_AND_TAG": "ghcr.io/sage-bionetworks/myapp:release-1.0", + "IMAGE_PATH_AND_TAG": "registry:2", "AWS_DEFAULT_REGION": "us-east-1", - "PORT": "3838", + "PORT": "443", "CONTAINER_ENV": { - "name1": "value1", - "name2": "value2" }, "TAGS": { - "CostCenter": "NO PROGRAM / 000000", - "OwnerEmail": "joe@sagebase.org" + "CostCenter": "Platform Infrastructure / 990300", + "OwnerEmail": "synapseeng@sagebase.org" }, - "STACK_NAME_PREFIX": "myapp-dev", - "VPC_CIDR": "172.31.0.0/24", - "ACM_CERT_ARN": "arn:aws:acm:us-east-1::certificate/" + "STACK_NAME_PREFIX": "registry-dev", + "VPC_CIDR": "172.33.0.0/24", + "ACM_CERT_ARN": "arn:aws:acm:us-east-1:449435941126:certificate/bbd59a26-ad30-4b74-ad2d-194241801b22" }, "prod": { - "IMAGE_PATH_AND_TAG": "ghcr.io/sage-bionetworks/myapp:release-1.0", + "IMAGE_PATH_AND_TAG": "registry:2", "AWS_DEFAULT_REGION": "us-east-1", - "PORT": "3838", + "PORT": "443", "CONTAINER_ENV": { - "name1": "value1", - "name2": "value2" }, "TAGS": { - "CostCenter": "NO PROGRAM / 000000", - "OwnerEmail": "joe@sagebase.org" + "CostCenter": "Platform Infrastructure / 990300", + "OwnerEmail": "synapseeng@sagebase.org" }, - "STACK_NAME_PREFIX": "myapp-prod", - "VPC_CIDR": "172.32.0.0/24", - "ACM_CERT_ARN": "arn:aws:acm:us-east-1::certificate/" + "STACK_NAME_PREFIX": "registry-prod", + "VPC_CIDR": "172.33.1.0/24", + "ACM_CERT_ARN": "arn:aws:acm:us-east-1:325565585839:certificate/7c42c355-3d69-4537-a5e6-428212db646f" } } } diff --git a/docker_fargate/docker_fargate_stack.py b/docker_fargate/docker_fargate_stack.py index b840726..2cf7db2 100644 --- a/docker_fargate/docker_fargate_stack.py +++ b/docker_fargate/docker_fargate_stack.py @@ -59,8 +59,16 @@ def __init__(self, scope: Construct, context: str, env: dict, vpc: ec2.Vpc, **kw } env_vars = get_container_env(env) + + entrypoint = "sh" + command = "echo ${config.yml} > /etc/docker/registry/config.yml" + command = command + " && echo ${public.crt} > /etc/docker/registry/ssl/public.crt" + command = command + " && echo ${privatekey.pem} > /etc/docker/registry/ssl/privatekey.pem" + command = command + " && /entrypoint.sh /etc/docker/registry/config.yml" task_image_options = ecs_patterns.ApplicationLoadBalancedTaskImageOptions( + entrypoint=entrypoint, + command=["-c", command], image=ecs.ContainerImage.from_registry(get_docker_image_name(env)), environment=env_vars, secrets = secrets, @@ -97,7 +105,7 @@ def __init__(self, scope: Construct, context: str, env: dict, vpc: ec2.Vpc, **kw # https://docs.aws.amazon.com/cdk/api/v1/python/aws_cdk.aws_elasticloadbalancingv2/ApplicationTargetGroup.html#aws_cdk.aws_elasticloadbalancingv2.ApplicationTargetGroup load_balanced_fargate_service.target_group.configure_health_check(interval=Duration.seconds(120), timeout=Duration.seconds(60)) - if False: # enable/disable autoscaling + if True: # enable/disable autoscaling scalable_target = load_balanced_fargate_service.service.auto_scale_task_count( min_capacity=1, # Minimum capacity to scale to. Default: 1 max_capacity=4 # Maximum capacity to scale to. From 9dcafbc644823a74f133b46e866223e95fcca8f7 Mon Sep 17 00:00:00 2001 From: bhoff Date: Tue, 3 Sep 2024 17:45:00 -0700 Subject: [PATCH 02/37] PLFM-8554: Run Synapse Docker registry using ECS --- README.md | 138 +++++-------------------- config.py | 2 +- docker_fargate/docker_fargate_stack.py | 13 +-- sample-registry-config.yml | 54 ++++++++++ 4 files changed, 85 insertions(+), 122 deletions(-) create mode 100644 sample-registry-config.yml diff --git a/README.md b/README.md index 3157a56..e780aac 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,46 @@ # synapse-docker-registry -CDK-based template for deploying a containerized application to AWS +CDK-based template for deploying the Synapse Docker registry -## Perequisites -AWS CDK projects require some bootstrapping before synthesis or deployment. -Please review the [bootstapping documentation](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_bootstrap) -before development. +## Configuration -## Development +We use the [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) -The `cdk.json` file tells the CDK Toolkit how to execute your app. +In dev the secret is named `registry-dev-DockerFargateStack/dev/ecs` and in the prod stack, +`registry-prod-DockerFargateStack/prod/ecs` -This project is set up like a standard Python project. The initialization -process also creates a virtualenv within this project, stored under the `.venv` -directory. To create the virtualenv it assumes that there is a `python3` -(or `python` for Windows) executable in your path with access to the `venv` -package. If for any reason the automatic creation of the virtualenv fails, -you can create the virtualenv manually. +A secret is a collection of key-value pairs. For this application there are four pairs. The keys and their values are described below. Note that each value is base64-encoded. +This is because Secrets Manager doesn't handle line breaks when values are entered in the AWS console. -To manually create a virtualenv on MacOS and Linux: +- `config.yml` The value should be a yml file based on `sample-registry-config.yml`, provided in this repository. -``` -$ python3 -m venv .venv -``` +- `public.crt` The registry domain certificate, described [here](https://distribution.github.io/distribution/about/deploying/). -After the init process completes and the virtualenv is created, you can use the following -step to activate your virtualenv. +- `privatekey.pem` The private key for the above certificate, in .pem format. -``` -$ source .venv/bin/activate -``` +- `cert.pem` The certificate part of the RSA key pair used by Synapse to sign JWTs, in .pem format. -If you are a Windows platform, you would activate the virtualenv like this: -``` -% .venv\Scripts\activate.bat -``` +### Missing Secrets -Once the virtualenv is activated, you can install the required dependencies. +Each new environment (dev/staging/prod/etc..) may require adding secrets. If a +secret is not created for the environment you may get an error with the following +stack trace.. ``` -$ pip install -r requirements.txt +Resource handler returned message: "Error occurred during operation 'ECS Deployment Circuit Breaker was triggered'." (RequestToken: d180e115-ba94-d8a2-acf9-abe17a3aaed9, HandlerErrorCode: GeneralServiceException) + new BaseService (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/jsii-kernel-4PEWmj/node_modules/aws-cdk-lib/aws-ecs/lib/base/base-service.js:1:3583) + \_ new FargateService (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/jsii-kernel-4PEWmj/node_modules/aws-cdk-lib/aws-ecs/lib/fargate/fargate-service.js:1:967) + \_ new ApplicationLoadBalancedFargateService (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/jsii-kernel-4PEWmj/node_modules/aws-cdk-lib/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.js:1:2300) + \_ Kernel._create (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:9964:29) + \_ Kernel.create (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:9693:29) + \_ KernelHost.processRequest (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:11544:36) + \_ KernelHost.run (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:11504:22) + \_ Immediate._onImmediate (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:11505:46) + \_ processImmediate (node:internal/timers:464:21) ``` -At this point you can now synthesize the CloudFormation template for this code. -An environment context is rquired, check [cdk.json](cdk.json) for available contexts. - -``` -$ cdk synth --context env=dev -``` ## Testing @@ -67,82 +58,3 @@ Tests are available in the tests folder. Execute the following to run tests: ``` python -m pytest tests/ -s -v ``` - -## Secrets - -We use the [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) -to store secrets for this project. An AWS best practice is to create secrets -with a unique ID to prevent conflicts when multiple instances of this project -is deployed to the same AWS account. Our naming convention is -`//`. The template in this repo' uses -the secret name, `ecs`, so an example Secrets Manager name is `myapp-dev-DockerFargateStack/dev/ecs`. - - -## Deployment from GitHub to AWS - -To allow the GitHub action in your repository to deploy to AWS, submit a -PR like [this](https://github.com/Sage-Bionetworks-IT/organizations-infra/pull/771/files), -customizing the `StackName`, `Repositories` (name), and the `Account`(s) to -in which the infrastructure will be deployed. More on GitHub OIDC integration -[here](https://github.com/Sage-Bionetworks-IT/organizations-infra/tree/master/org-formation/650-identity-providers). - -Once the PR is merged, an IAM role will be created in each AWS account listed in the PR. -Put the ARNs for the roles in the `ROLE_TO_ASSUME` field of `main.yml`, which -allows switching between development and production based on the git branch. - -## VPC CIDR - -Select a unique IP address range for the VPC (CIDR) following the instructions -[here](https://sagebionetworks.jira.com/wiki/spaces/IT/pages/2850586648/Setup+AWS+VPC). -Enter the range as the `VPC_CIDR` parameter in the file `cdk.json`. - - -## DNS and Certificates - -Obtain the ARN of the ACM Certificate by following the instructions -[here](https://sagebionetworks.jira.com/wiki/spaces/IT/pages/2859302913/Admin+Tasks+for+CDK+Applications) -Set the value of `ACM_CERT_ARN` context variable to the ARN obtained above. - -Finally, a DNS CNAME must be created in org-formation after the initial -deployment of the application to make the application available at the desired -URL. The CDK application exports the DNS name of the Application Load Balancer -to be consumed in org-formation. [An example PR setting up a CNAME](https://github.com/Sage-Bionetworks-IT/organizations-infra/pull/739). - -Find the `LoadBalancerDNS` name: Navigate to the deployed stack in the AWS CloudFormation -console and click on the `Outputs` tab. On the row whose key is `LoadBalancerDNS` look for -the value in the `ExportName` column, e.g., `dca-dev-DockerFargateStack-LoadBalancerDNS`. -Now use the name in the `TargetHostName` definition, for example: - -``` -TargetHostName: !CopyValue [!Sub 'dca-dev-DockerFargateStack-LoadBalancerDNS', !Ref DnTDevAccount] -``` - -(You would also replace `DnTDevAccount` with the name of the account in which the application is deployed.) - - -## Debugging - -Generally CDK deployments will create cloudformation events during a CDK deploy. -The events can be viewed in the AWS console under the cloudformation service page. -Viewing those events will help with errors during a deployment. Below are cases -where it might be difficult to debug due to misleading or insufficient error -messages from AWS - -### Missing Secrets - -Each new environment (dev/staging/prod/etc..) may require adding secrets. If a -secret is not created for the environment you may get an error with the following -stack trace.. - -``` -Resource handler returned message: "Error occurred during operation 'ECS Deployment Circuit Breaker was triggered'." (RequestToken: d180e115-ba94-d8a2-acf9-abe17a3aaed9, HandlerErrorCode: GeneralServiceException) - new BaseService (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/jsii-kernel-4PEWmj/node_modules/aws-cdk-lib/aws-ecs/lib/base/base-service.js:1:3583) - \_ new FargateService (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/jsii-kernel-4PEWmj/node_modules/aws-cdk-lib/aws-ecs/lib/fargate/fargate-service.js:1:967) - \_ new ApplicationLoadBalancedFargateService (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/jsii-kernel-4PEWmj/node_modules/aws-cdk-lib/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.js:1:2300) - \_ Kernel._create (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:9964:29) - \_ Kernel.create (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:9693:29) - \_ KernelHost.processRequest (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:11544:36) - \_ KernelHost.run (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:11504:22) - \_ Immediate._onImmediate (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:11505:46) - \_ processImmediate (node:internal/timers:464:21) -``` diff --git a/config.py b/config.py index b168afa..a39c0b2 100644 --- a/config.py +++ b/config.py @@ -1,4 +1,4 @@ -CONTEXT_ENVS = ["dev", "staging", "prod"] +CONTEXT_ENVS = ["dev", "prod"] TAGS_CONTEXT = "TAGS" STACK_NAME_PREFIX_CONTEXT = "STACK_NAME_PREFIX" diff --git a/docker_fargate/docker_fargate_stack.py b/docker_fargate/docker_fargate_stack.py index 2cf7db2..06d5076 100644 --- a/docker_fargate/docker_fargate_stack.py +++ b/docker_fargate/docker_fargate_stack.py @@ -61,9 +61,10 @@ def __init__(self, scope: Construct, context: str, env: dict, vpc: ec2.Vpc, **kw env_vars = get_container_env(env) entrypoint = "sh" - command = "echo ${config.yml} > /etc/docker/registry/config.yml" - command = command + " && echo ${public.crt} > /etc/docker/registry/ssl/public.crt" - command = command + " && echo ${privatekey.pem} > /etc/docker/registry/ssl/privatekey.pem" + command = "echo ${config.yml} | base64 --decode > /etc/docker/registry/config.yml" + command = command + " && echo ${cert.pem} | base64 --decode > /etc/docker/registry/cert.pem" + command = command + " && echo ${public.crt} | base64 --decode > /etc/docker/registry/ssl/public.crt" + command = command + " && echo ${privatekey.pem} | base64 --decode > /etc/docker/registry/ssl/privatekey.pem" command = command + " && /entrypoint.sh /etc/docker/registry/config.yml" task_image_options = ecs_patterns.ApplicationLoadBalancedTaskImageOptions( @@ -101,11 +102,7 @@ def __init__(self, scope: Construct, context: str, env: dict, vpc: ec2.Vpc, **kw ssl_policy=elbv2.SslPolicy.FORWARD_SECRECY_TLS12_RES, # Strong forward secrecy ciphers and TLS1.2 only. ) - # Overriding health check timeout helps with sluggishly responding app's (e.g. Shiny) - # https://docs.aws.amazon.com/cdk/api/v1/python/aws_cdk.aws_elasticloadbalancingv2/ApplicationTargetGroup.html#aws_cdk.aws_elasticloadbalancingv2.ApplicationTargetGroup - load_balanced_fargate_service.target_group.configure_health_check(interval=Duration.seconds(120), timeout=Duration.seconds(60)) - - if True: # enable/disable autoscaling + if True: # enable/disable autoscaling scalable_target = load_balanced_fargate_service.service.auto_scale_task_count( min_capacity=1, # Minimum capacity to scale to. Default: 1 max_capacity=4 # Maximum capacity to scale to. diff --git a/sample-registry-config.yml b/sample-registry-config.yml new file mode 100644 index 0000000..e58dfe4 --- /dev/null +++ b/sample-registry-config.yml @@ -0,0 +1,54 @@ +# +# sample config.yml for Docker registry +# +# To use, complete the following fields: +# storage/s3:bucket: The name of the bucket for sotring images, e.g., prod.docker.registry.sagebase.org +# auth/token/realm: The Synapse auth' endpoint, e.g., https://repo-prod.prod.sagebase.org/docker/v1/bearerToken +# auth/token/service: docker.synapse.org or, for dev', dev-docker-registry.dev.sagebase.org +# notification/endpoints/url: The Synapse endpoint for notifications. See https://rest-docs.synapse.org/rest/POST/events.html +# notification/endpoints/headers/Authorization: A name/pwd pair used to authenticate with Synapse when sending events, in Basic Authorization format. +# +# Additional guidance here: https://distribution.github.io/distribution/about/deploying/ + +version: 0.1 +log: + level: info + formatter: text + fields: + service: registry +http: + addr: :443 + tls: + certificate: /etc/docker/registry/ssl/public.crt + key: /etc/docker/registry/ssl/privatekey.pem + +storage: + cache: + layerinfo: inmemory + s3: + region: us-east-1 + bucket: + encrypt: true + secure: true + v4auth: true + chunksize: 104857600 + rootdirectory: / + +auth: + token: + realm: https://repo-prod.prod.sagebase.org/docker/v1/bearerToken + service: docker.synapse.org + issuer: www.synapse.org + rootcertbundle: /etc/docker/registry/cert.pem + +notifications: + endpoints: + - name: Synapse + disabled: false + url: https://repo-prod.prod.sagebase.org/dockerRegistryListener/v1/events + headers: + Authorization: + - Basic base64-encoded-pair + timeout: 1m + threshold: 1 + backoff: 30s From 3e1938e12768e7c7151469b6948074b8524ee508 Mon Sep 17 00:00:00 2001 From: bhoff Date: Tue, 3 Sep 2024 17:58:55 -0700 Subject: [PATCH 03/37] PLFM-8554: Fixed whitespace --- docker_fargate/docker_fargate_stack.py | 4 ++-- sample-registry-config.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker_fargate/docker_fargate_stack.py b/docker_fargate/docker_fargate_stack.py index 06d5076..b34bdff 100644 --- a/docker_fargate/docker_fargate_stack.py +++ b/docker_fargate/docker_fargate_stack.py @@ -59,7 +59,7 @@ def __init__(self, scope: Construct, context: str, env: dict, vpc: ec2.Vpc, **kw } env_vars = get_container_env(env) - + entrypoint = "sh" command = "echo ${config.yml} | base64 --decode > /etc/docker/registry/config.yml" command = command + " && echo ${cert.pem} | base64 --decode > /etc/docker/registry/cert.pem" @@ -102,7 +102,7 @@ def __init__(self, scope: Construct, context: str, env: dict, vpc: ec2.Vpc, **kw ssl_policy=elbv2.SslPolicy.FORWARD_SECRECY_TLS12_RES, # Strong forward secrecy ciphers and TLS1.2 only. ) - if True: # enable/disable autoscaling + if True: # enable/disable autoscaling scalable_target = load_balanced_fargate_service.service.auto_scale_task_count( min_capacity=1, # Minimum capacity to scale to. Default: 1 max_capacity=4 # Maximum capacity to scale to. diff --git a/sample-registry-config.yml b/sample-registry-config.yml index e58dfe4..361e9fa 100644 --- a/sample-registry-config.yml +++ b/sample-registry-config.yml @@ -27,7 +27,7 @@ storage: layerinfo: inmemory s3: region: us-east-1 - bucket: + bucket: encrypt: true secure: true v4auth: true From 302b6f6ad67324af48a9fc76a3fbf3544fb1c3c1 Mon Sep 17 00:00:00 2001 From: bhoff Date: Tue, 3 Sep 2024 18:08:10 -0700 Subject: [PATCH 04/37] PLFM-8554: Typo --- docker_fargate/docker_fargate_stack.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker_fargate/docker_fargate_stack.py b/docker_fargate/docker_fargate_stack.py index b34bdff..1141dfe 100644 --- a/docker_fargate/docker_fargate_stack.py +++ b/docker_fargate/docker_fargate_stack.py @@ -68,7 +68,7 @@ def __init__(self, scope: Construct, context: str, env: dict, vpc: ec2.Vpc, **kw command = command + " && /entrypoint.sh /etc/docker/registry/config.yml" task_image_options = ecs_patterns.ApplicationLoadBalancedTaskImageOptions( - entrypoint=entrypoint, + entry_point=entrypoint, command=["-c", command], image=ecs.ContainerImage.from_registry(get_docker_image_name(env)), environment=env_vars, From 4cf6a2c24ae5602ee1641936e4d9ffc563fa6025 Mon Sep 17 00:00:00 2001 From: bhoff Date: Tue, 3 Sep 2024 18:12:35 -0700 Subject: [PATCH 05/37] PLFM-8554: Typo --- README.md | 6 ++---- docker_fargate/docker_fargate_stack.py | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e780aac..c36e853 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,7 @@ We use the [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/late In dev the secret is named `registry-dev-DockerFargateStack/dev/ecs` and in the prod stack, `registry-prod-DockerFargateStack/prod/ecs` -A secret is a collection of key-value pairs. For this application there are four pairs. The keys and their values are described below. Note that each value is base64-encoded. -This is because Secrets Manager doesn't handle line breaks when values are entered in the AWS console. +A secret is a collection of key-value pairs. For this application there are four pairs. The keys and their values are described below. Note that each value is base64-encoded. This is because Secrets Manager doesn't handle line breaks when values are entered in the AWS console. - `config.yml` The value should be a yml file based on `sample-registry-config.yml`, provided in this repository. @@ -25,8 +24,7 @@ This is because Secrets Manager doesn't handle line breaks when values are enter ### Missing Secrets Each new environment (dev/staging/prod/etc..) may require adding secrets. If a -secret is not created for the environment you may get an error with the following -stack trace.. +secret is not created for the environment you may get an error with the following stack trace: ``` Resource handler returned message: "Error occurred during operation 'ECS Deployment Circuit Breaker was triggered'." (RequestToken: d180e115-ba94-d8a2-acf9-abe17a3aaed9, HandlerErrorCode: GeneralServiceException) diff --git a/docker_fargate/docker_fargate_stack.py b/docker_fargate/docker_fargate_stack.py index 1141dfe..90800ba 100644 --- a/docker_fargate/docker_fargate_stack.py +++ b/docker_fargate/docker_fargate_stack.py @@ -68,7 +68,7 @@ def __init__(self, scope: Construct, context: str, env: dict, vpc: ec2.Vpc, **kw command = command + " && /entrypoint.sh /etc/docker/registry/config.yml" task_image_options = ecs_patterns.ApplicationLoadBalancedTaskImageOptions( - entry_point=entrypoint, + entry_point=[entrypoint], command=["-c", command], image=ecs.ContainerImage.from_registry(get_docker_image_name(env)), environment=env_vars, From 60ecf7ec938321ee923910b7d9c6f62a40163912 Mon Sep 17 00:00:00 2001 From: bhoff Date: Thu, 19 Sep 2024 14:46:08 -0700 Subject: [PATCH 06/37] PLFM-8554: build container with Synapse configuration baked-in --- .github/workflows/main.yml | 37 +++++++++++++ Dockerfile | 23 ++++++++ README.md | 11 +--- cdk.json | 4 +- docker_fargate/docker_fargate_stack.py | 39 +++++--------- resources/dev/config.yml | 48 +++++++++++++++++ .../dev/token_signing_key_public_cert.pem | 18 +++++++ resources/prod/config.yml | 48 +++++++++++++++++ .../prod/token_signing_key_public_cert.pem | 21 ++++++++ sample-registry-config.yml | 54 ------------------- startup.sh | 8 +++ 11 files changed, 221 insertions(+), 90 deletions(-) create mode 100644 Dockerfile create mode 100644 resources/dev/config.yml create mode 100644 resources/dev/token_signing_key_public_cert.pem create mode 100644 resources/prod/config.yml create mode 100644 resources/prod/token_signing_key_public_cert.pem delete mode 100644 sample-registry-config.yml create mode 100755 startup.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 899d125..388c576 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,6 +25,43 @@ jobs: - name: Run unit tests run: python -m pytest tests/ -s -v + build-registry-container: + needs: [tests] + if: ${{github.ref == 'refs/heads/dev'}} || ${{github.ref == 'refs/heads/prod'}} + steps: + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4.1.1 + with: + images: ghcr.io/${{ github.repository }} + + - name: Extract branch name + id: extract_branch + shell: bash + run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT + + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: create self-signed cert + run: > + openssl req -x509 -days 3650 -newkey rsa:2048 -sha256 + -nodes -keyout privatekey.pem -out certificate.pem + -subj "/C=US/ST=Seattle/L=WA/O=SageBionetworks/OU=IT/CN=synapse.org" + + - name: Build and push Docker image + uses: docker/build-push-action@v6.4.0 + with: + context: . + build-args: stack=${{ steps.extract_branch.outputs.branch }} + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + synth-test-dev: needs: tests uses: "./.github/workflows/synth-test.yml" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8d1a23a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +# +# Creates a configuration of the open source Docker registry +# suitable for using with Synapse +# +# +FROM registry:v2 +# stack is dev or prod +ARG stack=dev + +# switches between 'dev' and 'prod' +COPY resources/${stack}/config.yml /etc/docker/registry/config.yml +COPY resources/${stack}/token_signing_key_public_cert.pem /etc/docker/registry/token_signing_key_public_cert.pem +# the self-signed cert' and private key should be generated before running 'docker build' +# see the github workflow for an example of how to do this +COPY privatekey.pem /etc/docker/registry/ssl/privatekey.pem +COPY certificate.pem /etc/docker/registry/ssl/certificate.pem + +ENTRYPOINT ... +CMD ... + +COPY startup.sh /startup.sh + +CMD /startup.sh diff --git a/README.md b/README.md index c36e853..83254e3 100644 --- a/README.md +++ b/README.md @@ -10,15 +10,8 @@ We use the [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/late In dev the secret is named `registry-dev-DockerFargateStack/dev/ecs` and in the prod stack, `registry-prod-DockerFargateStack/prod/ecs` -A secret is a collection of key-value pairs. For this application there are four pairs. The keys and their values are described below. Note that each value is base64-encoded. This is because Secrets Manager doesn't handle line breaks when values are entered in the AWS console. - -- `config.yml` The value should be a yml file based on `sample-registry-config.yml`, provided in this repository. - -- `public.crt` The registry domain certificate, described [here](https://distribution.github.io/distribution/about/deploying/). - -- `privatekey.pem` The private key for the above certificate, in .pem format. - -- `cert.pem` The certificate part of the RSA key pair used by Synapse to sign JWTs, in .pem format. +A secret is a collection of key-value pairs. For this application there is just one pair. The key should be `notification-auth` and the value is the +Base64 encoded "Basic auth" credentials which are a shared-secret with Synapse as the event notification recipient. ### Missing Secrets diff --git a/cdk.json b/cdk.json index 96f3d2a..be205fd 100644 --- a/cdk.json +++ b/cdk.json @@ -31,7 +31,7 @@ "aws-cn" ], "dev": { - "IMAGE_PATH_AND_TAG": "registry:2", + "IMAGE_PATH_AND_TAG": "sage-bionetworks/synapse-docker-registry:dev", "AWS_DEFAULT_REGION": "us-east-1", "PORT": "443", "CONTAINER_ENV": { @@ -45,7 +45,7 @@ "ACM_CERT_ARN": "arn:aws:acm:us-east-1:449435941126:certificate/bbd59a26-ad30-4b74-ad2d-194241801b22" }, "prod": { - "IMAGE_PATH_AND_TAG": "registry:2", + "IMAGE_PATH_AND_TAG": "sage-bionetworks/synapse-docker-registry:prod", "AWS_DEFAULT_REGION": "us-east-1", "PORT": "443", "CONTAINER_ENV": { diff --git a/docker_fargate/docker_fargate_stack.py b/docker_fargate/docker_fargate_stack.py index 90800ba..24c59bd 100644 --- a/docker_fargate/docker_fargate_stack.py +++ b/docker_fargate/docker_fargate_stack.py @@ -12,6 +12,8 @@ import aws_cdk.aws_certificatemanager as cm import aws_cdk.aws_secretsmanager as sm from constructs import Construct +from importlib import resources.files as files +from . import resources ACM_CERT_ARN_CONTEXT = "ACM_CERT_ARN" IMAGE_PATH_AND_TAG_CONTEXT = "IMAGE_PATH_AND_TAG" @@ -60,16 +62,7 @@ def __init__(self, scope: Construct, context: str, env: dict, vpc: ec2.Vpc, **kw env_vars = get_container_env(env) - entrypoint = "sh" - command = "echo ${config.yml} | base64 --decode > /etc/docker/registry/config.yml" - command = command + " && echo ${cert.pem} | base64 --decode > /etc/docker/registry/cert.pem" - command = command + " && echo ${public.crt} | base64 --decode > /etc/docker/registry/ssl/public.crt" - command = command + " && echo ${privatekey.pem} | base64 --decode > /etc/docker/registry/ssl/privatekey.pem" - command = command + " && /entrypoint.sh /etc/docker/registry/config.yml" - task_image_options = ecs_patterns.ApplicationLoadBalancedTaskImageOptions( - entry_point=[entrypoint], - command=["-c", command], image=ecs.ContainerImage.from_registry(get_docker_image_name(env)), environment=env_vars, secrets = secrets, @@ -102,24 +95,20 @@ def __init__(self, scope: Construct, context: str, env: dict, vpc: ec2.Vpc, **kw ssl_policy=elbv2.SslPolicy.FORWARD_SECRECY_TLS12_RES, # Strong forward secrecy ciphers and TLS1.2 only. ) - if True: # enable/disable autoscaling - scalable_target = load_balanced_fargate_service.service.auto_scale_task_count( - min_capacity=1, # Minimum capacity to scale to. Default: 1 - max_capacity=4 # Maximum capacity to scale to. - ) - - # Add more capacity when CPU utilization reaches 50% - scalable_target.scale_on_cpu_utilization("CpuScaling", - target_utilization_percent=50 - ) + scalable_target = load_balanced_fargate_service.service.auto_scale_task_count( + min_capacity=1, # Minimum capacity to scale to. Default: 1 + max_capacity=4 # Maximum capacity to scale to. + ) - # Add more capacity when memory utilization reaches 50% - scalable_target.scale_on_memory_utilization("MemoryScaling", - target_utilization_percent=50 - ) + # Add more capacity when CPU utilization reaches 50% + scalable_target.scale_on_cpu_utilization("CpuScaling", + target_utilization_percent=50 + ) - # Other metrics to drive scaling are discussed here: - # https://docs.aws.amazon.com/cdk/api/v1/python/aws_cdk.aws_autoscaling/README.html + # Add more capacity when memory utilization reaches 50% + scalable_target.scale_on_memory_utilization("MemoryScaling", + target_utilization_percent=50 + ) # Tag all resources in this Stack's scope with context tags for key, value in env.get(config.TAGS_CONTEXT).items(): diff --git a/resources/dev/config.yml b/resources/dev/config.yml new file mode 100644 index 0000000..bac9e84 --- /dev/null +++ b/resources/dev/config.yml @@ -0,0 +1,48 @@ +# +# Configuration file for Docker registry +# https://distribution.github.io/distribution/about/deploying/ +# +# Before using, notifications/endpoints/headers/Authorization must be filled in +# +version: 0.1 +log: + level: info + formatter: text + fields: + service: registry +http: + addr: :443 + tls: + certificate: /etc/docker/registry/ssl/certificate.pem + key: /etc/docker/registry/ssl/privatekey.pem + +storage: + cache: + layerinfo: inmemory + s3: + region: us-east-1 + bucket: dev-docker-registry.sagebase.org + encrypt: true + secure: true + v4auth: true + chunksize: 104857600 + rootdirectory: / + +auth: + token: + realm: https://repo-dev.dev.sagebase.org/docker/v1/bearerToken + service: dev-docker-registry.dev.sagebase.org + issuer: www.synapse.org + rootcertbundle: /etc/docker/registry/token_signing_key_public_cert.pem + +notifications: + endpoints: + - name: Synapse + disabled: false + url: https://repo-dev.dev.sagebase.org/dockerRegistryListener/v1/events + headers: + Authorization: + - Basic notification-auth + timeout: 1m + threshold: 1 + backoff: 30s diff --git a/resources/dev/token_signing_key_public_cert.pem b/resources/dev/token_signing_key_public_cert.pem new file mode 100644 index 0000000..b64cd7b --- /dev/null +++ b/resources/dev/token_signing_key_public_cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC+zCCAqGgAwIBAgIJAI+Kok0VfNbJMAkGByqGSM49BAEwgYgxCzAJBgNVBAYT +AlVTMQswCQYDVQQIEwJXQTEQMA4GA1UEBxMHU2VhdHRsZTENMAsGA1UEChMEU2Fn +ZTELMAkGA1UECxMCUEwxGDAWBgNVBAMTD3d3dy5zeW5hcHNlLm9yZzEkMCIGCSqG +SIb3DQEJARYVcGxhdGZvcm1Ac2FnZWJhc2Uub3JnMCAXDTE2MDYxMjE2NTU0M1oY +DzIxMTYwNTE5MTY1NTQzWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAw +DgYDVQQHEwdTZWF0dGxlMQ0wCwYDVQQKEwRTYWdlMQswCQYDVQQLEwJQTDEYMBYG +A1UEAxMPd3d3LnN5bmFwc2Uub3JnMSQwIgYJKoZIhvcNAQkBFhVwbGF0Zm9ybUBz +YWdlYmFzZS5vcmcwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ5e3PRzLYweP78 +cDPDwPMc6XhuTaKgKtmDEsqS13DmBXt8c65rt3owdJ7JCxHJYxON91Eg9sBQhT2K +8yyOf+PBo4HwMIHtMB0GA1UdDgQWBBQXzi7VyAjmc2nucRtLQaAkGL7RWTCBvQYD +VR0jBIG1MIGygBQXzi7VyAjmc2nucRtLQaAkGL7RWaGBjqSBizCBiDELMAkGA1UE +BhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ0wCwYDVQQKEwRT +YWdlMQswCQYDVQQLEwJQTDEYMBYGA1UEAxMPd3d3LnN5bmFwc2Uub3JnMSQwIgYJ +KoZIhvcNAQkBFhVwbGF0Zm9ybUBzYWdlYmFzZS5vcmeCCQCPiqJNFXzWyTAMBgNV +HRMEBTADAQH/MAkGByqGSM49BAEDSQAwRgIhAI5mLcT6D++3oTbjdNhKs6SI3ijO +mKf6Xe++KzE8JJknAiEAq17eb0ZG0Eh/3hKk+9FREUAZ2iub3HPjwD3QPA+bL1c= +-----END CERTIFICATE----- diff --git a/resources/prod/config.yml b/resources/prod/config.yml new file mode 100644 index 0000000..16f2bfa --- /dev/null +++ b/resources/prod/config.yml @@ -0,0 +1,48 @@ +# +# Configuration file for Docker registry +# https://distribution.github.io/distribution/about/deploying/ +# +# Before using, notifications/endpoints/headers/Authorization must be filled in +# +version: 0.1 +log: + level: info + formatter: text + fields: + service: registry +http: + addr: :443 + tls: + certificate: /etc/docker/registry/ssl/public.crt + key: /etc/docker/registry/ssl/privatekey.pem + +storage: + cache: + layerinfo: inmemory + s3: + region: us-east-1 + bucket: prod.docker.registry.sagebase.org + encrypt: true + secure: true + v4auth: true + chunksize: 104857600 + rootdirectory: / + +auth: + token: + realm: https://repo-prod.prod.sagebase.org/docker/v1/bearerToken + service: docker.synapse.org + issuer: www.synapse.org + rootcertbundle: /etc/docker/registry/token_signing_key_public_cert.pem + +notifications: + endpoints: + - name: Synapse + disabled: false + url: https://repo-prod.prod.sagebase.org/dockerRegistryListener/v1/events + headers: + Authorization: + - Basic notification-auth + timeout: 1m + threshold: 1 + backoff: 30s diff --git a/resources/prod/token_signing_key_public_cert.pem b/resources/prod/token_signing_key_public_cert.pem new file mode 100644 index 0000000..712f231 --- /dev/null +++ b/resources/prod/token_signing_key_public_cert.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDYjCCAwmgAwIBAgIJAPjAfVg1hZLeMAkGByqGSM49BAEwgaoxCzAJBgNVBAYT +AlVTMQswCQYDVQQIEwJXQTEQMA4GA1UEBxMHU2VhdHRsZTEZMBcGA1UEChMQU2Fn +ZSBCaW9uZXR3b3JrczEhMB8GA1UECxMYU3luYXBzZSBFbmdpbmVlcmluZyBUZWFt +MRgwFgYDVQQDEw93d3cuc3luYXBzZS5vcmcxJDAiBgkqhkiG9w0BCQEWFXBsYXRm +b3JtQHNhZ2ViYXNlLm9yZzAgFw0xNjA2MTcxNjAzMDZaGA8yMTE2MDUyNDE2MDMw +NlowgaoxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJXQTEQMA4GA1UEBxMHU2VhdHRs +ZTEZMBcGA1UEChMQU2FnZSBCaW9uZXR3b3JrczEhMB8GA1UECxMYU3luYXBzZSBF +bmdpbmVlcmluZyBUZWFtMRgwFgYDVQQDEw93d3cuc3luYXBzZS5vcmcxJDAiBgkq +hkiG9w0BCQEWFXBsYXRmb3JtQHNhZ2ViYXNlLm9yZzBZMBMGByqGSM49AgEGCCqG +SM49AwEHA0IABH+L4hYeqS3yNtSR4PX6vrd/d4DXP4Dcxsa6+ztVXT1GRXpnVzzS +qTMqDT8caOyXgoIMMQyQS1scHbs5J4NDnSmjggETMIIBDzAdBgNVHQ4EFgQUzX4k +DwoYtxcxO9Ag6smecR+MtfEwgd8GA1UdIwSB1zCB1IAUzX4kDwoYtxcxO9Ag6sme +cR+MtfGhgbCkga0wgaoxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJXQTEQMA4GA1UE +BxMHU2VhdHRsZTEZMBcGA1UEChMQU2FnZSBCaW9uZXR3b3JrczEhMB8GA1UECxMY +U3luYXBzZSBFbmdpbmVlcmluZyBUZWFtMRgwFgYDVQQDEw93d3cuc3luYXBzZS5v +cmcxJDAiBgkqhkiG9w0BCQEWFXBsYXRmb3JtQHNhZ2ViYXNlLm9yZ4IJAPjAfVg1 +hZLeMAwGA1UdEwQFMAMBAf8wCQYHKoZIzj0EAQNIADBFAiAa9iX8YT8agglhE1DW +hBIC5tqUa+pAZawmTZWgsMm4lAIhAPCAlfHaho9OsebE2PMriQm4DQhgtQve0qjO +7IxEfJZg +-----END CERTIFICATE----- diff --git a/sample-registry-config.yml b/sample-registry-config.yml deleted file mode 100644 index 361e9fa..0000000 --- a/sample-registry-config.yml +++ /dev/null @@ -1,54 +0,0 @@ -# -# sample config.yml for Docker registry -# -# To use, complete the following fields: -# storage/s3:bucket: The name of the bucket for sotring images, e.g., prod.docker.registry.sagebase.org -# auth/token/realm: The Synapse auth' endpoint, e.g., https://repo-prod.prod.sagebase.org/docker/v1/bearerToken -# auth/token/service: docker.synapse.org or, for dev', dev-docker-registry.dev.sagebase.org -# notification/endpoints/url: The Synapse endpoint for notifications. See https://rest-docs.synapse.org/rest/POST/events.html -# notification/endpoints/headers/Authorization: A name/pwd pair used to authenticate with Synapse when sending events, in Basic Authorization format. -# -# Additional guidance here: https://distribution.github.io/distribution/about/deploying/ - -version: 0.1 -log: - level: info - formatter: text - fields: - service: registry -http: - addr: :443 - tls: - certificate: /etc/docker/registry/ssl/public.crt - key: /etc/docker/registry/ssl/privatekey.pem - -storage: - cache: - layerinfo: inmemory - s3: - region: us-east-1 - bucket: - encrypt: true - secure: true - v4auth: true - chunksize: 104857600 - rootdirectory: / - -auth: - token: - realm: https://repo-prod.prod.sagebase.org/docker/v1/bearerToken - service: docker.synapse.org - issuer: www.synapse.org - rootcertbundle: /etc/docker/registry/cert.pem - -notifications: - endpoints: - - name: Synapse - disabled: false - url: https://repo-prod.prod.sagebase.org/dockerRegistryListener/v1/events - headers: - Authorization: - - Basic base64-encoded-pair - timeout: 1m - threshold: 1 - backoff: 30s diff --git a/startup.sh b/startup.sh new file mode 100755 index 0000000..43aa2d4 --- /dev/null +++ b/startup.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# Inject notification listener authorization credentials into config.yml +sed -i "s/notification-auth/$notification-auth/g" /etc/docker/registry/config.yml + +# this assumed a particular start-up for the container registry +# if the command changes in future versions, this will have to be updated too +/entrypoint.sh /etc/docker/registry/config.yml From d33a6ce9f7a2decbefec1605219dbc6e9d8d8d75 Mon Sep 17 00:00:00 2001 From: bhoff Date: Thu, 19 Sep 2024 14:49:10 -0700 Subject: [PATCH 07/37] PLFM-8554: fixed bugs in action, python, and whitespace --- .github/workflows/main.yml | 11 ++++++----- README.md | 2 +- docker_fargate/docker_fargate_stack.py | 2 -- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 388c576..c87f3f3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,7 +27,8 @@ jobs: build-registry-container: needs: [tests] - if: ${{github.ref == 'refs/heads/dev'}} || ${{github.ref == 'refs/heads/prod'}} + if: ${{github.ref == 'refs/heads/dev'}} || ${{github.ref == 'refs/heads/prod'}} + runs-on: ubuntu-latest steps: - name: Extract metadata (tags, labels) for Docker id: meta @@ -39,20 +40,20 @@ jobs: id: extract_branch shell: bash run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT - + - name: Login to GitHub Container Registry uses: docker/login-action@v2 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - + - name: create self-signed cert run: > - openssl req -x509 -days 3650 -newkey rsa:2048 -sha256 + openssl req -x509 -days 3650 -newkey rsa:2048 -sha256 -nodes -keyout privatekey.pem -out certificate.pem -subj "/C=US/ST=Seattle/L=WA/O=SageBionetworks/OU=IT/CN=synapse.org" - + - name: Build and push Docker image uses: docker/build-push-action@v6.4.0 with: diff --git a/README.md b/README.md index 83254e3..d1b5878 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ We use the [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/late In dev the secret is named `registry-dev-DockerFargateStack/dev/ecs` and in the prod stack, `registry-prod-DockerFargateStack/prod/ecs` -A secret is a collection of key-value pairs. For this application there is just one pair. The key should be `notification-auth` and the value is the +A secret is a collection of key-value pairs. For this application there is just one pair. The key should be `notification-auth` and the value is the Base64 encoded "Basic auth" credentials which are a shared-secret with Synapse as the event notification recipient. diff --git a/docker_fargate/docker_fargate_stack.py b/docker_fargate/docker_fargate_stack.py index 24c59bd..c28980d 100644 --- a/docker_fargate/docker_fargate_stack.py +++ b/docker_fargate/docker_fargate_stack.py @@ -12,8 +12,6 @@ import aws_cdk.aws_certificatemanager as cm import aws_cdk.aws_secretsmanager as sm from constructs import Construct -from importlib import resources.files as files -from . import resources ACM_CERT_ARN_CONTEXT = "ACM_CERT_ARN" IMAGE_PATH_AND_TAG_CONTEXT = "IMAGE_PATH_AND_TAG" From 57d556ba5f54c82ae696b88e8d05de80a9afb4cc Mon Sep 17 00:00:00 2001 From: bhoff Date: Thu, 19 Sep 2024 17:09:29 -0700 Subject: [PATCH 08/37] PLFM-8554: added checkout to docker build job --- .github/workflows/main.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c87f3f3..f4fcdcf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,6 +30,9 @@ jobs: if: ${{github.ref == 'refs/heads/dev'}} || ${{github.ref == 'refs/heads/prod'}} runs-on: ubuntu-latest steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@v4.1.1 @@ -77,7 +80,7 @@ jobs: cdk-deploy-dev: if: ${{github.ref == 'refs/heads/dev'}} - needs: [tests, synth-test-dev] + needs: [tests, synth-test-dev, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: @@ -86,7 +89,7 @@ jobs: cdk-deploy-prod: if: ${{github.ref == 'refs/heads/prod'}} - needs: [tests, synth-test-prod] + needs: [tests, synth-test-prod, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: From 9661961b28f1df8b5867bb16d86eed0e324795e6 Mon Sep 17 00:00:00 2001 From: bhoff Date: Thu, 19 Sep 2024 17:21:38 -0700 Subject: [PATCH 09/37] PLFM-8554: added Docer linting and fixed Dockerfile --- .dockerfilelintrc | 8 ++++++++ .pre-commit-config.yaml | 4 ++++ Dockerfile | 7 ++----- 3 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 .dockerfilelintrc diff --git a/.dockerfilelintrc b/.dockerfilelintrc new file mode 100644 index 0000000..d4595a7 --- /dev/null +++ b/.dockerfilelintrc @@ -0,0 +1,8 @@ +--- +# https://github.com/replicatedhq/dockerfilelint +rules: + apt-get-upgrade: off + apt-get-update_require_install: off + apt-get_recommends: off + apt-get_missing_rm: off + sudo_usage: off diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 014202e..9e9dd75 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -36,3 +36,7 @@ repos: hooks: - id: check-github-workflows - id: check-github-actions + - repo: https://github.com/pryorda/dockerfilelint-precommit-hooks + rev: v0.1.0 + hooks: + - id: dockerfilelint diff --git a/Dockerfile b/Dockerfile index 8d1a23a..4d5e555 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ # suitable for using with Synapse # # -FROM registry:v2 +FROM registry:2 # stack is dev or prod ARG stack=dev @@ -15,9 +15,6 @@ COPY resources/${stack}/token_signing_key_public_cert.pem /etc/docker/registry/t COPY privatekey.pem /etc/docker/registry/ssl/privatekey.pem COPY certificate.pem /etc/docker/registry/ssl/certificate.pem -ENTRYPOINT ... -CMD ... - COPY startup.sh /startup.sh -CMD /startup.sh +CMD ["/startup.sh"] From dbf62128c155d4dc6f2c10b76ec467eb2165e89c Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 08:05:19 -0700 Subject: [PATCH 10/37] PLFM-8554: removed dash from env var name; chnaged CMD to ENTRYPOINT in Dockerfile --- Dockerfile | 2 +- README.md | 2 +- resources/dev/config.yml | 2 +- resources/prod/config.yml | 2 +- startup.sh | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4d5e555..4046524 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,4 +17,4 @@ COPY certificate.pem /etc/docker/registry/ssl/certificate.pem COPY startup.sh /startup.sh -CMD ["/startup.sh"] +ENTRYPOINT ["/startup.sh"] diff --git a/README.md b/README.md index d1b5878..a39141d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ We use the [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/late In dev the secret is named `registry-dev-DockerFargateStack/dev/ecs` and in the prod stack, `registry-prod-DockerFargateStack/prod/ecs` -A secret is a collection of key-value pairs. For this application there is just one pair. The key should be `notification-auth` and the value is the +A secret is a collection of key-value pairs. For this application there is just one pair. The key should be `notification_auth` and the value is the Base64 encoded "Basic auth" credentials which are a shared-secret with Synapse as the event notification recipient. diff --git a/resources/dev/config.yml b/resources/dev/config.yml index bac9e84..f5955b1 100644 --- a/resources/dev/config.yml +++ b/resources/dev/config.yml @@ -42,7 +42,7 @@ notifications: url: https://repo-dev.dev.sagebase.org/dockerRegistryListener/v1/events headers: Authorization: - - Basic notification-auth + - Basic notification_auth timeout: 1m threshold: 1 backoff: 30s diff --git a/resources/prod/config.yml b/resources/prod/config.yml index 16f2bfa..a6a0832 100644 --- a/resources/prod/config.yml +++ b/resources/prod/config.yml @@ -42,7 +42,7 @@ notifications: url: https://repo-prod.prod.sagebase.org/dockerRegistryListener/v1/events headers: Authorization: - - Basic notification-auth + - Basic notification_auth timeout: 1m threshold: 1 backoff: 30s diff --git a/startup.sh b/startup.sh index 43aa2d4..034b386 100755 --- a/startup.sh +++ b/startup.sh @@ -1,7 +1,7 @@ #!/bin/bash # Inject notification listener authorization credentials into config.yml -sed -i "s/notification-auth/$notification-auth/g" /etc/docker/registry/config.yml +sed -i "s/notification_auth/$notification_auth/g" /etc/docker/registry/config.yml # this assumed a particular start-up for the container registry # if the command changes in future versions, this will have to be updated too From e980b6076198a4822bea97d37d808da40460d4e4 Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 08:20:39 -0700 Subject: [PATCH 11/37] PLFM-8554: changed bash to sh in startup.sh --- startup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/startup.sh b/startup.sh index 034b386..dad0621 100755 --- a/startup.sh +++ b/startup.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # Inject notification listener authorization credentials into config.yml sed -i "s/notification_auth/$notification_auth/g" /etc/docker/registry/config.yml From 3eecee470220fe0362cb6b2af7c3954da900714b Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 14:19:00 -0700 Subject: [PATCH 12/37] PLFM-8554: Updated CIDR range; updated GitHub workflow --- .github/workflows/main.yml | 48 +++++++++---------- README.md | 7 ++- cdk.json | 8 ++-- .../dev/token_signing_key_public_cert.pem | 35 +++++++------- 4 files changed, 51 insertions(+), 47 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f4fcdcf..c01122d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,6 +9,9 @@ on: concurrency: ci-${{ github.ref }} +env: + branch: ${{ github.head_ref || github.ref_name }} + jobs: tests: runs-on: ubuntu-latest @@ -25,9 +28,19 @@ jobs: - name: Run unit tests run: python -m pytest tests/ -s -v + # make sure tests pass for both dev and prod stacks + synth-test: + needs: tests + strategy: + matrix: + stack: ['dev', 'prod'] + uses: "./.github/workflows/synth-test.yml" + with: + CONTEXT: ${{ matrix.stack }} + build-registry-container: - needs: [tests] - if: ${{github.ref == 'refs/heads/dev'}} || ${{github.ref == 'refs/heads/prod'}} + needs: [tests, synth-test] + if: ${{env.branch == 'dev'}} || ${{env.branch == 'prod'}} runs-on: ubuntu-latest steps: - name: Checkout repository @@ -39,11 +52,6 @@ jobs: with: images: ghcr.io/${{ github.repository }} - - name: Extract branch name - id: extract_branch - shell: bash - run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT - - name: Login to GitHub Container Registry uses: docker/login-action@v2 with: @@ -61,37 +69,25 @@ jobs: uses: docker/build-push-action@v6.4.0 with: context: . - build-args: stack=${{ steps.extract_branch.outputs.branch }} + build-args: stack=${{ env.branch }} push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - synth-test-dev: - needs: tests - uses: "./.github/workflows/synth-test.yml" - with: - CONTEXT: dev - - synth-test-prod: - needs: tests - uses: "./.github/workflows/synth-test.yml" - with: - CONTEXT: prod - cdk-deploy-dev: - if: ${{github.ref == 'refs/heads/dev'}} - needs: [tests, synth-test-dev, build-registry-container] + if: ${{env.branch == 'dev'}} + needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: - CONTEXT: dev + CONTEXT: ${{ env.branch }} ROLE_TO_ASSUME: arn:aws:iam::449435941126:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry cdk-deploy-prod: - if: ${{github.ref == 'refs/heads/prod'}} - needs: [tests, synth-test-prod, build-registry-container] + if: ${{env.branch == 'prod'}} + needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: - CONTEXT: prod + CONTEXT: ${{ env.branch }} ROLE_TO_ASSUME: arn:aws:iam::325565585839:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry diff --git a/README.md b/README.md index a39141d..c02e80c 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,15 @@ In dev the secret is named `registry-dev-DockerFargateStack/dev/ecs` and in the A secret is a collection of key-value pairs. For this application there is just one pair. The key should be `notification_auth` and the value is the Base64 encoded "Basic auth" credentials which are a shared-secret with Synapse as the event notification recipient. +### Registry container +We use the open source Docker `registry`, available on DockerHub. This container requires several configuration files to be mounted. +To achieve this cleanly, we embed the files into our own copy of the registry, published to GitHub as `ghcr.io/synapse-docker-registry`, making two versions under +two different tags, `dev` and `prod`, each with its own configuration. Note that the configuration files we add contain no secrets. The only required secret (the event listener +authorization credential) is inserted into the registry configuration file at the time the container is started up. ### Missing Secrets -Each new environment (dev/staging/prod/etc..) may require adding secrets. If a +Each new environment (dev/staging/prod/etc..) requires adding secrets in AWS Secrets Manager. If a secret is not created for the environment you may get an error with the following stack trace: ``` diff --git a/cdk.json b/cdk.json index be205fd..8c24c57 100644 --- a/cdk.json +++ b/cdk.json @@ -31,7 +31,7 @@ "aws-cn" ], "dev": { - "IMAGE_PATH_AND_TAG": "sage-bionetworks/synapse-docker-registry:dev", + "IMAGE_PATH_AND_TAG": "ghcr.io/sage-bionetworks/synapse-docker-registry:dev", "AWS_DEFAULT_REGION": "us-east-1", "PORT": "443", "CONTAINER_ENV": { @@ -41,11 +41,11 @@ "OwnerEmail": "synapseeng@sagebase.org" }, "STACK_NAME_PREFIX": "registry-dev", - "VPC_CIDR": "172.33.0.0/24", + "VPC_CIDR": "172.30.0.0/24", "ACM_CERT_ARN": "arn:aws:acm:us-east-1:449435941126:certificate/bbd59a26-ad30-4b74-ad2d-194241801b22" }, "prod": { - "IMAGE_PATH_AND_TAG": "sage-bionetworks/synapse-docker-registry:prod", + "IMAGE_PATH_AND_TAG": "ghcr.io/sage-bionetworks/synapse-docker-registry:prod", "AWS_DEFAULT_REGION": "us-east-1", "PORT": "443", "CONTAINER_ENV": { @@ -55,7 +55,7 @@ "OwnerEmail": "synapseeng@sagebase.org" }, "STACK_NAME_PREFIX": "registry-prod", - "VPC_CIDR": "172.33.1.0/24", + "VPC_CIDR": "172.30.1.0/24", "ACM_CERT_ARN": "arn:aws:acm:us-east-1:325565585839:certificate/7c42c355-3d69-4537-a5e6-428212db646f" } } diff --git a/resources/dev/token_signing_key_public_cert.pem b/resources/dev/token_signing_key_public_cert.pem index b64cd7b..712f231 100644 --- a/resources/dev/token_signing_key_public_cert.pem +++ b/resources/dev/token_signing_key_public_cert.pem @@ -1,18 +1,21 @@ -----BEGIN CERTIFICATE----- -MIIC+zCCAqGgAwIBAgIJAI+Kok0VfNbJMAkGByqGSM49BAEwgYgxCzAJBgNVBAYT -AlVTMQswCQYDVQQIEwJXQTEQMA4GA1UEBxMHU2VhdHRsZTENMAsGA1UEChMEU2Fn -ZTELMAkGA1UECxMCUEwxGDAWBgNVBAMTD3d3dy5zeW5hcHNlLm9yZzEkMCIGCSqG -SIb3DQEJARYVcGxhdGZvcm1Ac2FnZWJhc2Uub3JnMCAXDTE2MDYxMjE2NTU0M1oY -DzIxMTYwNTE5MTY1NTQzWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAw -DgYDVQQHEwdTZWF0dGxlMQ0wCwYDVQQKEwRTYWdlMQswCQYDVQQLEwJQTDEYMBYG -A1UEAxMPd3d3LnN5bmFwc2Uub3JnMSQwIgYJKoZIhvcNAQkBFhVwbGF0Zm9ybUBz -YWdlYmFzZS5vcmcwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ5e3PRzLYweP78 -cDPDwPMc6XhuTaKgKtmDEsqS13DmBXt8c65rt3owdJ7JCxHJYxON91Eg9sBQhT2K -8yyOf+PBo4HwMIHtMB0GA1UdDgQWBBQXzi7VyAjmc2nucRtLQaAkGL7RWTCBvQYD -VR0jBIG1MIGygBQXzi7VyAjmc2nucRtLQaAkGL7RWaGBjqSBizCBiDELMAkGA1UE -BhMCVVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ0wCwYDVQQKEwRT -YWdlMQswCQYDVQQLEwJQTDEYMBYGA1UEAxMPd3d3LnN5bmFwc2Uub3JnMSQwIgYJ -KoZIhvcNAQkBFhVwbGF0Zm9ybUBzYWdlYmFzZS5vcmeCCQCPiqJNFXzWyTAMBgNV -HRMEBTADAQH/MAkGByqGSM49BAEDSQAwRgIhAI5mLcT6D++3oTbjdNhKs6SI3ijO -mKf6Xe++KzE8JJknAiEAq17eb0ZG0Eh/3hKk+9FREUAZ2iub3HPjwD3QPA+bL1c= +MIIDYjCCAwmgAwIBAgIJAPjAfVg1hZLeMAkGByqGSM49BAEwgaoxCzAJBgNVBAYT +AlVTMQswCQYDVQQIEwJXQTEQMA4GA1UEBxMHU2VhdHRsZTEZMBcGA1UEChMQU2Fn +ZSBCaW9uZXR3b3JrczEhMB8GA1UECxMYU3luYXBzZSBFbmdpbmVlcmluZyBUZWFt +MRgwFgYDVQQDEw93d3cuc3luYXBzZS5vcmcxJDAiBgkqhkiG9w0BCQEWFXBsYXRm +b3JtQHNhZ2ViYXNlLm9yZzAgFw0xNjA2MTcxNjAzMDZaGA8yMTE2MDUyNDE2MDMw +NlowgaoxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJXQTEQMA4GA1UEBxMHU2VhdHRs +ZTEZMBcGA1UEChMQU2FnZSBCaW9uZXR3b3JrczEhMB8GA1UECxMYU3luYXBzZSBF +bmdpbmVlcmluZyBUZWFtMRgwFgYDVQQDEw93d3cuc3luYXBzZS5vcmcxJDAiBgkq +hkiG9w0BCQEWFXBsYXRmb3JtQHNhZ2ViYXNlLm9yZzBZMBMGByqGSM49AgEGCCqG +SM49AwEHA0IABH+L4hYeqS3yNtSR4PX6vrd/d4DXP4Dcxsa6+ztVXT1GRXpnVzzS +qTMqDT8caOyXgoIMMQyQS1scHbs5J4NDnSmjggETMIIBDzAdBgNVHQ4EFgQUzX4k +DwoYtxcxO9Ag6smecR+MtfEwgd8GA1UdIwSB1zCB1IAUzX4kDwoYtxcxO9Ag6sme +cR+MtfGhgbCkga0wgaoxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJXQTEQMA4GA1UE +BxMHU2VhdHRsZTEZMBcGA1UEChMQU2FnZSBCaW9uZXR3b3JrczEhMB8GA1UECxMY +U3luYXBzZSBFbmdpbmVlcmluZyBUZWFtMRgwFgYDVQQDEw93d3cuc3luYXBzZS5v +cmcxJDAiBgkqhkiG9w0BCQEWFXBsYXRmb3JtQHNhZ2ViYXNlLm9yZ4IJAPjAfVg1 +hZLeMAwGA1UdEwQFMAMBAf8wCQYHKoZIzj0EAQNIADBFAiAa9iX8YT8agglhE1DW +hBIC5tqUa+pAZawmTZWgsMm4lAIhAPCAlfHaho9OsebE2PMriQm4DQhgtQve0qjO +7IxEfJZg -----END CERTIFICATE----- From f7344dcd3101ddaf6f0f559d2c4fc480a6e906b5 Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 14:22:35 -0700 Subject: [PATCH 13/37] PLFM-8554: updated GitHub workflow --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c01122d..faf1392 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,8 +10,8 @@ on: concurrency: ci-${{ github.ref }} env: - branch: ${{ github.head_ref || github.ref_name }} - + branch: ${{ github.head_ref || github.ref_name }} + jobs: tests: runs-on: ubuntu-latest @@ -40,7 +40,7 @@ jobs: build-registry-container: needs: [tests, synth-test] - if: ${{env.branch == 'dev'}} || ${{env.branch == 'prod'}} + if: ${{ env.branch }} == 'dev' || ${{ env.branch }} == 'prod' runs-on: ubuntu-latest steps: - name: Checkout repository From 1c4abc26c9b3d8205a9cb46cb087c4c4bf69164b Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 14:25:47 -0700 Subject: [PATCH 14/37] PLFM-8554: fixed 'if' in workflow --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index faf1392..b1c5ab3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,7 +40,7 @@ jobs: build-registry-container: needs: [tests, synth-test] - if: ${{ env.branch }} == 'dev' || ${{ env.branch }} == 'prod' + if: $branch == 'dev' || $branch == 'prod' runs-on: ubuntu-latest steps: - name: Checkout repository From 539aa60d8184beaf55659038dd1754f19d5a63b2 Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 14:27:28 -0700 Subject: [PATCH 15/37] PLFM-8554: fixed references to env.branch in workflow --- .github/workflows/main.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b1c5ab3..cda775c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -69,25 +69,25 @@ jobs: uses: docker/build-push-action@v6.4.0 with: context: . - build-args: stack=${{ env.branch }} + build-args: stack=$branch push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cdk-deploy-dev: - if: ${{env.branch == 'dev'}} + if: $branch == 'dev' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: - CONTEXT: ${{ env.branch }} + CONTEXT: $branch ROLE_TO_ASSUME: arn:aws:iam::449435941126:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry cdk-deploy-prod: - if: ${{env.branch == 'prod'}} + if: $branch == 'prod' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: - CONTEXT: ${{ env.branch }} + CONTEXT: $branch ROLE_TO_ASSUME: arn:aws:iam::325565585839:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry From a5346ecafc75fd32d605fe2f67a1d78376a05ba4 Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 14:30:28 -0700 Subject: [PATCH 16/37] PLFM-8554: -> .branch --- .github/workflows/main.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cda775c..26578f4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,7 +40,7 @@ jobs: build-registry-container: needs: [tests, synth-test] - if: $branch == 'dev' || $branch == 'prod' + if: $env.branch == 'dev' || $env.branch == 'prod' runs-on: ubuntu-latest steps: - name: Checkout repository @@ -69,25 +69,25 @@ jobs: uses: docker/build-push-action@v6.4.0 with: context: . - build-args: stack=$branch + build-args: stack=$env.branch push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cdk-deploy-dev: - if: $branch == 'dev' + if: env.branch == 'dev' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: - CONTEXT: $branch + CONTEXT: $env.branch ROLE_TO_ASSUME: arn:aws:iam::449435941126:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry cdk-deploy-prod: - if: $branch == 'prod' + if: env.branch == 'prod' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: - CONTEXT: $branch + CONTEXT: $env.branch ROLE_TO_ASSUME: arn:aws:iam::325565585839:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry From 91e1f217858379a102194691b84c21c56ec4cc93 Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 16:42:55 -0700 Subject: [PATCH 17/37] PLFM-8554: env.branch --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 26578f4..1b3b70e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,7 +40,7 @@ jobs: build-registry-container: needs: [tests, synth-test] - if: $env.branch == 'dev' || $env.branch == 'prod' + if: env.branch == 'dev' || env.branch == 'prod' runs-on: ubuntu-latest steps: - name: Checkout repository From 64c4528c60e883464335d2971826608709b45a88 Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 16:51:07 -0700 Subject: [PATCH 18/37] PLFM-8554: env.branch --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1b3b70e..f551409 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,7 +40,7 @@ jobs: build-registry-container: needs: [tests, synth-test] - if: env.branch == 'dev' || env.branch == 'prod' + if: ${{env.branch}} == 'dev' || ${{env.branch}} == 'prod' runs-on: ubuntu-latest steps: - name: Checkout repository @@ -75,7 +75,7 @@ jobs: labels: ${{ steps.meta.outputs.labels }} cdk-deploy-dev: - if: env.branch == 'dev' + if: ${{env.branch}} == 'dev' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit @@ -84,7 +84,7 @@ jobs: ROLE_TO_ASSUME: arn:aws:iam::449435941126:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry cdk-deploy-prod: - if: env.branch == 'prod' + if: ${{env.branch}} == 'prod' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit From a2d5da29b119a2de390e2666f03996578a1a9625 Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 16:56:00 -0700 Subject: [PATCH 19/37] PLFM-8554: env.branch --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f551409..092adbc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,7 +40,7 @@ jobs: build-registry-container: needs: [tests, synth-test] - if: ${{env.branch}} == 'dev' || ${{env.branch}} == 'prod' + if: ${{ env.branch }} == 'dev' || ${{ env.branch }} == 'prod' runs-on: ubuntu-latest steps: - name: Checkout repository @@ -75,7 +75,7 @@ jobs: labels: ${{ steps.meta.outputs.labels }} cdk-deploy-dev: - if: ${{env.branch}} == 'dev' + if: ${{ env.branch }} == 'dev' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit @@ -84,7 +84,7 @@ jobs: ROLE_TO_ASSUME: arn:aws:iam::449435941126:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry cdk-deploy-prod: - if: ${{env.branch}} == 'prod' + if: ${{ env.branch }} == 'prod' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit From 9e97169e30d6a78f3645ba18801d7345d265b5a4 Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 17:02:16 -0700 Subject: [PATCH 20/37] PLFM-8554: don't refer to env var in if statement --- .github/workflows/main.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 092adbc..d3f7316 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,7 +40,7 @@ jobs: build-registry-container: needs: [tests, synth-test] - if: ${{ env.branch }} == 'dev' || ${{ env.branch }} == 'prod' + if: ${{ github.head_ref || github.ref_name }} == 'dev' || ${{ github.head_ref || github.ref_name }} == 'prod' runs-on: ubuntu-latest steps: - name: Checkout repository @@ -69,25 +69,25 @@ jobs: uses: docker/build-push-action@v6.4.0 with: context: . - build-args: stack=$env.branch + build-args: stack=${{ env.branch }} push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cdk-deploy-dev: - if: ${{ env.branch }} == 'dev' + if: ${{ github.head_ref || github.ref_name }} == 'dev' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: - CONTEXT: $env.branch + CONTEXT: ${{ env.branch }} ROLE_TO_ASSUME: arn:aws:iam::449435941126:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry cdk-deploy-prod: - if: ${{ env.branch }} == 'prod' + if: ${{ github.head_ref || github.ref_name }} == 'prod' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: - CONTEXT: $env.branch + CONTEXT: ${{ env.branch }} ROLE_TO_ASSUME: arn:aws:iam::325565585839:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry From a141f6e89fbf0e876f1069e834e65d742a4ce6ae Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 17:04:10 -0700 Subject: [PATCH 21/37] PLFM-8554: don't refer to env var anywhere --- .github/workflows/main.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d3f7316..4aab514 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,9 +9,6 @@ on: concurrency: ci-${{ github.ref }} -env: - branch: ${{ github.head_ref || github.ref_name }} - jobs: tests: runs-on: ubuntu-latest @@ -69,7 +66,7 @@ jobs: uses: docker/build-push-action@v6.4.0 with: context: . - build-args: stack=${{ env.branch }} + build-args: stack=${{ github.head_ref || github.ref_name }} push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} @@ -80,7 +77,7 @@ jobs: uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: - CONTEXT: ${{ env.branch }} + CONTEXT: ${{ github.head_ref || github.ref_name }} ROLE_TO_ASSUME: arn:aws:iam::449435941126:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry cdk-deploy-prod: @@ -89,5 +86,5 @@ jobs: uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: - CONTEXT: ${{ env.branch }} + CONTEXT: ${{ github.head_ref || github.ref_name }} ROLE_TO_ASSUME: arn:aws:iam::325565585839:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry From c7bd34d8c5f18a2cc2fa791ef572077999e6c14c Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 17:12:01 -0700 Subject: [PATCH 22/37] PLFM-8554: only publish container or deploy cdk on push/merge, not PR --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4aab514..79f2edc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -37,7 +37,7 @@ jobs: build-registry-container: needs: [tests, synth-test] - if: ${{ github.head_ref || github.ref_name }} == 'dev' || ${{ github.head_ref || github.ref_name }} == 'prod' + if: ${{ github.event_name == 'push' }} && (${{ github.head_ref || github.ref_name }} == 'dev' || ${{ github.head_ref || github.ref_name }} == 'prod') runs-on: ubuntu-latest steps: - name: Checkout repository @@ -72,7 +72,7 @@ jobs: labels: ${{ steps.meta.outputs.labels }} cdk-deploy-dev: - if: ${{ github.head_ref || github.ref_name }} == 'dev' + if: ${{ github.event_name == 'push' }} && ${{ github.head_ref || github.ref_name }} == 'dev' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit @@ -81,7 +81,7 @@ jobs: ROLE_TO_ASSUME: arn:aws:iam::449435941126:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry cdk-deploy-prod: - if: ${{ github.head_ref || github.ref_name }} == 'prod' + if: ${{ github.event_name == 'push' }} && ${{ github.head_ref || github.ref_name }} == 'prod' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit From 4b8c670a62f2c1faf459f9f494c52dacf87b1a16 Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 17:22:45 -0700 Subject: [PATCH 23/37] PLFM-8554: only publish container or deploy cdk on push/merge, not PR --- .github/workflows/main.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 79f2edc..8e5e4b9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -37,7 +37,8 @@ jobs: build-registry-container: needs: [tests, synth-test] - if: ${{ github.event_name == 'push' }} && (${{ github.head_ref || github.ref_name }} == 'dev' || ${{ github.head_ref || github.ref_name }} == 'prod') + # only run on a push/merge, not on a PR + if: ${{ github.ref_name }} == 'dev' || ${{ github.ref_name }} == 'prod' runs-on: ubuntu-latest steps: - name: Checkout repository @@ -66,25 +67,27 @@ jobs: uses: docker/build-push-action@v6.4.0 with: context: . - build-args: stack=${{ github.head_ref || github.ref_name }} + build-args: stack=${{ github.ref_name }} push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cdk-deploy-dev: - if: ${{ github.event_name == 'push' }} && ${{ github.head_ref || github.ref_name }} == 'dev' + # only run on a push/merge, not on a PR + if: ${{ github.ref_name }} == 'dev' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: - CONTEXT: ${{ github.head_ref || github.ref_name }} + CONTEXT: ${{ github.ref_name }} ROLE_TO_ASSUME: arn:aws:iam::449435941126:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry cdk-deploy-prod: - if: ${{ github.event_name == 'push' }} && ${{ github.head_ref || github.ref_name }} == 'prod' + # only run on a push/merge, not on a PR + if: ${{ \github.ref_name }} == 'prod' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: - CONTEXT: ${{ github.head_ref || github.ref_name }} + CONTEXT: ${{ github.ref_name }} ROLE_TO_ASSUME: arn:aws:iam::325565585839:role/sagebase-github-oidc-sage-bionetworks-synapse-docker-registry From f76d00161964a3a46061f1e241e0bebf553fc77c Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 17:23:23 -0700 Subject: [PATCH 24/37] PLFM-8554: typo --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8e5e4b9..df85ad4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -84,7 +84,7 @@ jobs: cdk-deploy-prod: # only run on a push/merge, not on a PR - if: ${{ \github.ref_name }} == 'prod' + if: ${{ github.ref_name }} == 'prod' needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit From c93a7d99af080e470a946da3549506f1c18e9d67 Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 17:29:54 -0700 Subject: [PATCH 25/37] PLFM-8554: order of operations --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index df85ad4..4d1874c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -38,7 +38,7 @@ jobs: build-registry-container: needs: [tests, synth-test] # only run on a push/merge, not on a PR - if: ${{ github.ref_name }} == 'dev' || ${{ github.ref_name }} == 'prod' + if: (${{ github.ref_name }} == 'dev') || (${{ github.ref_name }} == 'prod') runs-on: ubuntu-latest steps: - name: Checkout repository From 4bfc3e00ea00cfad1fad753bc7877d3162b1402e Mon Sep 17 00:00:00 2001 From: bhoff Date: Fri, 20 Sep 2024 17:39:21 -0700 Subject: [PATCH 26/37] PLFM-8554: syntax --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4d1874c..2065200 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -38,7 +38,7 @@ jobs: build-registry-container: needs: [tests, synth-test] # only run on a push/merge, not on a PR - if: (${{ github.ref_name }} == 'dev') || (${{ github.ref_name }} == 'prod') + if: ${{ github.ref_name == 'dev' || github.ref_name == 'prod' }} runs-on: ubuntu-latest steps: - name: Checkout repository @@ -74,7 +74,7 @@ jobs: cdk-deploy-dev: # only run on a push/merge, not on a PR - if: ${{ github.ref_name }} == 'dev' + if: ${{ github.ref_name == 'dev' }} needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit @@ -84,7 +84,7 @@ jobs: cdk-deploy-prod: # only run on a push/merge, not on a PR - if: ${{ github.ref_name }} == 'prod' + if: ${{ github.ref_name == 'prod' }} needs: [tests, synth-test, build-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit From 3c31a4024f66d756c85505aac407ec04d6a5babd Mon Sep 17 00:00:00 2001 From: bhoff Date: Mon, 23 Sep 2024 15:43:02 -0700 Subject: [PATCH 27/37] PLFM-8554: rotated dev token signing key/cert --- .github/workflows/main.yml | 2 +- .../dev/token_signing_key_public_cert.pem | 29 +++++++------------ 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2065200..95a80ac 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -61,7 +61,7 @@ jobs: run: > openssl req -x509 -days 3650 -newkey rsa:2048 -sha256 -nodes -keyout privatekey.pem -out certificate.pem - -subj "/C=US/ST=Seattle/L=WA/O=SageBionetworks/OU=IT/CN=synapse.org" + -subj "/C=US/ST=WA/L=Seattle/O=SageBionetworks/OU=IT/CN=www.synapse.org" - name: Build and push Docker image uses: docker/build-push-action@v6.4.0 diff --git a/resources/dev/token_signing_key_public_cert.pem b/resources/dev/token_signing_key_public_cert.pem index 712f231..56df7f4 100644 --- a/resources/dev/token_signing_key_public_cert.pem +++ b/resources/dev/token_signing_key_public_cert.pem @@ -1,21 +1,12 @@ -----BEGIN CERTIFICATE----- -MIIDYjCCAwmgAwIBAgIJAPjAfVg1hZLeMAkGByqGSM49BAEwgaoxCzAJBgNVBAYT -AlVTMQswCQYDVQQIEwJXQTEQMA4GA1UEBxMHU2VhdHRsZTEZMBcGA1UEChMQU2Fn -ZSBCaW9uZXR3b3JrczEhMB8GA1UECxMYU3luYXBzZSBFbmdpbmVlcmluZyBUZWFt -MRgwFgYDVQQDEw93d3cuc3luYXBzZS5vcmcxJDAiBgkqhkiG9w0BCQEWFXBsYXRm -b3JtQHNhZ2ViYXNlLm9yZzAgFw0xNjA2MTcxNjAzMDZaGA8yMTE2MDUyNDE2MDMw -NlowgaoxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJXQTEQMA4GA1UEBxMHU2VhdHRs -ZTEZMBcGA1UEChMQU2FnZSBCaW9uZXR3b3JrczEhMB8GA1UECxMYU3luYXBzZSBF -bmdpbmVlcmluZyBUZWFtMRgwFgYDVQQDEw93d3cuc3luYXBzZS5vcmcxJDAiBgkq -hkiG9w0BCQEWFXBsYXRmb3JtQHNhZ2ViYXNlLm9yZzBZMBMGByqGSM49AgEGCCqG -SM49AwEHA0IABH+L4hYeqS3yNtSR4PX6vrd/d4DXP4Dcxsa6+ztVXT1GRXpnVzzS -qTMqDT8caOyXgoIMMQyQS1scHbs5J4NDnSmjggETMIIBDzAdBgNVHQ4EFgQUzX4k -DwoYtxcxO9Ag6smecR+MtfEwgd8GA1UdIwSB1zCB1IAUzX4kDwoYtxcxO9Ag6sme -cR+MtfGhgbCkga0wgaoxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJXQTEQMA4GA1UE -BxMHU2VhdHRsZTEZMBcGA1UEChMQU2FnZSBCaW9uZXR3b3JrczEhMB8GA1UECxMY -U3luYXBzZSBFbmdpbmVlcmluZyBUZWFtMRgwFgYDVQQDEw93d3cuc3luYXBzZS5v -cmcxJDAiBgkqhkiG9w0BCQEWFXBsYXRmb3JtQHNhZ2ViYXNlLm9yZ4IJAPjAfVg1 -hZLeMAwGA1UdEwQFMAMBAf8wCQYHKoZIzj0EAQNIADBFAiAa9iX8YT8agglhE1DW -hBIC5tqUa+pAZawmTZWgsMm4lAIhAPCAlfHaho9OsebE2PMriQm4DQhgtQve0qjO -7IxEfJZg +MIIBzDCCAXICCQCJ7hzkH54X2zAKBggqhkjOPQQDAjBtMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxGDAWBgNVBAoMD1NhZ2VCaW9u +ZXR3b3JrczELMAkGA1UECwwCSVQxGDAWBgNVBAMMD3d3dy5zeW5hcHNlLm9yZzAg +Fw0yNDA5MjMyMjM0MzhaGA8yMTI0MDgzMDIyMzQzOFowbTELMAkGA1UEBhMCVVMx +CzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMRgwFgYDVQQKDA9TYWdlQmlv +bmV0d29ya3MxCzAJBgNVBAsMAklUMRgwFgYDVQQDDA93d3cuc3luYXBzZS5vcmcw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARzPVcdfxSSsI7dw6HfI5VWJ1GuCPTY +vOu/vuJ/8ifE66ISY0MlRQGNc+JM2enB0PimpMnA6ZeWofxMeRN/6+P/MAoGCCqG +SM49BAMCA0gAMEUCIQDjk9V7l4LK4c99fMFMm1A2m7ZBzsTGzps8r1gvXaWEbwIg +LgW0X3Vq7mX/dkUEHa3+COmkdK9M2bPRAMRPU0esZHk= -----END CERTIFICATE----- From efc0d46849e47643522f45add337f7e0f66f0831 Mon Sep 17 00:00:00 2001 From: bhoff Date: Wed, 25 Sep 2024 15:51:37 -0700 Subject: [PATCH 28/37] PLFM-8554: updates from CR --- .dockerfilelintrc | 8 -------- .gitignore | 4 ++++ .pre-commit-config.yaml | 6 +++--- README.md | 13 ++++++++++++- 4 files changed, 19 insertions(+), 12 deletions(-) delete mode 100644 .dockerfilelintrc diff --git a/.dockerfilelintrc b/.dockerfilelintrc deleted file mode 100644 index d4595a7..0000000 --- a/.dockerfilelintrc +++ /dev/null @@ -1,8 +0,0 @@ ---- -# https://github.com/replicatedhq/dockerfilelint -rules: - apt-get-upgrade: off - apt-get-update_require_install: off - apt-get_recommends: off - apt-get_missing_rm: off - sudo_usage: off diff --git a/.gitignore b/.gitignore index e0ddae8..7be5f53 100644 --- a/.gitignore +++ b/.gitignore @@ -142,3 +142,7 @@ cdk.out/ # VS Code .vscode/ + +# locally generated self-signed certificate-key pair +certificate.pem +privatekey.pem diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9e9dd75..35460ba 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -36,7 +36,7 @@ repos: hooks: - id: check-github-workflows - id: check-github-actions - - repo: https://github.com/pryorda/dockerfilelint-precommit-hooks - rev: v0.1.0 + - repo: https://github.com/hadolint/hadolint + rev: v2.12.0 hooks: - - id: dockerfilelint + - id: hadolint-docker diff --git a/README.md b/README.md index c02e80c..9ab8252 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,18 @@ Base64 encoded "Basic auth" credentials which are a shared-secret with Synapse a We use the open source Docker `registry`, available on DockerHub. This container requires several configuration files to be mounted. To achieve this cleanly, we embed the files into our own copy of the registry, published to GitHub as `ghcr.io/synapse-docker-registry`, making two versions under two different tags, `dev` and `prod`, each with its own configuration. Note that the configuration files we add contain no secrets. The only required secret (the event listener -authorization credential) is inserted into the registry configuration file at the time the container is started up. +authorization credential) is inserted into the registry configuration file at the time the container is started up. (See /startup.sh.) + +To build the container image manually during development: + +``` +openssl req -x509 -days 3650 -newkey rsa:2048 -sha256 \ +-nodes -keyout privatekey.pem -out certificate.pem \ +-subj "/C=US/ST=WA/L=Seattle/O=SageBionetworks/OU=IT/CN=www.synapse.org" + +docker build --build-arg stack=dev . + +``` ### Missing Secrets From f2d0bd959699272dd85b6533550ceab5e51c3496 Mon Sep 17 00:00:00 2001 From: bhoff Date: Wed, 25 Sep 2024 15:58:00 -0700 Subject: [PATCH 29/37] PLFM-8554: updates from CR --- startup.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/startup.sh b/startup.sh index dad0621..38c429b 100755 --- a/startup.sh +++ b/startup.sh @@ -1,6 +1,8 @@ #!/bin/sh # Inject notification listener authorization credentials into config.yml +# The value is taken from the environment variable, `notification_auth` which, +# during ECS deployment comes from the AWS Secrets Manager. sed -i "s/notification_auth/$notification_auth/g" /etc/docker/registry/config.yml # this assumed a particular start-up for the container registry From a139b19598f6a8c5a48b509d9b4c9b4d490335da Mon Sep 17 00:00:00 2001 From: bhoff Date: Wed, 25 Sep 2024 16:00:20 -0700 Subject: [PATCH 30/37] PLFM-8554: updates from CR --- resources/prod/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/prod/config.yml b/resources/prod/config.yml index a6a0832..66cbe47 100644 --- a/resources/prod/config.yml +++ b/resources/prod/config.yml @@ -13,7 +13,7 @@ log: http: addr: :443 tls: - certificate: /etc/docker/registry/ssl/public.crt + certificate: /etc/docker/registry/ssl/certificate.pem key: /etc/docker/registry/ssl/privatekey.pem storage: From e2d7c51f6459d780b0f4748f08cdf9216025cb71 Mon Sep 17 00:00:00 2001 From: bhoff Date: Wed, 25 Sep 2024 16:28:31 -0700 Subject: [PATCH 31/37] PLFM-8554: added no-publish Docker build to workflow --- .github/workflows/main.yml | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 95a80ac..71d1284 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,8 +35,29 @@ jobs: with: CONTEXT: ${{ matrix.stack }} - build-registry-container: - needs: [tests, synth-test] + build-only-container: + # build on PRs as well as on merges, but do not push + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: create self-signed cert + # the Dockerfile expects these files, but the content is not used + # so we jsut put dummy information in them + run: > + cat "fake-key" > privatekey.pem + cat "fake-cert" > certificate.pem + + - name: Build and push Docker image + uses: docker/build-push-action@v6.4.0 + with: + context: . + build-args: stack=dev + push: false + + build-and-publish-registry-container: + needs: [tests, synth-test, build-only-container] # only run on a push/merge, not on a PR if: ${{ github.ref_name == 'dev' || github.ref_name == 'prod' }} runs-on: ubuntu-latest From 609e95237643691950070a4e6b79c1318189252f Mon Sep 17 00:00:00 2001 From: bhoff Date: Wed, 25 Sep 2024 16:29:28 -0700 Subject: [PATCH 32/37] PLFM-8554: added no-publish Docker build to workflow --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 71d1284..2030cfc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -96,7 +96,7 @@ jobs: cdk-deploy-dev: # only run on a push/merge, not on a PR if: ${{ github.ref_name == 'dev' }} - needs: [tests, synth-test, build-registry-container] + needs: [tests, synth-test, build-and-publish-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: @@ -106,7 +106,7 @@ jobs: cdk-deploy-prod: # only run on a push/merge, not on a PR if: ${{ github.ref_name == 'prod' }} - needs: [tests, synth-test, build-registry-container] + needs: [tests, synth-test, build-and-publish-registry-container] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: From 2e59e943b4e6c0d93a313f5572180571475cd0ac Mon Sep 17 00:00:00 2001 From: bhoff Date: Wed, 25 Sep 2024 16:31:14 -0700 Subject: [PATCH 33/37] PLFM-8554: added no-publish Docker build to workflow --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2030cfc..d089d8b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -46,8 +46,8 @@ jobs: # the Dockerfile expects these files, but the content is not used # so we jsut put dummy information in them run: > - cat "fake-key" > privatekey.pem - cat "fake-cert" > certificate.pem + echo "fake-key" > privatekey.pem + echo "fake-cert" > certificate.pem - name: Build and push Docker image uses: docker/build-push-action@v6.4.0 From 5979d8391953ea4a9ae919dcd4cb530e57b6d96a Mon Sep 17 00:00:00 2001 From: bhoff Date: Thu, 17 Oct 2024 09:15:41 -0700 Subject: [PATCH 34/37] PLFM-8554: Build registry Docker image on-the-fly --- .github/workflows/aws-deploy.yml | 2 +- .github/workflows/main.yml | 62 +------------------------- README.md | 8 ++-- cdk.json | 2 - docker_fargate/docker_fargate_stack.py | 21 ++++++++- docker_fargate/generate_ssl_cert.py | 50 +++++++++++++++++++++ tests/unit/test_cert_gen.py | 12 +++++ 7 files changed, 90 insertions(+), 67 deletions(-) create mode 100644 docker_fargate/generate_ssl_cert.py create mode 100644 tests/unit/test_cert_gen.py diff --git a/.github/workflows/aws-deploy.yml b/.github/workflows/aws-deploy.yml index 63a0657..a5a3b7c 100644 --- a/.github/workflows/aws-deploy.yml +++ b/.github/workflows/aws-deploy.yml @@ -27,7 +27,7 @@ jobs: uses: actions/checkout@v3 - name: Assume AWS Role - uses: aws-actions/configure-aws-credentials@v1 + uses: aws-actions/configure-aws-credentials@v4 with: aws-region: us-east-1 role-to-assume: ${{inputs.ROLE_TO_ASSUME }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d089d8b..a49c8b2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,68 +35,10 @@ jobs: with: CONTEXT: ${{ matrix.stack }} - build-only-container: - # build on PRs as well as on merges, but do not push - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: create self-signed cert - # the Dockerfile expects these files, but the content is not used - # so we jsut put dummy information in them - run: > - echo "fake-key" > privatekey.pem - echo "fake-cert" > certificate.pem - - - name: Build and push Docker image - uses: docker/build-push-action@v6.4.0 - with: - context: . - build-args: stack=dev - push: false - - build-and-publish-registry-container: - needs: [tests, synth-test, build-only-container] - # only run on a push/merge, not on a PR - if: ${{ github.ref_name == 'dev' || github.ref_name == 'prod' }} - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4.1.1 - with: - images: ghcr.io/${{ github.repository }} - - - name: Login to GitHub Container Registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: create self-signed cert - run: > - openssl req -x509 -days 3650 -newkey rsa:2048 -sha256 - -nodes -keyout privatekey.pem -out certificate.pem - -subj "/C=US/ST=WA/L=Seattle/O=SageBionetworks/OU=IT/CN=www.synapse.org" - - - name: Build and push Docker image - uses: docker/build-push-action@v6.4.0 - with: - context: . - build-args: stack=${{ github.ref_name }} - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cdk-deploy-dev: # only run on a push/merge, not on a PR if: ${{ github.ref_name == 'dev' }} - needs: [tests, synth-test, build-and-publish-registry-container] + needs: [tests, synth-test] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: @@ -106,7 +48,7 @@ jobs: cdk-deploy-prod: # only run on a push/merge, not on a PR if: ${{ github.ref_name == 'prod' }} - needs: [tests, synth-test, build-and-publish-registry-container] + needs: [tests, synth-test] uses: "./.github/workflows/aws-deploy.yml" secrets: inherit with: diff --git a/README.md b/README.md index 9ab8252..06ddf78 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,7 @@ Base64 encoded "Basic auth" credentials which are a shared-secret with Synapse a ### Registry container We use the open source Docker `registry`, available on DockerHub. This container requires several configuration files to be mounted. -To achieve this cleanly, we embed the files into our own copy of the registry, published to GitHub as `ghcr.io/synapse-docker-registry`, making two versions under -two different tags, `dev` and `prod`, each with its own configuration. Note that the configuration files we add contain no secrets. The only required secret (the event listener -authorization credential) is inserted into the registry configuration file at the time the container is started up. (See /startup.sh.) +To achieve this cleanly, we embed the files into our own copy of the registry, created at synth' time, on the fly. To build the container image manually during development: @@ -30,6 +28,10 @@ docker build --build-arg stack=dev . ``` +Note that when deployed the container is behind a load balancer which uses its own certificate. The self-signed-cert' +only serves to allow encryption of data in transit between the load balancer and the container, which is a HIPAA +security requirement. + ### Missing Secrets Each new environment (dev/staging/prod/etc..) requires adding secrets in AWS Secrets Manager. If a diff --git a/cdk.json b/cdk.json index 8c24c57..67581b7 100644 --- a/cdk.json +++ b/cdk.json @@ -31,7 +31,6 @@ "aws-cn" ], "dev": { - "IMAGE_PATH_AND_TAG": "ghcr.io/sage-bionetworks/synapse-docker-registry:dev", "AWS_DEFAULT_REGION": "us-east-1", "PORT": "443", "CONTAINER_ENV": { @@ -45,7 +44,6 @@ "ACM_CERT_ARN": "arn:aws:acm:us-east-1:449435941126:certificate/bbd59a26-ad30-4b74-ad2d-194241801b22" }, "prod": { - "IMAGE_PATH_AND_TAG": "ghcr.io/sage-bionetworks/synapse-docker-registry:prod", "AWS_DEFAULT_REGION": "us-east-1", "PORT": "443", "CONTAINER_ENV": { diff --git a/docker_fargate/docker_fargate_stack.py b/docker_fargate/docker_fargate_stack.py index c28980d..544ccd8 100644 --- a/docker_fargate/docker_fargate_stack.py +++ b/docker_fargate/docker_fargate_stack.py @@ -12,6 +12,7 @@ import aws_cdk.aws_certificatemanager as cm import aws_cdk.aws_secretsmanager as sm from constructs import Construct +from docker_fargate.generate_ssl_cert import cert_gen ACM_CERT_ARN_CONTEXT = "ACM_CERT_ARN" IMAGE_PATH_AND_TAG_CONTEXT = "IMAGE_PATH_AND_TAG" @@ -21,6 +22,9 @@ SECRETS_MANAGER_ENV_NAME = "SECRETS_MANAGER_SECRETS" CONTAINER_ENV_NAME = "CONTAINER_ENV" +PRIVATE_KEY_FILE_NAME = "privatekey.pem" +CERTIFICATE_FILE_NAME = "certificate.pem" + def get_secret(scope: Construct, id: str, name: str) -> str: isecret = sm.Secret.from_secret_name_v2(scope, id, name) return ecs.Secret.from_secrets_manager(isecret) @@ -60,8 +64,22 @@ def __init__(self, scope: Construct, context: str, env: dict, vpc: ec2.Vpc, **kw env_vars = get_container_env(env) + # Build the container image for the registry + # Need self-signed certificates to add to the image + key_and_cert = cert_gen() + # write the private key and self-signed-cert to disk for Docker to use + with open(PRIVATE_KEY_FILE_NAME, "wt") as f: + f.write(key_and_cert["private_key"]) + with open(CERTIFICATE_FILE_NAME, "wt") as f: + f.write(key_and_cert["certificate"]) + # Now build the image, using the self-signed cert and key + image = ecs.ContainerImage.from_asset( + directory=".", + build_args={"stack":context} # 'dev' or 'prod' + ) + task_image_options = ecs_patterns.ApplicationLoadBalancedTaskImageOptions( - image=ecs.ContainerImage.from_registry(get_docker_image_name(env)), + image=image, environment=env_vars, secrets = secrets, container_port = get_port(env)) @@ -88,6 +106,7 @@ def __init__(self, scope: Construct, context: str, env: dict, vpc: ec2.Vpc, **kw public_load_balancer=True, # Default is False redirect_http=True, # TLS: + target_protocol=elbv2.ApplicationProtocol.HTTPS, certificate=cert, protocol=elbv2.ApplicationProtocol.HTTPS, ssl_policy=elbv2.SslPolicy.FORWARD_SECRECY_TLS12_RES, # Strong forward secrecy ciphers and TLS1.2 only. diff --git a/docker_fargate/generate_ssl_cert.py b/docker_fargate/generate_ssl_cert.py new file mode 100644 index 0000000..f343604 --- /dev/null +++ b/docker_fargate/generate_ssl_cert.py @@ -0,0 +1,50 @@ +# +# Generate a self-signed cert' +# +# from +# https://stackoverflow.com/questions/27164354/create-a-self-signed-x509-certificate-in-python +# +from OpenSSL import crypto, SSL + +# +# returns a dict containing the private key and certificate as strings +# +# +def cert_gen( + emailAddress="emailAddress", + commonName="commonName", + countryName="NT", + localityName="localityName", + stateOrProvinceName="stateOrProvinceName", + organizationName="organizationName", + organizationUnitName="organizationUnitName", + serialNumber=0, + validityStartInSeconds=0, + validityEndInSeconds=10*365*24*60*60): + #can look at generated file using openssl: + #openssl x509 -inform pem -in selfsigned.crt -noout -text + # create a key pair + k = crypto.PKey() + k.generate_key(crypto.TYPE_RSA, 4096) + # create a self-signed cert + cert = crypto.X509() + cert.get_subject().C = countryName + cert.get_subject().ST = stateOrProvinceName + cert.get_subject().L = localityName + cert.get_subject().O = organizationName + cert.get_subject().OU = organizationUnitName + cert.get_subject().CN = commonName + cert.get_subject().emailAddress = emailAddress + cert.set_serial_number(serialNumber) + cert.gmtime_adj_notBefore(validityStartInSeconds) + cert.gmtime_adj_notAfter(validityEndInSeconds) + cert.set_issuer(cert.get_subject()) + cert.set_pubkey(k) + cert.sign(k, 'sha512') + return {'private_key':crypto.dump_privatekey(crypto.FILETYPE_PEM, k).decode("utf-8"), + 'certificate':crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode("utf-8")} + + +if __name__ == '__main__': + result = cert_gen() + print(f"private_key:\n{result['private_key']}\n\ncert:\n{result['certificate']}") diff --git a/tests/unit/test_cert_gen.py b/tests/unit/test_cert_gen.py new file mode 100644 index 0000000..7a85d45 --- /dev/null +++ b/tests/unit/test_cert_gen.py @@ -0,0 +1,12 @@ +from docker_fargate.generate_ssl_cert import cert_gen +import aws_cdk.assertions as assertions +from OpenSSL.crypto import (load_privatekey, load_certificate, FILETYPE_PEM) + +# +# Check that the self-signed-cert code returns a valid private key +# and certificate +# +def test_cert_gen(): + key_and_cert = cert_gen() + load_privatekey(FILETYPE_PEM, key_and_cert["private_key"]) + load_certificate(FILETYPE_PEM, key_and_cert["certificate"]) From 2b647aa0ad6a310ca4f29672fae7635c64d8b343 Mon Sep 17 00:00:00 2001 From: bhoff Date: Thu, 17 Oct 2024 09:17:16 -0700 Subject: [PATCH 35/37] PLFM-8554: white space --- docker_fargate/docker_fargate_stack.py | 4 ++-- docker_fargate/generate_ssl_cert.py | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docker_fargate/docker_fargate_stack.py b/docker_fargate/docker_fargate_stack.py index 544ccd8..f095377 100644 --- a/docker_fargate/docker_fargate_stack.py +++ b/docker_fargate/docker_fargate_stack.py @@ -74,8 +74,8 @@ def __init__(self, scope: Construct, context: str, env: dict, vpc: ec2.Vpc, **kw f.write(key_and_cert["certificate"]) # Now build the image, using the self-signed cert and key image = ecs.ContainerImage.from_asset( - directory=".", - build_args={"stack":context} # 'dev' or 'prod' + directory=".", + build_args={"stack":context} # 'dev' or 'prod' ) task_image_options = ecs_patterns.ApplicationLoadBalancedTaskImageOptions( diff --git a/docker_fargate/generate_ssl_cert.py b/docker_fargate/generate_ssl_cert.py index f343604..424b4aa 100644 --- a/docker_fargate/generate_ssl_cert.py +++ b/docker_fargate/generate_ssl_cert.py @@ -41,10 +41,10 @@ def cert_gen( cert.set_issuer(cert.get_subject()) cert.set_pubkey(k) cert.sign(k, 'sha512') - return {'private_key':crypto.dump_privatekey(crypto.FILETYPE_PEM, k).decode("utf-8"), - 'certificate':crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode("utf-8")} + return {'private_key':crypto.dump_privatekey(crypto.FILETYPE_PEM, k).decode("utf-8"), + 'certificate':crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode("utf-8")} + - if __name__ == '__main__': - result = cert_gen() - print(f"private_key:\n{result['private_key']}\n\ncert:\n{result['certificate']}") + result = cert_gen() + print(f"private_key:\n{result['private_key']}\n\ncert:\n{result['certificate']}") From 69dd8ee58402c5ce414e5687c16088c7b50f7ee3 Mon Sep 17 00:00:00 2001 From: bhoff Date: Thu, 17 Oct 2024 09:30:23 -0700 Subject: [PATCH 36/37] PLFM-8554: add openssl to requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 74454a1..7938d52 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ +pyOpenSSL==24.2.1 aws-cdk-lib==2.60.0 constructs>=10.0.0,<11.0.0 From 2520b20902a7b5003fcf29707dc21c680ba61d84 Mon Sep 17 00:00:00 2001 From: bhoff Date: Thu, 17 Oct 2024 09:50:10 -0700 Subject: [PATCH 37/37] PLFM-8554: Updated CIDR ranges not to be conflicting --- cdk.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cdk.json b/cdk.json index 67581b7..429deb6 100644 --- a/cdk.json +++ b/cdk.json @@ -40,7 +40,7 @@ "OwnerEmail": "synapseeng@sagebase.org" }, "STACK_NAME_PREFIX": "registry-dev", - "VPC_CIDR": "172.30.0.0/24", + "VPC_CIDR": "172.29.0.0/24", "ACM_CERT_ARN": "arn:aws:acm:us-east-1:449435941126:certificate/bbd59a26-ad30-4b74-ad2d-194241801b22" }, "prod": { @@ -53,7 +53,7 @@ "OwnerEmail": "synapseeng@sagebase.org" }, "STACK_NAME_PREFIX": "registry-prod", - "VPC_CIDR": "172.30.1.0/24", + "VPC_CIDR": "172.29.1.0/24", "ACM_CERT_ARN": "arn:aws:acm:us-east-1:325565585839:certificate/7c42c355-3d69-4537-a5e6-428212db646f" } }