Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NAT provision stack deployer role example #107

Merged
merged 3 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions elastio-nat-provision-lambda/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,25 @@ 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:
```
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 apply -auto-approve

cd test
./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" : "*"
},
Veetaha marked this conversation as resolved.
Show resolved Hide resolved

{
"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 vkryvenko)
Veetaha marked this conversation as resolved.
Show resolved Hide resolved

AWS_REGION=$(aws configure get region || echo us-east-2)
export AWS_REGION
Veetaha marked this conversation as resolved.
Show resolved Hide resolved

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
Veetaha marked this conversation as resolved.
Show resolved Hide resolved