We're working on creating a CloudFormation stack which will be published to clients to install an "on-prem" agent of our product on a client's AWS environment.
We want to initiate the connection from our end and add some configurations based on the outputs of the CloudFormation.
Is there a way to automatically transmit the output of CloudFormation back to the publisher of the template? I've been looking for a solution online but with no avail. Not sure this is possible - but I'm hoping someone here has maybe done something similar.
Couldn't find any solution. From what I'm seeing the "only" way to do so is to ask the client to manually send back the output, but I'm glad to be proven wrong :)
So I happen to be working on something similar, and this is what I've found that works. There are caveats which I will enumerate.
TLDR;
To have a CloudFormation stack "phone home" you can specify a SNS topic that the stack will post changes to when it is created, updates, and/or deleted. The CloudFormation docs (see 'Notification options') and CLI reference (see '--notification-arns') mention this. You can then have a Lambda respond to the SNS messages to enable your desired behavior. Unfortunately you cannot specify this topic in the stack template and can only provide is when making the call to create the stack. This can be worked around by using a nested CloudFormation stack.
My (current) approach:
Use a SNS topic that has a resource policy which allows the installing user's AWS account to publish messages to your topic. AWS documents how to do this, but be warned that using a AWS Account Principal in the SNS topic policy (which so far is the only thing that has worked for me) allows anything in the customer account to publish to the SNS topic. This security issue is one part I have yet to work around and ideally a combination of a Service Principal and restrictive IAM policy conditions could be used instead.
Create a template that you provide to your user that acts as the top-level stack, and contains a nested stack which you will use to create resources in your user's AWS account. This also gives you an opportunity to do things like use a mapping that specifies per-region SNS topics for your CloudFormation notifications.
When specifying your nested stack in your top-level stack template you use the NotificationARNs property to provide the SNS topic ARN so that the nested stack will report back to you.
The Lambda (or other mechanism) that subscribes to the SNS topic will need to parse and filter the messages that CloudFormation posts to react appropriately. When needing to acquire the ARN of something like an IAM role in the user's AWS account my recommendation would be to give the role a static name such that you can know the role's ARN by using the user's AWS account ID and the role name. Ideally the role will have permission to retrieve information about the CloudFormation stack so that you can get ARNs and other data about any other resources your stack created.
Related
Depending on which page I create a subscription for a SNS topic to a SQS queue (both belonging to the same account) from within the AWS console, I notice a difference in how SQS policy for the queue is updated.
When I initially created the subscription from the SNS topic page in
the console, the queue's access policy did not get updated.
When I created the policy from SQS queue's page, I see the queue policy is
updated automatically allowing "SQS:SendMessage" from the SNS topic
ARN.
Is the difference in behavior between these two use cases intentional? Is there a reason behind why creating the subscription from SNS topic page does not update the permission automatically?
I don't think there is any specially reason for that. Its just inconsistencies in how AWS Console works. In fact, there is plenty of such inconsistencies in AWS Console.
The most basic example of that is when you delete a resource. Some resources will just delete without asking anything, others will force you to write "delete", others "delete me", or "permanently delete", or write "resource-name" or confirm something else.
I want to implement Security in AWS Cloud using IAM like below:
1. Restricting Region(Possible)
2. Restricting Particular Service(EC2/RDS/VPC)(Possible)
3. Restricting IAM user(Disabled other IAM user resources)(Not Sure)
4. Deleting IAM user should delete AWS Resources created by this user.(Not Sure)
I came across Cloud Training site called Qwiklabs where they restrict exactly what I need.
I already tried and done first two restrictions(Region and Services).
Now I'm not sure for remaining 3rd and 4th.
Can anyone suggest me how to implement this scenario?
Ad 3. - Can You elaborate?
In Qwiklabs Your labs are created on separate AWS account - no other users are there.
Ad. 4 - You will have to force all users to use CloudFormation do provision resources or develop a process (Lambda/Step function) triggered by delete user action
4.Deleting IAM user should delete AWS Resources created by the user - You can use AWS Cloudtrail/AWS Lambda for that.
AWS Lambda:
https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/RunLambdaSchedule.html
You can create a Lambda function which triggers as soon as the user logs in. The first Lambda function should create another Lambda Function with the scheduled events associated.
The second Lambda Function contains the specific user's information, instructions for deleting the resources created by the specific user and the instructions to delete the scheduled event.
With AWS CloudTrail:
By using the below sample command you can get the list of actions performed by the user.
aws cloudtrail lookup-events --lookup-attributes AttributeKey=username,AttributeValue=user#example.com
Once you have that you can delete them.
What are the best practices for CloudFormation stacks that create IAM users? I'm creating an API that will automatically add clients to one of our services, i.e., it uses a CloudFormation template to create buckets, dynamo db entries, IAM user, etc.
You send a POST call to a route with specific parameters in the call, and it will create the client and everything that's needed for them; however, due to security concerns, I'm hesitant to allow a lambda role to have IAM permissions. We take IAM user creation extremely seriously, as this could always have a negative connotation.
Is there a way that I could create a CloudFormation stack, but require an Admin's manual approval to create it? I noticed there isn't a way to "delay" a stack for approval from another entity who has the correct permissions, since, for stacks to be created in the first place, proper policies must be in place for the entity creating it.
So, in summary, send a POST request to a URL that creates a stack needing Admin approval with proper permissions to activate the creation.
I'm starting to believe this isn't possible, so what are some recommendations?
We have thought about some other methods:
API call uploads the generated CloudFormation template to an s3, then admins manually create the stack with object url
Modify the CloudFormation template to remove the IAM section, and have Admins create that portion manually
Either way, it kinda takes away from the "automation" aspect.
Any thoughts?
I would suggest to use AWS Step Functions to create a state machine (a codified process) around the approval mechanism. The POST request would then trigger a new Step Function execution with the specific CFN template. I imagine you would need to build a simple frontend to list all the pending Step Function executions (i.e. pending approvals).
An alternative solution could be built on top of CodePipeline. A pipeline execution can have a manual approval action and it can be configured in a way that it would creating the stack by itself.
If you are open to additional tools, you can trigger the cloudformation stack via a Jenkins job and allow only the admins to trigger that job.
I would like to set up different AWS Identity and Access Management (IAM) users so that if an AWS resource is created by that IAM user, the resource is automatically assigned a specific tag.
For example: if IAM user F creates a new EC2 instance, the instance is automatically tagged as User:MrF. Is it possible to build a custom policy that does this?
My company GorillaStack have an open source lambda function that does exactly that.
The function 'listens' for CloudTrail logs to be delivered and tag the created resource with the ARN of the user that created it. It also support cross account tagging, for cases where a central account collects CloudTrail logs for other accounts.
Github: https://github.com/GorillaStack/auto-tag
Blog Post: http://blog.gorillastack.com/gorillastack-presents-auto-tag
It got a shout out at the 2015 re:Invent conference which is pretty cool :)
Hope that helps!
This is not available when using the AWS APIs directly (i.e. there's no way to command all AWS API's to tag new resources automatically on your behalf), however, depending on the specifics of your use case you could work around that limitation by correlating the creating user with the resource via post hoc tagging:
Workaround
You could activate AWS CloudTrail, which records AWS API calls for your account and delivers log files to you and provides exactly the information you are after:
The recorded information includes the identity of the API caller, the
time of the API call, the source IP address of the API caller, the
request parameters, and the response elements returned by the AWS
service.
Based on that information, a dedicated service of yours could analyze the logs and apply post hoc tags to all resources based on the logged user and created resource via the resp. API actions. Please see my answer to Which user launched EC2 instance? for some caveats/constraints to consider when going down this route.
An even better solution (faster plus I believe cheaper than parsing through CloudTrail logs) is to use CloudTrail but in combination with CloudWatch Events.
This is the basic concept described in a diagram
The implementation is detailed in this article:
https://blogs.aws.amazon.com/security/post/Tx150Z810KS4ZEC/How-to-Automatically-Tag-Amazon-EC2-Resources-in-Response-to-API-Events
The article also describes how to setup an IAM policy that only allows the creator of a resource to perform certain actions (like start / stop, describe, edit, terminate) against it.
I would chose AWS Config. Create a rule that automatically tags resources on creation. No cost, works across multiple accounts. Great for enforcing compliance. https://aws.amazon.com/about-aws/whats-new/2019/03/aws-config-now-supports-tagging-of-aws-config-resources/
Currently there is no such feature on IAM. If what you need is allow/deny based on user names, what you could do is use variables on your policy to allow or deny access based on naming conventions, e.g.:
...
"Resource":"arn:aws:dynamodb:us-east-!:123456789:table/ItemsCatalog_${aws:username}"
...
I would like to know if is possible to configure
SNS Delivery Retry Policies through cloudFormation.
I couldn't find it in any online documentation. If such configuration is possible,
I would really appreciate if someone could post a snippet showing how to do it.
Thanks in Advance,
AWS CloudFormation sometimes doesn't cover all (new) API actions available within other AWS Products & Services, though they usually get introduced within a few month later on.
Unfortunately, despite SNS Delivery Retry Policies for HTTP/HTTPS Endpoints being introduced in December 2011 already, this feature is still not supported as of today.
Workaround
You might be able to implement a workaround with CloudFormation still by means of the dedicated CustomResource type, which are special AWS CloudFormation resources that provide a way for a template developer to include resources in an AWS CloudFormation stack that are provided by a source other than Amazon Web Services. - the AWS CloudFormation Custom Resource Walkthrough provides a good overview of what this is all about, how it works and what's required to implement your own.
Your custom resource would need to implement the missing support for delivery retry policies by explicitly calling the SetSubscriptionAttributes or SetTopicAttributes API actions with the apparently also undocumented DeliveryPolicy attribute as per the Sample Requests shown there, e.g.:
{
"healthyRetryPolicy":
{
"minDelayTarget": <int>,
"maxDelayTarget": <int>,
"numRetries": <int>,
"numMaxDelayRetries": <int>,
"backoffFunction": "<linear|arithmetic|geometric|exponential>"
},
"throttlePolicy":
{
"maxReceivesPerSecond": <int>
}
}
I was able to do this by firstly deploying an AWS SNS Topic using CDK. I then had to create a Lambda function to set the attributes of the topic.
I have created an example of how to do this in the following repository:
https://github.com/Milan9805/cdk-set-topic-attributes
There is a GitHub action in the repository that uses cdk to deploy the topic and lambda. Then it invokes the lambda to set the topic attributes.