CloudFormation vs Engineers: How to protect your CloudFormation managed AWS account from human intervention

Michael Wittig – 12 Oct 2015

To eliminate human error as much as possible I advised you to follow the idea of Infrastructure as Code implemented by AWS CloudFormation. Changes to your infrastructure like launching a new virtual server or making changes to a firewall configuration are no longer done manually. Instead you change the description of your infrastructure and let CloudFormation apply the changes.
A common problem with CloudFormation are manual changes to resources managed by CloudFormation. A manual change to your AWS account can conflict with what CloudFormation has done before. If you apply the next update to your infrastructure with CloudFormation things can become worse because CloudFormation can no longer figure out what to do. To prevent human intervention at all I advised you to use ReadOnlyAccess in an earlier post.
This may sound very restrictive to you but this post will show you how to implement the idea with ease.

Problems of the solution

ReadOnlyAccess comes with a problem: you can’t create or modify any resources. But most often your job is to solve problems so you will need to create or modify AWS resources. To create a stack based on a CloudFormation template you will need all those IAM permissions that are needed to create the resources described in the template. This will most likely include very sensitive resources like IAM roles.

I want to show you how you can follow the ReadOnlyAccess principle without:

  • slowing you down
  • leaving ReadOnlyAccess (only adding lambda:Invoke access rights)

You will make use of AWS Lambda, the JavaScript SDK and CloudFormation to achieve this goal.

Lambda functions run inside their own execution role

A Lambda function can execute JavaScript code (inside the Node.js runtime) and therefore can make use of the JavaScript SDK to make calls to AWS services. The interesting point is that the Lambda function runs inside it´s own execution role. Which means that you as the invoker of the function only need the right to invoke the function but not the rights to make all the calls inside the function.


Looking for a new challenge?

  • tecRacer

    Cloud Consultant

    tecRacer • Premier AWS Consulting Partner • Germany, Austria, Spain, and Switzerland
    AWS only Infrastructure as Code EC2 Containers Serverless
  • tecRacer

    Cloud Migration Specialist

    tecRacer • Premier AWS Consulting Partner • Germany, Austria, Spain, and Switzerland
    Lift&Shift Transformation EC2 RDS VPC

The solution

If you create a Lambda function that basically wraps the SDK call to create a CloudFormation stack you can allow the lambda function to do everything in your AWS account because you make sure that this function can only be modified by a handful of trusted people while everyone can invoke the function to create stacks they need. The supported API calls by the Lambda function are well defined. It is only possible to create (update or delete) CloudFormation stacks. The code of the lambda function looks as simple as this:

var AWS = require('aws-sdk');
var cloudformation = new AWS.CloudFormation();

exports.createStack = function name(event, context) {
console.log('createStack(): ', event);
cloudformation.createStack(event, function(err, data) {
if (err !== undefined) {
context.fail(err);
} else {
context.succeed(data);
}
});
};

Besides ReadOnlyAccess of you normal users you can add the inline policy to allow your users to invoke the lambda functions that wrap calls to the CloudFormation service like this:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:eu-west-1:XXX:function:YYY"
}
]
}

If you need a step-by-step instruction from setting up Lambda to adjusting your IAM role used by your users follow the detailed instruction on GitHub.

Summary

With the help of Lambda you can run code with an execution role that has nothing to do with the IAM permissions of the invoker of the Lambda function. The invoker only needs the access rights to invoke the Lambda function. With this technique you can wrap API calls that need most likely AdministratorAccess to do their job. The wrapper function can than be called by less privileged users. With this trick you can use ReadOnlyAccess to manage your AWS account with the exception to invoke a few Lambda functions.

Become a cloudonaut supporter

Michael Wittig

Michael Wittig ( Email, Twitter, or LinkedIn )

We launched the cloudonaut blog in 2015. Since then, we have published 345 articles, 45 podcast episodes, and 37 videos. It's all free and means a lot of work in our spare time. We enjoy sharing our AWS knowledge with you.

Please support us

Have you learned something new by reading, listening, or watching our content? With your help, we can spend enough time to keep publishing great content in the future. Learn more

$
Amount must be a multriply of 5. E.g, 5, 10, 15.

Thanks to Alan Leech, Alex DeBrie, ANTHONY RAITI, Jaap-Jan Frans, Jason Yorty, Jeff Finley, Jens Gehring, jhoadley, Johannes Grumböck, John Culkin, Jonas Mellquist, Juraj Martinka, Kamil Oboril, Ken Snyder, Ross Mohan, Ross Mohan, sam onaga, Shawn Tolidano, Thorsten Hoeger, Todd Valentine, and all anonymous supporters for your help! We also want to thank all supporters who purchased a cloudonaut t-shirt.