Cloudformation: Passing parameters from a file and on the command line - amazon-web-services

I've got a question around using parameters in Cloudformation and more generally best practices around using secrets in Clouformation.
I have a template that defines our CI servers in an autoscaling group. We could in theory stand up many of these stacks. The templates are stored in source control along with parameters.json files use to specify the details of the stack (e.g. instance type, autoscaling conditions etc.). One of those parameters is a token that allows the CI server to interact with our CI provider, I don't want to store the token in source control. I want someone to be prompted for it or be forced to pass it when creating or updating the stack.
Ideally what I'm imagining is something like this, but obviously this is invalid
aws cloudformation create-stack --stack-name <name> --template-body file://<template> --parameters file://<parameters-file.json> TokenParameter=xxxyyyzzz
Does anyone have any suggestions?
Many Thanks

Hopefully this helps someone 2+ years later...
I solved this will a little help of jq. I'm on a mac, so that's a simple brew install jq
My goal was to use a default file of parameters, but wanted to pass my github oauth as a secret this one time. To the point above of storing secrets in other / better places, that's ideal, but I believe can be overkill for all situations. Mine for example was just lab based work.
aws cloudformation create-stack --stack-name "codepipeline-test"
--template-body file://codepipeline-test.yml
--parameters $(cat codepipeline-test-params.json | jq -r '.[]
| "ParameterKey=" + .ParameterKey + ",ParameterValue=" + .ParameterValue')
ParameterKey="GitHubOAuthToken",
ParameterValue="1234567890826xxxxxxxxxx753dde68858ac2169"
--tags '[{"Key": "Name","Value": "codedepipeline-test"},
{"Key": "Owner","Value": "username"}]' --capabilities CAPABILITY_NAMED_IAM
FYI in the CF Template I define the github oath param to be a secret (hide in GUI) as follows:
GitHubOAuthToken:
Description: A valid access token for GitHub that has admin access to the GitHub Repo you specify
Type: String
NoEcho: true
MinLength: 40
MaxLength: 40
AllowedPattern: '[a-z0-9]*'

For any sort of token/secret type interaction, I would actually go on the side of recommend using Systems Manager Parameter Store. The advantage is it centralizes your credential store so that if you need to rotate credentials for any reason it's just one place to change. You can also encrypt the creds for additional security.
As this is an AWS service you can use the SDK/CLI to pull the value. This could either be a user data script with an IAM role that allows systems manager access (as well as all other access) to pull the parameter and place it in the respective file. Another option is to utilize the SDK to pull down credential on demand, though that would require support in your CI code for pulling that off.
One caveat to this is that you would need the parameter setup ahead of time before launching the auto scaling group, which would make including the parameter as part of the CF template a bit difficult.

Related

Confusing parameter for cloudFormation script

Hello i am planning to run the cloudFormation stack that is preconfigured by aws here.
It prompts me to fill out
NeptuneBulkloadIAMRoleArn
NeptuneClusterEndpoint
NeptuneLambdaIAMRoleArn
But i don't know what to fill in there, can you help me out?
The parameters you described above are used for the following:
NeptuneBulkloadIAMRoleArn - This is an IAM role setup to run the loader command. Instructions for setting this up found here.
NeptuneClusterEndpoint - This is the endpoint of your Neptune database, it will be accessible either from the console or the CLI.
NeptuneLambdaIAMRoleArn - This allows you to pass in your own role the Lambda should use, if not specified the CloudFormation stack should make one for you.

Fetching secrets by just name when using AWS SecretManager in cdk

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).

Use existing DBUser and DBPassword parameter values when updating stack

Does anyone know, if there's an option to use some kind of 'existingDBUser' and 'existingDBPassword parameter while describing DBUser and DBPassword in a Cloudformation template?
I don't want to use 'Default' params and when deploying template via cli it asks me for DBUser and DBPassword.
In my case if I specify that and it's different than ones assigned already to DBCluster it creates a new cluster instead of updating existing one.
There's a way to upload the template via AWS Console, where you can check the 'use existing' boxes.
How can I do that from CLI perspective?
Thanks for replies.
Yes, this is possible. You don't define this in the template, you specify this when you call the update stack command from the SDK or CLI.
You need to specify the "UsePreviousValue" attribute of the parameter when calling the UpdateStack.
Here is an example of how you would do it on the AWS CLI but the SDKs should also provide a similar functionality:
aws cloudformation update-stack \
--stack-name mystack \
--template-url https://s3.amazonaws.com/sample/updated.template \
--parameters ParameterKey=DBUser,UsePreviousValue=true \
ParameterKey=DBPassword,UsePreviousValue=true

AWS Cloud Formation templates

Is there any way to use a simple JSON file (of my instance details) to configure a Cloud Formation template?
That's basically what a CloudFormation template provides you. Since it is a template, you can also pass in parameters as variables.
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html
Details on passing parameters from a config file:
https://aws.amazon.com/blogs/devops/passing-parameters-to-cloudformation-stacks-with-the-aws-cli-and-powershell/
You can have CFT parameters populated however you like. If you want to run / load the CFT from AWS console - add the parameters as either default or options within the CFT and choose them while creating the stack.
If you want to load them from a properties file - you can use any programming language of your choice to do so. A bash script that loads the properties or whatever, it's upto you and your use case. If you are using AWS cli to run the CFT use bash shell or power shell, if you are using AWS SDK to run your CFT - use the same language as your SDK etc.
If you are using just aws cli, you can do something like this with a json parameters file:
aws cloudformation create-stack --stackname startmyinstance
--template-body file:///some/local/path/templates/startmyinstance.json
--parameters file:///some/local/path/params/startmyinstance-parameters.json

AWS how to use a credential just for one request

Is it possible to provide the credential in each request in a way like
aws sns create-topic my_topic --ACCESS-KEY XXXX --SECRET-KEY XXXX
Instead of doing aws configure before I make the call.
I know that credential management can be done by using --profile like Using multiple profiles but that requires me to save the credential, which I cannot do. I'm depending on the user to provide me the key as parameter input. Is it possible?
I believe the closest option to what you are looking for would be to set the credentials as environment variables before invoking the AWS CLI.
One option is to export the environment variables that control the credentials and then call the desired CLI. The following works for me in bash:
$ export AWS_ACCESS_KEY_ID=AKIXXXXXXXXXXXXXXXX AWS_SECRET_ACCESS_KEY=YhTYxxxxxxxxxxxxxxVCSi; aws sns create-topic my_topic
You may also want to take a look at: Configuration Settings and Precedence
There is another way. Instead of "export"ing, just run the command like:
AWS_ACCESS_KEY_ID=AAAA AWS_SECRET_ACCESS_KEY=BBB aws ec2 describe-regions
This will ensure that the credentials are set only for the command.
Your best bit would be to use IAM Role for Amazon ec2 instance. That way you don't need to worry about the credentials at all. Also they keys will be rotated periodically.
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html