Skip to content

Commit

Permalink
Fix/upsert secrets issue 210 (#216)
Browse files Browse the repository at this point in the history
* Fix secret upsert and add test

* Update tests

* Fix prefix and add output to validate arn

* Use a different account id

* Fix arn for secret

* Add new secret, and role to make the test correct

* Fix: replace jsondecode for jsonencode

* Temporarily destroy env at the beginning for testing

* Revert "Temporarily destroy env at the beginning for testing"

This reverts commit a5d0155.

* remove codeploy from tests

* Update tests

* Remove codeploy dependency

* Update policy name for parameter store

* Add secret as parameter to cf

* Update roles definition

* MOve role to cf

* Fix vpc file and teardown script

* Remove dependency

* Fix output role

* Move secret to CF

* update auth method and add more trust relationships to role

* Fix var

* Cleanup

* try destroy once

* Update name of stacks

* Revert name changes

* Update secret name in fargate

* Removed commented code
  • Loading branch information
marboledacci authored Aug 28, 2024
1 parent de763c5 commit 26cc336
Show file tree
Hide file tree
Showing 13 changed files with 120 additions and 191 deletions.
187 changes: 28 additions & 159 deletions .circleci/test-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,6 @@ jobs:
set -x
terraform plan \
-input=false \
-var "aws_access_key=${AWS_ACCESS_KEY_ID}" \
-var "aws_secret_key=${AWS_SECRET_ACCESS_KEY}" \
-var "aws_session_token=${AWS_SESSION_TOKEN}" \
-var "aws_region=${AWS_DEFAULT_REGION}" \
-var "aws_account_id=${AWS_ACCOUNT_ID}" \
-var "aws_resource_prefix=<< parameters.aws-resource-name-prefix >>" \
Expand Down Expand Up @@ -224,6 +221,9 @@ jobs:
role_arn:
type: string
default: ''
secret_arn:
type: string
default: ''
steps:
- checkout
- setup_remote_docker
Expand Down Expand Up @@ -260,6 +260,7 @@ jobs:
cluster: "<< parameters.aws-resource-name-prefix >>-cluster"
container_image_name_updates: "container=<< parameters.aws-resource-name-prefix >>-service,image-and-tag=$FULL_IMAGE_NAME"
container_env_var_updates: 'container=<< parameters.aws-resource-name-prefix >>-service,name=VERSION_INFO,value="${CIRCLE_SHA1}_${CIRCLE_BUILD_NUM}",container=<< parameters.aws-resource-name-prefix >>-service,name=BUILD_DATE,value=$(date)'
container_secret_updates: 'container=<< parameters.aws-resource-name-prefix >>-service,name=test,valueFrom=<<parameters.secret_arn>>'
verify_revision_is_deployed: true
fail_on_verification_timeout: false
profile_name: "<<parameters.profile_name>>"
Expand Down Expand Up @@ -391,22 +392,11 @@ jobs:
no_output_timeout: "20m"
command: |-
cd << parameters.terraform-config-dir >>
if [ "$(terraform destroy -input=false -auto-approve \
-var "aws_access_key=${AWS_ACCESS_KEY_ID}" \
-var "aws_secret_key=${AWS_SECRET_ACCESS_KEY}" \
-var "aws_session_token=${AWS_SESSION_TOKEN}" \
echo "Destroying terraform"
terraform destroy -input=false -auto-approve \
-var "aws_region=${AWS_DEFAULT_REGION}" \
-var "aws_account_id=${AWS_ACCOUNT_ID}" \
-var "aws_resource_prefix=<< parameters.aws-resource-name-prefix >>" > /dev/null; echo $?)" -ne 0 ]; then
echo "Retrying terraform destroy"
terraform destroy -input=false -auto-approve \
-var "aws_access_key=${AWS_ACCESS_KEY_ID}" \
-var "aws_secret_key=${AWS_SECRET_ACCESS_KEY}" \
-var "aws_region=${AWS_DEFAULT_REGION}" \
-var "aws_account_id=${AWS_ACCOUNT_ID}" \
-var "aws_resource_prefix=<< parameters.aws-resource-name-prefix >>"
fi
-var "aws_resource_prefix=<< parameters.aws-resource-name-prefix >>"
integration-test-ecs-cli-install:
parameters:
executor:
Expand Down Expand Up @@ -443,11 +433,20 @@ workflows:
#################
# Fargate
#################
- tear-down-test-env:
name: fargate_tear-down-test-env-initial
filters: *filters
aws-resource-name-prefix: ${AWS_RESOURCE_NAME_PREFIX_FARGATE}
terraform-config-dir: "tests/terraform_setup/fargate"
context: [CPE-OIDC]
role_arn: "arn:aws:iam::122211685980:role/CPE_ECS_OIDC_TEST"
- build-test-app:
name: fargate_build-test-app
docker-image-namespace: "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
docker-image-name: "${AWS_RESOURCE_NAME_PREFIX_FARGATE}:${CIRCLE_SHA1}"
context: [CPE-OIDC]
requires:
- fargate_tear-down-test-env-initial
filters: *filters
- set-up-test-env:
name: fargate_set-up-test-env
Expand All @@ -468,6 +467,7 @@ workflows:
service_name: "${AWS_RESOURCE_NAME_PREFIX_FARGATE}-service"
docker-image-namespace: "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
docker-image-name: "${AWS_RESOURCE_NAME_PREFIX_FARGATE}:${CIRCLE_SHA1}"
secret_arn: "arn:aws:ssm:${AWS_DEFAULT_REGION}:${AWS_ACCOUNT_ID}:parameter/TestParameterFargateUpdate"
context: [CPE-OIDC]
role_arn: "arn:aws:iam::122211685980:role/CPE_ECS_OIDC_TEST"
- aws-ecs/deploy_service_update:
Expand Down Expand Up @@ -527,12 +527,21 @@ workflows:
#################
# EC2
#################
- tear-down-test-env:
name: ec2_tear-down-test-env-initial
filters: *filters
aws-resource-name-prefix: ${AWS_RESOURCE_NAME_PREFIX_EC2}
terraform-config-dir: "tests/terraform_setup/ec2"
context: [CPE-OIDC]
role_arn: "arn:aws:iam::122211685980:role/CPE_ECS_OIDC_TEST"
- build-test-app:
name: ec2_build-test-app
docker-image-namespace: "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
docker-image-name: "${AWS_RESOURCE_NAME_PREFIX_EC2}:${CIRCLE_SHA1}"
context: [CPE-OIDC]
filters: *filters
requires:
- ec2_tear-down-test-env-initial
- set-up-test-env:
name: ec2_set-up-test-env
filters: *filters
Expand Down Expand Up @@ -582,6 +591,7 @@ workflows:
family_name: "${AWS_RESOURCE_NAME_PREFIX_EC2}-family"
service_name: "${AWS_RESOURCE_NAME_PREFIX_EC2}-service"
docker-image-namespace: "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com"
secret_arn: "arn:aws:ssm:${AWS_DEFAULT_REGION}:${AWS_ACCOUNT_ID}:parameter/TestParameterUpdate"
docker-image-name: "${AWS_RESOURCE_NAME_PREFIX_EC2}:${CIRCLE_SHA1}"
context: [CPE-OIDC]
role_arn: "arn:aws:iam::122211685980:role/CPE_ECS_OIDC_TEST"
Expand Down Expand Up @@ -635,109 +645,6 @@ workflows:
role_arn: "arn:aws:iam::122211685980:role/CPE_ECS_OIDC_TEST"
requires:
- fargate_set-up-test-env
#################
# CodeDeploy
#################
- build-test-app:
name: codedeploy_fargate_build-test-app
docker-image-namespace: "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com"
docker-image-name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}:${CIRCLE_SHA1}"
context: [CPE-OIDC]
filters: *filters
- set-up-test-env:
name: codedeploy_fargate_set-up-test-env
filters: *filters
requires:
- codedeploy_fargate_build-test-app
terraform-image: "hashicorp/terraform:1.4.0"
aws-resource-name-prefix: ${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}
terraform-config-dir: "tests/terraform_setup/fargate_codedeploy"
context: [CPE-OIDC]
role_arn: "arn:aws:iam::122211685980:role/CPE_ECS_OIDC_TEST"
# - test-service-update:
# name: codedeploy_fargate_test-update_service-command
# filters: *filters
# requires:
# - codedeploy_fargate_set-up-test-env
# aws-resource-name-prefix: ${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}
# family_name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service"
# service_name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service"
# docker-image-namespace: "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com"
# docker-image-name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}:${CIRCLE_SHA1}"
# role_arn: "arn:aws:iam::122211685980:role/CPE_ECS_OIDC_TEST"
# skip-service-update: true
# context: [CPE-OIDC]
# - aws-ecs/deploy_service_update:
# name: codedeploy_fargate_test-update_service-job
# auth:
# - aws-cli/setup:
# role_arn: "arn:aws:iam::122211685980:role/CPE_ECS_OIDC_TEST"
# filters: *filters
# requires:
# - codedeploy_fargate_test-update_service-command
# region: AWS_REGION
# family: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service"
# cluster: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-cluster"
# container_image_name_updates: "container=${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service,image-and-tag=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}:${CIRCLE_SHA1}"
# container_env_var_updates: 'container=${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service,name=VERSION_INFO,value="${CIRCLE_SHA1}_${CIRCLE_BUILD_NUM}",container=${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service,name=BUILD_DATE,value=$(date)'
# deployment_controller: "ECS"
# codedeploy_application_name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-codedeployapp"
# codedeploy_deployment_group_name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-codedeploygroup"
# codedeploy_load_balanced_container_name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service"
# codedeploy_load_balanced_container_port: 80
# codedeploy_capacity_provider_name: "FARGATE"
# codedeploy_capacity_provider_base: "1"
# codedeploy_capacity_provider_weight: "2"
# verify_revision_is_deployed: false
# context: [CPE-OIDC]
# post-steps:
# - wait-for-codedeploy-deployment:
# application-name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-codedeployapp"
# deployment-group-name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-codedeploygroup"
# - test-deployment:
# service_name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service"
# cluster: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-cluster"
# port: "8080"
# delete-load-balancer: false
# - aws-ecs/deploy_service_update:
# name: codedeploy_fargate_test-update-and-wait-service-job
# auth:
# - aws-cli/setup:
# role_arn: "arn:aws:iam::122211685980:role/CPE_ECS_OIDC_TEST"
# context: [CPE-OIDC]
# filters: *filters
# requires:
# - codedeploy_fargate_test-update_service-job
# region: AWS_REGION
# family: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service"
# cluster: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-cluster"
# container_image_name_updates: "container=${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service,image-and-tag=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}:${CIRCLE_SHA1}"
# container_env_var_updates: 'container=${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service,name=VERSION_INFO,value="${CIRCLE_SHA1}_${CIRCLE_BUILD_NUM}",container=${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service,name=BUILD_DATE,value=$(date)'
# deployment_controller: "CODE_DEPLOY"
# codedeploy_application_name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-codedeployapp"
# codedeploy_deployment_group_name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-codedeploygroup"
# codedeploy_load_balanced_container_name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service"
# codedeploy_load_balanced_container_port: 80
# verify_revision_is_deployed: true
# verification_timeout: "12m"
# post-steps:
# - test-deployment:
# service_name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service"
# cluster: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-cluster"
# delete-load-balancer: true
# - delete-service:
# service_name: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-service"
# cluster: "${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}-cluster"
- tear-down-test-env:
name: codedeploy_fargate_tear-down-test-env
requires:
- codedeploy_fargate_set-up-test-env
terraform-image: "hashicorp/terraform:1.4.0"
aws-resource-name-prefix: ${AWS_RESOURCE_NAME_PREFIX_CODEDEPLOY_FARGATE}
terraform-config-dir: "tests/terraform_setup/fargate_codedeploy"
context: [CPE-OIDC]
role_arn: "arn:aws:iam::122211685980:role/CPE_ECS_OIDC_TEST"
filters: *filters
- orb-tools/pack:
filters: *release-filters
- orb-tools/publish:
Expand All @@ -746,47 +653,9 @@ workflows:
pub_type: production
enable_pr_comment: true
context: orb-publisher
requires: [orb-tools/pack, ec2_tear-down-test-env, fargate_tear-down-test-env, codedeploy_fargate_tear-down-test-env, integration-test-ecs-cli-install]
requires: [orb-tools/pack, ec2_tear-down-test-env, fargate_tear-down-test-env, integration-test-ecs-cli-install]
filters: *release-filters
commands:
wait-for-codedeploy-deployment:
description: "Wait for the CodeDeploy deployment to be successful"
parameters:
application-name:
description: "CodeDeploy application name"
type: string
deployment-group-name:
description: "CodeDeploy application name"
type: string
steps:
- run:
name: Wait for CodeDeploy deployment to be successful (for orb testing and is not part of the orb)
command: |
DEPLOYMENT_ID=$(aws deploy list-deployments \
--application-name << parameters.application-name >> \
--deployment-group-name << parameters.deployment-group-name >> \
--query "deployments" \
--max-items 1 \
--output text \
| head -n 1)
aws deploy wait deployment-successful --deployment-id ${DEPLOYMENT_ID}
delete-service:
description: "Forcefully delete an ECS service"
parameters:
service_name:
description: "Name of the ECS service"
type: string
cluster:
description: "Name of the cluster"
type: string
steps:
- run:
name: Delete ECS service
command: |
aws ecs delete-service \
--cluster << parameters.cluster>> \
--service << parameters.service_name >> \
--force
test-deployment:
description: "Test the deployment"
parameters:
Expand Down
9 changes: 7 additions & 2 deletions src/scripts/update_container_defs.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ def run(previous_task_definition, container_image_name_updates,
if env_var_definitions is not None:
for env_var_index, env_var_definition in enumerate(env_var_definitions):
env_var_map[env_var_definition['name']] = {'index': env_var_index}
container_map[container_definition['name']] = {'image': container_definition['image'], 'index': index, 'environment_map': env_var_map}
secret_map = {}
secret_definitions = container_definition.get('secrets')
if secret_definitions is not None:
for secret_index, secret_definition in enumerate(secret_definitions):
secret_map[secret_definition['name']] = {'index': secret_index}
container_map[container_definition['name']] = {'image': container_definition['image'], 'index': index, 'environment_map': env_var_map, 'secret_map': secret_map}

# Expected format: container=...,name=...,value=...,container=...,name=...,value=
try:
Expand Down Expand Up @@ -113,7 +118,7 @@ def run(previous_task_definition, container_image_name_updates,
if container_entry is None:
raise ValueError('The container ' + container_name + ' is not defined in the existing task definition')
container_index = container_entry['index']
secret_entry = container_entry['environment_map'].get(secret_name)
secret_entry = container_entry['secret_map'].get(secret_name)
if secret_entry is None:
# The existing container definition does not contain secrets variable
if container_definitions[container_index].get('secrets') is None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,12 @@ Resources:
Family: !Ref 'FamilyName'
Cpu: !Ref 'TaskCpu'
Memory: !Ref 'TaskMemory'
ExecutionRoleArn:
Fn::ImportValue:
!Join [':', [!Ref 'StackName', 'EC2Role']]
TaskRoleArn:
Fn::If:
- 'HasCustomRole'
- !Ref 'Role'
- !Ref "AWS::NoValue"
Fn::ImportValue:
!Join [':', [!Ref 'StackName', 'EC2Role']]
PlacementConstraints:
- Type: memberOf
Expression:
Expand All @@ -97,7 +98,12 @@ Resources:
- Name: DummyContainer
Cpu: 512
Memory: 1024
Image: nginx:latest
Image: nginx:latest
Secrets:
- Name: test
ValueFrom:
Fn::ImportValue:
!Join [':', [!Ref 'StackName', 'SSMParameter']]
Environment:
- Name: DUMMY_VAR_1
Value: 'a'
Expand Down
34 changes: 32 additions & 2 deletions tests/terraform_setup/ec2/cloudformation-templates/public-vpc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ Resources:
Statement:
- Effect: Allow
Principal:
Service: [ec2.amazonaws.com]
Service: [ec2.amazonaws.com, ecs.amazonaws.com, ecs-tasks.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
Policies:
Expand All @@ -238,6 +238,9 @@ Resources:
- 'ecr:GetAuthorizationToken'
- 'ecr:BatchGetImage'
- 'ecr:GetDownloadUrlForLayer'
- 'ssm:Describe*'
- 'ssm:Get*'
- 'ssm:List*'
Resource: '*'

# Load balancers for getting traffic to containers.
Expand Down Expand Up @@ -309,7 +312,7 @@ Resources:
Statement:
- Effect: Allow
Principal:
Service: [ecs.amazonaws.com]
Service: [ecs.amazonaws.com, ec2.amazonaws.com, ecs-tasks.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
Policies:
Expand Down Expand Up @@ -337,10 +340,32 @@ Resources:
- 'elasticloadbalancing:RegisterTargets'
Resource: '*'

SSMParameter:
Type: AWS::SSM::Parameter
Properties:
Name: TestParameter
Type: String
Value: test-value
SSMParameterUpdate:
Type: AWS::SSM::Parameter
Properties:
Name: TestParameterUpdate
Type: String
Value: test-value
# These are the values output by the CloudFormation template. Be careful
# about changing any of them, because of them are exported with specific
# names so that the other task related CF templates can use them.
Outputs:
SSMParameter:
Description: The original parameter to use as secret
Value: !Ref 'SSMParameter'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'SSMParameter' ] ]
SSMParameterUpdate:
Description: The original parameter to use as secret
Value: !Ref 'SSMParameterUpdate'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'SSMParameterUpdate' ] ]
ClusterName:
Description: The name of the ECS cluster
Value: !Ref 'ECSCluster'
Expand All @@ -356,6 +381,11 @@ Outputs:
Value: !GetAtt 'ECSRole.Arn'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ECSRole' ] ]
EC2Role:
Description: The ARN of the EC2 role
Value: !GetAtt 'EC2Role.Arn'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'EC2Role' ] ]
PublicListener:
Description: The ARN of the public load balancer's Listener
Value: !Ref PublicLoadBalancerListener
Expand Down
Loading

0 comments on commit 26cc336

Please sign in to comment.