I am planning to use AWS parameter store to store config for one of the project I am working on it. We are using cloud formation (or CDK) to deploy all the components. That includes parameter store as well.
I have some config which has password and other sensitive fields which I can't put to in version control. How to handle this scenario?
I would use AWS Secrets Manager to generate the secrets randomly.
#This is a Secret resource with a randomly generated password in its SecretString JSON.
MyRDSInstanceRotationSecret:
Type: AWS::SecretsManager::Secret
Properties:
Description: 'This is my rds instance secret'
GenerateSecretString:
SecretStringTemplate: '{"username": "admin"}'
GenerateStringKey: 'password'
PasswordLength: 16
ExcludeCharacters: '"#/\'
Tags:
-
Key: AppName
Value: MyApp
And would further export the same into AWS Parameter Store using a policy attached and later on access them using static or dyanmic reference.
The best would be to take your secrets management out of Cloudformation as suggested by #jordanm.
Take a look at AWS Secrets Manage for this use case. If you are implementing your solution in Java, see this Github URL:
https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/javav2/example_code/secretsmanager
Provisioning SecureString parameter type is not possible in clouldforamtion
AWS CloudFormation doesn't support creating a SecureString parameter
type
See the following link: This
But you can reference it securely, using dynamic references which provide a compact, powerful way for you to specify external values that are stored and managed in other services, such as the Systems Manager Parameter Store, in your stack template.
Use the ssm-secure dynamic reference pattern to specify AWS Systems
Manager SecureString type parameters in your templates. For ssm-secure
dynamic references, AWS CloudFormation never stores the actual
parameter value. AWS CloudFormation accesses the parameter value
during create and update operations for stacks and change sets.
Check the following link:This
Related
How I encrypt secret manager value in aws kms so that no on can see the plain text value . it basically should be decrypted in lambda using kms . is this even possible in AWS .
I could see that we can use kms to encrypt and decrypt kms values, but that happens at rest .
If you want to use lambda to either access or store data in cloud formation dynamically, you likely want to use a lambda-backed custom resource. Read more about it here: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources-lambda.html.
Basically, you can either pass data to the lambda function (which can be dynamic based on outputs of resources already created) and/or get dynamic data that it created through its outputs.
However, secret manager is designed to be able to let authorized users/entities (like EC2 instances, for example) to see the plaintext password. Consider instead setting up which users/entities are allowed to use. See here for more detail on access control to secret manager: https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access_determining-access.html
To encrypt a given plaintext secret for inclusion within a CloudFormation template, you can use the custom secret provider. It will decrypt the secret and store it in the SSM parameter store, as shown below:
Resources:
ApiKey:
Type: Custom::Secret
Properties:
Name: /datadog/api-key
EncryptedContent: >-
AQICAHgefwksukJYA7L2AkPMZLGjZsGxHbvY9AoVs55dcju1AwEZui/8lNbnGAhv63Wh0heUAAAA3zCB
3AYJKoZIhvcNAQcGoIHOMIHLAgEAMIHFBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDOXKKVZ4ft75
/oZ2TQIBEICBlzf5j1M3w6OH+iphx59kFLnNoKb+u1RCLfIqEitrt6VGu13/jDlnDcPE2DfkZFkW3fnm
Nn5OXfgt1L9j4XYdIQTEwexorNqUr5pUtMfS9YX8yL9DbArH+XBv/OQPSj8VsuWRcwFP5EwZKB9O4X3l
1pZlPafp2Y/ndWXgC1o6YgfplnmjufoUUTy8wi4P5glbwnqGP/iyc7g=
ReturnSecret: true
RefreshOnUpdate: true
ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-secret-provider'
The value is stored encrypted, but will be available in plaintext from the parameter store for those authorised to read it. By specifying ReturnSecret, you can access the plaintext secret in the CloudFormation template itself.
If it is a static secret, storing the secret in the parameter store is way cheaper.
For a more information checkout https://binx.io/blog/2018/10/21/encrypting-secrets-in-aws-cloudformation/
I have a UI5 web application which has no access to AWS Parameter store. However, it is deployed by CloudFormation, by an account which has this access - I already collect some values from SSM during deployment and use them as parameters for resources which are being deployed by template.yml file.
However, now I need some of these parameters not only during deployment, but also during actual run of the app. Does someone familiar with AWS and UI5 know, how can I store these values during deployment so I can use them later, during the run of the web application? Thank you.
If you can edit the CloudFormation template then you can add resources of type AWS:SSM:Parameter to the template which will create SSM Parameters as part of the deployment.
Example:
Resources:
BasicParameter:
Type: AWS::SSM::Parameter
Properties:
Name: /my/basic/parameter
Type: String
Value: my-basic-parameter-value
Description: A description of the parameter
I am trying to fetch pre existing secrets from the aws-secretsmanager module on CDK, and from the documentation here, the suggestion is
If you need to use a pre-existing secret, the recommended way is to
manually provision the secret in AWS SecretsManager and use the
Secret.fromSecretArn or Secret.fromSecretAttributes method to make it
available in your CDK Application
However, both the methods demand the use of the arn to fetch the secrets. I am not sure if it is a good idea to hardcode arns and check them into the git repo. Instead is there a way to just fetch the secrets by just using the name, since we already have the account details available in the profile for cdk.
At least until this current version (1.38.0), it’s not possible. An alternative is to save the secret arn in the SSM parameter store and use the ssm key in the code.
Putting full ARNs in CFN should not be a concern. Since you are creating these secrets ahead of time, their name, account, and region will be know. If you wish, however, you could still use the CFN psuedo parameters for partition, region, and account (AWS::Partition, AWS::Region, AWS::AccountId or the CDK equivelent).
Is there a way to access auto-generated URLs for deployed resources before the deployment is finished? (like db host, lambda function URL, etc.)
I can access them after the deployment is finished, but sometimes I need to access them while building my stack. (E.g. use them in other resources).
What is a good solution to handle this use-case? I was thinking about outputting them into the SSM parameter store from CloudFormation template, but I'm not sure if this is even possible.
Thanks for any suggestion or guidance!
If "use them in other resources" means another serverless service or another CloudFormation stack, then use CloudFormation Outputs to export the values you are interested in. Then use CloudFormation ImportValue function to reference that value in another stack.
See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html and https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html
Within Serverless Framework, you can access a CloudFormation Output value using https://serverless.com/framework/docs/providers/aws/guide/variables/#reference-cloudformation-outputs
If you want to use the autogenerated value within the same stack, then just use CloudFormation GetAtt function. See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html.
For example, I have a CloudFormation stack that outputs the URL for an ElasticSearch cluster.
Resources:
Search:
Type: AWS::Elasticsearch::Domain
Properties: <redacted>
Outputs:
SearchUrl:
Value: !GetAtt Search.DomainEndpoint
Export:
Name: myapp:search-url
Assuming that the CloudFormation stack name is "mystack", then in my Serverless service, I can reference the SearchUrl by:
custom:
searchUrl: ${cf:mystack.SearchUrl}
To add to bwinant's answer, ${cf:<stack name>.<output name>} does not work if you want to reference a variable in another stack which is located in another region. There is a plugin to achieve this called serverless-plugin-cloudformation-cross-region-variables. You can use it like so
plugins:
- serverless-plugin-cloudformation-cross-region-variables
custom:
myVariable: ${cfcr:ca-central-1:my-other-stack:MyVariable}
From the CFN docs I can see that I can create an AWS::SSM::Parameter. I also see how I can create a KMS Master Key.
However the type parameter on the SSM:Parameter in the doc page does not list the secure string type.
Is there a way that I can do the following in a cloudformation template:
1) create KMS Key
2) use KMS key to encrypt a param
3) pull that param in User-Data for an EC2 instance
I will be running the CFN template from a Jenkins job with the value of the param in a jenkins password parameter. I can also set "NoEcho": true on the template's parameter so it's not echoed in the CloudFormation console.
Support for this has been added so you no longer need to use a custom resource. You have to use a dynamic reference to a secure parameter.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html
Using this feature you can use add {{resolve:ssm-secure:parameter-name:version}} to your user data within a Fn::Join CF intrinsic.
As of April 2019 secure strings are not available as a parameter type in cloudformation templates however the documentation states that CloudFormation will support the Parameter Store ‘SecureString’ type in a later release.
https://aws.amazon.com/blogs/mt/integrating-aws-cloudformation-with-aws-systems-manager-parameter-store/
There seems to be a way to use a custom resource to do this. In combination with a lambda function.