Part 4
In Part 3 we successfully made the first glue between Azure Functions and AWS CodeCommit by making it possible to manually trigger the Azure Functions Web App to pull from the AWS CodeCommit repository. Obviously, a manual pull is not ideal. It is certainly not a Continuous Delivery.
In Part 4 we lay the groundwork for the 2nd piece of glue between Azure Functions and AWS CodeCommit. In order to automatically trigger a pull AWS CodeCommit from Azure Functions, we need an AWS Lambda. AWS Lambda and Azure Functions are somewhat analogous. They serve almost identical purposes in their respective clouds. We also need to create a KMS key that will be used for encrypting and decrypting secrets.
Series Table of Contents
- Part 1 of 6: Project Introduction and Overview
- Part 2 of 6: Project Settings, Authentication, Azure Function App Deployment, and AWS Code Commit Deployment
- Part 3 of 6: Creating AWS IAM User for Git, Generating HTTPS Git Credentials, Configuring Azure Web App External Git Deployment, and Initial Manual Deployment
- Part 4 of 6 (This Post): Create AWS IAM Role, Deploy the C# .NET Core 2.0 AWS Lambda, and Create an AWS KMS Key
- Part 5 of 6: Add AWS CodeCommit Trigger and Encrypt Secrets with AWS KMS
- Part 6 of 6: Generate Configuration File, Automatic deployment from AWS CodeCommit to Azure Functions, Trigger the Azure Function from PowerShell, and Series Conclusion
Create AWS Lambda IAM Role and Attach Managed Policies
Before we create the AWS Lambda, we need to create an IAM Role for the Lambda to assume when it runs. This role will need to grant the Lambda access to AWS CodeCommit and to perform normal AWS Lambda functions. This could be done more fine-grained, but I chose to use two AWS Managed Policies because they were a good enough fit. They are bit more permissive than our purposes require, but the additional permissions are not worrisome.
As a reminder, from the settings we defined the following:
These policies grant the basic Lambda permissions required for the Lambda to run and read-only access to AWS CodeCommit. Rather than give the Lambda read-only access to the specific CodeCommit repository, we grant it read-only access to all CodeCommit repositories. Since we are using one AWS CodeCommit repository per Azure Functions Web App, we will reuse a single AWS Lambda to manage the automated pull triggering.
First we create the AWS IAM Role for the Lambda to assume:
Then we attach the managed policies to the role:
Finally, we validate the role was created and the policies attached using Pester:
If all is well, you should see the following:
About the C# .NET Core 2.0 AWS Lambda
Before we go further, I want to briefly go over the C# AWS Lambda this project will use. I chose C# and .NET Core 2.0 for this project because I’m more familiar with it than the other languages available in AWS Lambda. I have done a fair bit of programming in python, but that was many years ago and at this point, my C# skills outpace where I was in my python prime. I also already have a decent development environment already set up for C# and .NET Core 2.0 projects. There is nothing particular about C# and what this lambda does could just as easily be translated to other AWS Lambda languages.
This AWS Lambda does the following:
- Accepts a CodeCommit event
- Queries the calling CodeCommit repository
- Retrieves the cc2fa.yml file.
- Validates the git branch the commit was made against is the one configured to be used in Azure Functions
- Decodes and Decrypts the Azure Functions Web App deployment password and AWS IAM User HTTPS Git Credential Password
- Triggers the Azure Functions Web App Deployment
- Writes the environment settings and results to CloudWatch Logs
First, I want to make it clear that the AWS Lambda does not push any data to the Azure Function. It only triggers the Azure Function Web App manual deployment. This is analogous to clicking the sync button in the deployment options of the Azure Function in the Azure portal.
Second, I want to explain why I’m storing secrets in the cc2fa.yml instead of using environment variables. Remember, that the relationship of the AWS Lambda to AWS CodeCommit repositories is one-to-many. Also, in an ideal situation, the AWS Lambda maintainer is separate from the Azure Functions maintainer. That means that secrets are subject to change and rather than coordinate a hand off, we can make use of the YAML file. The secrets are encrypted with a KMS key (which you will see performed later). You can limit who (or what) can decrypt these strings with IAM policies. There are other ways to accomplish this, but I kind of wanted to emulate how AppVeyor allows for secure strings in their YAML file.
Finally, I want to share the code used for the CodeCommit event object model. Currently, this model is not available in the AWS .NET SDK, so I had to piece this together from the API documentation and from making several different types of CodeCommit events and inspecting the JSON sent to SNS. Since I had to put so much effort into this, I felt I should share so others can benefit from my efforts. If I ever get the time I will see if this is something I can get added to the SDK. Anyway, the code for the model can be found here.
The C# AWS Lambda is available as a Visual Studio solution at https://github.com/markekraus/PeanutButterChocolate/tree/master/CSLambda
Build and Deploy the C# .NET Core 2.0 AWS Lambda
This process may be documented somewhere, but I couldn’t find it.I ended up reverse engineering this from this from the AWS add-in for Visual Studio 2017. Essentially, to deploy C# .NET 2.0 AWS Lambda from source to working Lambda, you need to build and publish the .NET project, zip the publish files, then use that zip file with the CreateFunction API.
As a reminder, the prerequisites for this include installing the .NET Core SDK.
First, we build, publish, and zip the .NET Core project:
Next, we publish the AWS Lambda using the zip file:
Then, we clean up the temporary zip file:
Finally, we validation the AWS Lambda deployment with Pester:
If it was successful, you should see the following:
Create the AWS KMS Key
We need to create a KMS Key that the AWS Lambda will use to decrypt the secrets in the cc2af.yml. We will also use this key to encrypt those same secrets.
I have it displaying the result, which contains the Key ID. You should note this Key ID for your records. It would probably be a good idea to use Add-KMSResourceTag to add some tags so you know what the key is being used for.
Before continuing, we validate the KMS key was created using Pester:
If successful, you should see:
Grant AWS Lambda IAM Role Access to AWS KMS Key
For the final topic for this post, we will grant the AWS IAM Role that the AWS Lambda assumes access to the AWS KMS Key. This will allow the Lambda to use the KMS key to decrypt secrets in the cc2af.yml file.
I am giving it encrypt rights too, but honestly decrypting is the bigger risk anyway. Therefore, I see no problem giving both even though it doesn’t require encryption rights at this time.
Now we validate the access policy is in place with Pester:
If it was successful you should see:
Part 4 End
Now we have an AWS Lambda, an IAM role for it to assume, and a KMS key to encrypt and decrypt secrets. In the next part we will continue by creating the automatic trigger to launch the AWS lambda automatically when a commit is made tot he AWS CodeCommit repository.
It may be over a week before I can post Part 5. The Microsoft MVP Summit is next week and I will be pretty busy.So check back next weekend.