Skip to content

Commit

Permalink
Add NAT provision stack deployer role example (#107)
Browse files Browse the repository at this point in the history
  • Loading branch information
Veetaha authored Oct 10, 2024
1 parent 0e93476 commit dd386f1
Show file tree
Hide file tree
Showing 4 changed files with 268 additions and 1 deletion.
20 changes: 19 additions & 1 deletion elastio-nat-provision-lambda/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,27 @@ be no route `0.0.0.0/0` configured in the route table of the private subnet.
2. Check the box in front of `I acknowledge that AWS CloudFormation might create IAM resources`
and click `Create stack`.

## Deployer IAM role

If you'd like to automate the deployment of the NAT Gateway Provision Lambda Cloudformation stack, then you can use the example IAM role and policies to assign to your deployer process IAM identity. The example is available at [`deployer/main.tf`](./deployer/main.tf).

## Updating the CFN stack

To update the existing CFN stack use the Cloudformation UI or AWS CLI and pass the following CFN template link to replace the existing template:
To update the existing CFN stack, use the Cloudformation UI or AWS CLI and pass the following CFN template link to replace the existing template:
```
https://elastio-prod-artifacts-us-east-2.s3.us-east-2.amazonaws.com/contrib/elastio-nat-provision-lambda/v5/cloudformation-lambda.yaml
```

## Contributing

For anyone contributing to the code of the NAT Gateway Provision Lambda, make sure to test your changes against the deployer IAM role. Create the deployer IAM role and run the script [`deployer/test/test.sh`](./deployer/test/test.sh) to test that the role is capable of deploying the stack.

```bash
cd deployer
terraform init
terraform apply -auto-approve

cd test
terraform init
./test.sh
```
196 changes: 196 additions & 0 deletions elastio-nat-provision-lambda/deployer/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
provider "aws" {}

data "aws_caller_identity" "current" {}

locals {
account = data.aws_caller_identity.current.account_id
}

resource "aws_iam_role" "deployer" {
name = "ElastioNatProvisionLambdaDeployer"
assume_role_policy = jsonencode(
{
"Version" : "2012-10-17"
"Statement" : [
{
"Effect" : "Allow",
"Principal" : {
"AWS" : "arn:aws:iam::${local.account}:root"
},
"Action" : "sts:AssumeRole"
}
]
}
)
}

resource "aws_iam_role_policy" "manage_cfn_deployment" {
name = "ManageCfnDeployment"
role = aws_iam_role.deployer.id
policy = jsonencode(
{
"Version" : "2012-10-17",
"Statement" : [
{
"Effect" : "Allow",
"Action" : [
"cloudformation:CreateStack",
"cloudformation:DeleteStack",
"cloudformation:UpdateStack",
"cloudformation:CancelUpdateStack",
"cloudformation:RollbackStack",
"cloudformation:ContinueUpdateRollback",
"cloudformation:DescribeStacks",
"cloudformation:GetTemplate",

"iam:CreateRole",
"iam:DeleteRole",
"iam:UpdateRole",
"iam:UpdateRoleDescription",
"iam:GetRole",

"iam:TagRole",
"iam:UntagRole",
"iam:ListRoleTags",

"iam:UpdateAssumeRolePolicy",

"iam:AttachRolePolicy",
"iam:DetachRolePolicy",
"iam:ListAttachedRolePolicies",

"iam:PutRolePolicy",
"iam:DeleteRolePolicy",
"iam:GetRolePolicy",
"iam:ListRolePolicies",

"iam:PutRolePermissionsBoundary",
"iam:DeleteRolePermissionsBoundary",

"logs:CreateLogGroup",
"logs:DescribeLogGroups",
"logs:DeleteLogGroup",

"logs:ListTagsLogGroup",
"logs:UntagLogGroup",
"logs:TagLogGroup",
"logs:TagResource",
"logs:UntagResource",
"logs:PutRetentionPolicy",
"logs:DeleteRetentionPolicy",

"kms:CreateAlias",
"kms:DeleteAlias",
"kms:UpdateAlias",
"kms:ListAliases",

# Required when creating a lambda function with encrypted env vars
"kms:Encrypt",
"kms:Decrypt",
"kms:CreateGrant",

"kms:CreateKey",
"kms:DescribeKey",
"kms:UpdateKeyDescription",
"kms:ScheduleKeyDeletion",

"kms:EnableKey",
"kms:DisableKey",

"kms:EnableKeyRotation",
"kms:DisableKeyRotation",
"kms:GetKeyRotationStatus",
"kms:ListKeyRotations",

"kms:PutKeyPolicy",
"kms:GetKeyPolicy",
"kms:ListKeyPolicies",

"kms:CancelKeyDeletion",

"kms:ListResourceTags",
"kms:TagResource",
"kms:UntagResource",

"lambda:CreateFunction",
"lambda:DeleteFunction",
"lambda:DeleteFunctionEventInvokeConfig",
"lambda:PutFunctionEventInvokeConfig",
"lambda:UpdateFunctionCode",
"lambda:UpdateFunctionConfiguration",
"lambda:ListVersionsByFunction",
"lambda:GetFunction",
"lambda:GetFunctionConfiguration",
"lambda:GetFunctionCodeSigningConfig",
"lambda:GetFunctionEventInvokeConfig",
"lambda:GetPolicy",

"lambda:GetEventSourceMapping",
"lambda:UpdateEventSourceMapping",
"lambda:CreateEventSourceMapping",
"lambda:DeleteEventSourceMapping",

"lambda:AddPermission",
"lambda:RemovePermission",

"lambda:ListTags",
"lambda:TagResource",
"lambda:UntagResource",

"states:CreateStateMachine",
"states:DeleteStateMachine",
"states:UpdateStateMachine",
"states:DescribeStateMachine",
"states:ListStateMachineVersions",

"states:ListTagsForResource",
"states:TagResource",
"states:UntagResource",

"events:PutTargets",
"events:RemoveTargets",
"events:ListTargetsByRule",

"events:PutRule",
"events:DeleteRule",
"events:DescribeRule",

"events:DisableRule",
"events:EnableRule",

"events:TagResource",
"events:UntagResource",
"events:ListTagsForResource",

"scheduler:CreateSchedule",
"scheduler:GetSchedule",
"scheduler:UpdateSchedule",
"scheduler:DeleteSchedule",

"scheduler:ListTagsForResource",
"scheduler:TagResource",
"scheduler:UntagResource",
],
"Resource" : "*"
},

{
"Effect" : "Allow"
"Action" : [
"iam:PassRole"
],
"Resource" : "arn:aws:iam::${local.account}:role/*Elastio*"
},

# Get access for reading the artifacts (e.g. lambda zip) from the public elastio bucket
{
"Effect" : "Allow"
"Action" : [
"s3:GetObject"
],
"Resource" : "arn:aws:s3:::elastio*"
}
]
}
)
}
27 changes: 27 additions & 0 deletions elastio-nat-provision-lambda/deployer/test/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
provider "aws" {}

locals {
version = trimspace(file("${path.module}/../../version"))
}

resource "aws_cloudformation_stack" "elastio_nat_provision_stack" {
name = "elastio-nat-provision-lambda"
template_url = join(
"/",
[
"https://elastio-prod-artifacts-us-east-2.s3.us-east-2.amazonaws.com",
"contrib/elastio-nat-provision-lambda/${local.version}",
"cloudformation-lambda.yaml"
]
)
tags = {
"elastio:resource" = "true"
}
capabilities = ["CAPABILITY_NAMED_IAM"]
parameters = {
EncryptWithCmk = "true"
LambdaTracing = "true"
IamResourceNamesPrefix = "Prefix"
IamResourceNamesSuffix = "Suffix"
}
}
26 changes: 26 additions & 0 deletions elastio-nat-provision-lambda/deployer/test/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env bash

set -euxo pipefail

role=ElastioNatProvisionLambdaDeployer
account=$(aws sts get-caller-identity --query 'Account' --output text)
role_arn="arn:aws:iam::${account}:role/${role}"

output=$(aws sts assume-role --role-arn "$role_arn" --role-session-name elastio-nat-provision-lambda-deployer-test)

AWS_REGION=$(aws configure get region || echo us-east-2)
export AWS_REGION

AWS_ACCESS_KEY_ID=$(echo "$output" | jq -r '.Credentials.AccessKeyId')
export AWS_ACCESS_KEY_ID

AWS_SECRET_ACCESS_KEY=$(echo "$output" | jq -r '.Credentials.SecretAccessKey')
export AWS_SECRET_ACCESS_KEY

AWS_SESSION_TOKEN=$(echo "$output" | jq -r '.Credentials.SessionToken')
export AWS_SESSION_TOKEN

unset AWS_PROFILE

terraform apply -auto-approve
terraform destroy -auto-approve

0 comments on commit dd386f1

Please sign in to comment.