Blog

Share your configuration across AWS accounts

31 Aug, 2024
Xebia Background Header Wave

It’s a best practice to split your environments into separate AWS accounts. It does not cost you anything extra and you can guarantee that your development environment is completely isolated from the higher environments. With this setup, it’s also common to have a build or tooling account to be responsible for the deployment of your application.

But it does bring some other challenges, for example: When you have a web application it usually has a frontend and an API that it uses. If you use separate pipelines to deploy these components you need a way to share the endpoint. You could use a predictable schema to determine the endpoint programmatically when you build the web application. This works well for a URL, but this does not work for a Cognito Client ID.

Use SSM Parameters

SSM Parameters are a key/value store, they are perfect for configuration values. When you deploy your API, Cognito user pool and client. You can store the value in an SSM parameter like this:

UserPoolClientIdParameter:
 Type: AWS::SSM::Parameter
 Properties:
   Name: /<Environment>/cognito/user-pool-client-id
   Tier: Advanced
   Type: String
   Value: !Ref AppClient

Next, you can share this parameter with the build/tooling account:

ShareUserPoolClientIdParameter:
 Type: AWS::RAM::ResourceShare
 Properties:
   AllowExternalPrincipals: true
   Name: UserPool Client ID - <Environment>
   PermissionArns:
     - arn:aws:ram::aws:permission/AWSRAMDefaultPermissionSSMParameterReadOnly
   Principals: 
     # This is the account id of your build/tooling account
     - 111122223333
   ResourceArns:
     - !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${UserPoolClientIdParameter}

Resolve the values in CodeBuild

Now that we have shared the configuration with the build/tooling account. We need to resolve the value. First, make sure that the principle is allowed to resolve the parameter:

{
  "Effect": "Allow",
  "Action": [
    "ssm:GetParameter",
    "ssm:GetParameters"
  ],
  "Resource": [
    "arn:aws:ssm:eu-west-1:444455556666:parameter/<Environment>/cognito/user-pool-client-id"
  ]
}

Next, we need to add the parameter to the buildspec:

version: 0.2
env:
  parameter-store:
    USER_POOL_CLIENT_ID: arn:aws:ssm:eu-west-1:444455556666:parameter/<Environment>/cognito/user-pool-client-id
phases:
   ...

Now in theory this should work… However, this parameter will not resolve. I assume that CodeBuild can only resolve parameters stored in the same account. But you can simply work around this issue by fetching the parameter yourself:

export USER_POOL_CLIENT_ID=$(aws ssm get-parameter --name arn:aws:ssm:eu-west-1:444455556666:parameter/<Environment>/cognito/user-pool-client-id --output text --query 'Parameter.Value')

I preferred the native solution but unfortunately, this is not working. Until it is this would be my recommended solution.

Conclusion

Following best practices is always a good idea. But they can introduce new challenges. In the example given, I have shown you how to use an SSM parameter to share configuration across accounts.

Photo by Mostafa Meraji

Joris Conijn
Joris has been working with the AWS cloud since 2009 and focussing on building event driven architectures. While working with the cloud from (almost) the start he has seen most of the services being launched. Joris strongly believes in automation and infrastructure as code and is open to learn new things and experiment with them, because that is the way to learn and grow. In his spare time he enjoys running and runs a small micro brewery from his home.
Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts