creating ssm secure string with cloudformation - aws-cloudformation

since August 2018 AWS CloudFormation supports AWS Systems Manager Secure String Parameters in CloudFormation Templates.
I have been searching high and low but wasnt able to find a way to create a ssm-secure-string via Cloudformation like I can do it for simple SSM parameter via
Type: "AWS::SSM::Parameter"
Properties:
AllowedPattern: String
Description: String
Name: String
Type: String
Value: String
Can someone help me out? Or is there no way to generate the ssm-secure string right now via Cloudformtion?
Merci A

As per current docs, it's not supported to create SSM secure string via cloudformation.
Note
AWS CloudFormation doesn't support the SecureString parameter type.
What introduced in Aug 2018 is the support for SSM Secure String as Parameters in cloudformation. Link
For the time being, CustomResource is the only way, however having raw value in any kind of infra template for secure string is not recommended.
Updated (Nov 2019):
As per this, we can provide 3rd party resource provider for such use cases. CustomResource is good but kind of repetitive if you use in multiple stacks. So now I would prefer using this 3rd party resource providers for common use cases like secure SSM. It's farily simple to implement as well.

Related

Best Practice for Operators to Receive Secrets in custom resource

I'm not finding any answers to this on Google but I may just not know what terms to search for.
In a CRD, is there a way to define a field in the spec that is a secret (and therefore shouldn't be stored in plain text)? For example, if the custom resource needs to have an API token included in it, how do you define that in the CRD?
One thought I had was to just have the user create a Secret outside of the CRD and then provide the secret's name in a custom resource field so the operator can query it from the K8s API on demand when needed (and obviously associated RBAC needs to be configured so the operator has read access to the Secret). So the field in the CRD would just be a normal string that is the name of the target Secret.
But is there a better way? Any existing best practices around this?
You do indeed just store the value in an actual Secret and reference it. You'll find the same pattern all over k8s. Then in your controller code you get your custom object, find the ref, get that secret, and then you have your data.

Dynamically generate cloudformation resources using CDK

I'm trying to dynamically generate SNS subscriptions in CDK based on what we have in mappings. What's the best way to do this here? I have mappings that essentially maps the SNS topic ARNs my queue want to subscribe to in each region/stage. The mapping looks something like this:
"Mappings":
"SomeArnMap":
"eu-west-1":
"beta":
- "arn:aws:sns:us-west-2:0123456789:topic1"
"gamma":
- "arn:aws:sns:us-west-2:0123456789:topic2"
- "arn:aws:sns:us-west-2:0123456789:topic3"
How do I write code in CDK that creates a subscription for each element in the list here? I can't get regular loop to work because we don't know the size of the list until deployment. After CDK synth, it would just give me tokens like #{Token[TOKEN.264]} for my topic ARN.
Is it even doable in CDK/CloudFormation? Thanks.
Since tokens aren't resolved during the runtime of aws-cdk code, usually you can use cfn intrinsic functions which declare some sort operation on the token in your template. These are accessible in #aws-cdk/core.fn. However, cfn doesn't have intrinsics for looping over values, only selecting values from a list/map.
If your cdk has these mappings in its output template and you just want to extract a value for reference when building another construct Fn.findInMap I believe should do that.
const importedTopic = Sns.Topic.fromTopicArn(this, "ImportedTopicId", Fn.findInMap("SomeArnMap", "eu-west-1", "beta"));
importedTopic.addSubscription(SomeSqsQueueOrSomething);

Create a KMS custom Key in CloudFormation template for different region

Is there any way to generate a custom KMS Key via CloudFormation template in a different region than the region which is specified in the respective AWS User account you use to run the template?
Merci A
Short answer:
No, not directly.
Long answer:
It can actually be done in one of two ways. First, using StackSets, you can create a single template that will be deployed in selected accounts (1 in this occurence) and regions.
The second way to achieve your goal is to use a Custom Resource to create your KMS keys in other regions. This custom resource will invoke a Lambda function to handle the lifecycle of your KMS keys. Within this Lambda you will have to call the appropriate APIs to create/update/delete the KMS keys in the desired region.

Is it possible to pass back JWT payload from custom Lambda authorizer when using AWS API Gateway?

We want to use the AWS API Gateway as the central entry point to our application and let a custom authorizer validate the provided JWT.
Thereby we have several private claims that we would like extract and then pass on to subsequent services (i.e. optimally the lambda function should return these extracted parameters and could then be mapped within the API gateway).
My question is now:
Is that possible? So far I only found auth policies that were made up of two objects: the principalId and the policyDocument.
You can't pass back any additional data at the moment, but we have this on the backlog to do along with some other improvements to Lambda authorizers that I'm sure you will find useful. No ETA for those improvements at the moment.
Edit: additional context for the authorizer response has been released. Public docs are delayed, but see my answer here: https://stackoverflow.com/a/40644554/5679071
You can use authorizers now to do so. I guess what you mean is you have a payload to extract from the JWT. You can do so with Lambda Authorizer (or custom authorizer for API Gateway's version 1 (REST API)). You can return extra info in the authorizer's response's context. It will become the underlying lambda functions' event.requestContext.authorizer. More details in my post https://shaowang.hashnode.dev/aws-lambda-functions-with-lambda-authorizer if you want to copy things in event.requestContext.authorizer into event directly with a helper decorator. Happy to take questions.

I'd like to create CloudFormation stack with resources in multiple regions. Is this possible?

Is it possible to create a single Amazon CloudFormation stack template that instantiates an AWS::EC2::Instance in ap-southeast-1 and another AWS::EC2::Instance in us-west-2 for example?
I suspect not, but I've not yet found a definitive yes/no saying that stacks can't have resources spanning multiple regions.
The accepted answer is out of date. It is now possible to create stacks across accounts and regions using CloudFormation StackSets.
A very good question; but I don't think you would be able to create resources spread across multiple regions.
The end point URL for CloudFormation is region based and AFAIK there isn't a place whether you can specify an region specific (diff region) information.
As of today you can compose the CloudFormation template in such way to make it region independent by leveraging the mappings section and get::region function; but making the template spread across multiple regions simultaneously wouldn't be possible; but can be expected down the line.
Your best bet right now would be to use a Cloudformation Custom Resource that invokes a Lambda function in order to create the resources that are in other regions. When you run the CFN template it would invoke the Lambda function where you'd create code (Python, Node.js or Java) that leverages the AWS SDKs to create the resources you need. CFN Custom Resources allow you to pass parameters to the function and get "outputs" back from them so from a CFN perspective you can treat it just like any other resource.
Here's a walkthrough example from the AWS docs: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources-lambda.html
You can create a lambda function invoking to create a resource in another region, and even making your lambda function to invoke another stack in the other region.
To make your life easy, in this case you can use the lambda cli2cloudformation (https://github.com/lucioveloso/cli2cloudformation).
Using it, you can execute CLI commands inside your lambda, and by this way, you specific the --region in the command.
It's also interesting, because you will be able to set a command when your stack is created, updated and deleted.
"myCustomResource": {
"Type": "Custom::LocationConstraint",
"Properties": {
"ServiceToken": "arn:aws:lambda:eu-west-1:432811670411:function:cli2cfn_proxy2",
"CliCommandCreate": "s3api get-bucket-location --bucket my-test-bucket --region eu-west-1",
"CliCommandUpdate": "",
"CliCommandDelete": ""
}
},