Skip to content

Commit 3e3d371

Browse files
author
sivaram-mongodb
committed
feat: automate IAM role creation and cleanup for AWS Lambda stream connection tests
1 parent b29e473 commit 3e3d371

4 files changed

Lines changed: 193 additions & 3 deletions

File tree

cfn-resources/stream-connection/test/cfn-test-create-inputs.sh

Lines changed: 97 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,97 @@ atlas clusters create "${clusterName}" --projectId "${projectId}" --backup --pro
4646
atlas clusters watch "${clusterName}" --projectId "${projectId}"
4747
echo -e "Created Cluster \"${clusterName}\""
4848

49+
# AWS IAM role creation and authorization for Lambda connections
50+
echo "--------------------------------AWS Lambda IAM Role creation starts ----------------------------"
51+
52+
# Get AWS Account ID
53+
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
54+
55+
# Role names for CREATE and UPDATE scenarios
56+
iamRoleNameCreate="mongodb-atlas-streams-lambda-$(date +%s)-${RANDOM}"
57+
iamRoleNameUpdate="mongodb-atlas-streams-lambda-$(date +%s)-${RANDOM}-updated"
58+
policyName="atlas-lambda-invoke-policy"
59+
60+
echo "Creating IAM roles: ${iamRoleNameCreate} and ${iamRoleNameUpdate}"
61+
62+
# Create first cloud provider access entry (for CREATE role)
63+
roleIdCreate=$(atlas cloudProviders accessRoles aws create --projectId "${projectId}" --output json | jq -r '.roleId')
64+
echo "Created Atlas cloud provider access entry for CREATE role: ${roleIdCreate}"
65+
66+
# Create second cloud provider access entry (for UPDATE role)
67+
roleIdUpdate=$(atlas cloudProviders accessRoles aws create --projectId "${projectId}" --output json | jq -r '.roleId')
68+
echo "Created Atlas cloud provider access entry for UPDATE role: ${roleIdUpdate}"
69+
70+
# Get Atlas AWS Account ARN and External ID for CREATE role
71+
atlasAWSAccountArnCreate=$(atlas cloudProviders accessRoles list --projectId "${projectId}" --output json | jq --arg roleID "${roleIdCreate}" -r '.awsIamRoles[] | select(.roleId | test($roleID)) | .atlasAWSAccountArn')
72+
atlasAssumedRoleExternalIdCreate=$(atlas cloudProviders accessRoles list --projectId "${projectId}" --output json | jq --arg roleID "${roleIdCreate}" -r '.awsIamRoles[] | select(.roleId | test($roleID)) | .atlasAssumedRoleExternalId')
73+
74+
# Get Atlas AWS Account ARN and External ID for UPDATE role
75+
atlasAWSAccountArnUpdate=$(atlas cloudProviders accessRoles list --projectId "${projectId}" --output json | jq --arg roleID "${roleIdUpdate}" -r '.awsIamRoles[] | select(.roleId | test($roleID)) | .atlasAWSAccountArn')
76+
atlasAssumedRoleExternalIdUpdate=$(atlas cloudProviders accessRoles list --projectId "${projectId}" --output json | jq --arg roleID "${roleIdUpdate}" -r '.awsIamRoles[] | select(.roleId | test($roleID)) | .atlasAssumedRoleExternalId')
77+
78+
# Create trust policy for CREATE role
79+
jq --arg atlasAssumedRoleExternalId "$atlasAssumedRoleExternalIdCreate" \
80+
--arg atlasAWSAccountArn "$atlasAWSAccountArnCreate" \
81+
'.Statement[0].Principal.AWS?|=$atlasAWSAccountArn | .Statement[0].Condition.StringEquals["sts:ExternalId"]?|=$atlasAssumedRoleExternalId' \
82+
"$(dirname "$0")/lambda-role-policy-template.json" >"$(dirname "$0")/lambda-trust-policy-create.json"
83+
84+
# Create trust policy for UPDATE role
85+
jq --arg atlasAssumedRoleExternalId "$atlasAssumedRoleExternalIdUpdate" \
86+
--arg atlasAWSAccountArn "$atlasAWSAccountArnUpdate" \
87+
'.Statement[0].Principal.AWS?|=$atlasAWSAccountArn | .Statement[0].Condition.StringEquals["sts:ExternalId"]?|=$atlasAssumedRoleExternalId' \
88+
"$(dirname "$0")/lambda-role-policy-template.json" >"$(dirname "$0")/lambda-trust-policy-update.json"
89+
90+
echo "--------------------------------AWS IAM Role creation starts ----------------------------"
91+
92+
# Check if CREATE role exists, delete if found
93+
awsRoleIdCreate=$(aws iam get-role --role-name "${iamRoleNameCreate}" 2>/dev/null | jq --arg roleName "${iamRoleNameCreate}" -r '.Role | select(.RoleName==$roleName) | .RoleId' || echo "")
94+
if [ -n "$awsRoleIdCreate" ]; then
95+
aws iam delete-role-policy --role-name "${iamRoleNameCreate}" --policy-name "${policyName}" 2>/dev/null || true
96+
aws iam delete-role --role-name "${iamRoleNameCreate}"
97+
echo "Deleted existing CREATE role"
98+
fi
99+
100+
# Create CREATE role
101+
awsRoleIdCreate=$(aws iam create-role --role-name "${iamRoleNameCreate}" --assume-role-policy-document file://"$(dirname "$0")"/lambda-trust-policy-create.json | jq --arg roleName "${iamRoleNameCreate}" -r '.Role | select(.RoleName==$roleName) | .RoleId')
102+
echo "Created AWS IAM role for CREATE: ${awsRoleIdCreate}"
103+
104+
# Check if UPDATE role exists, delete if found
105+
awsRoleIdUpdate=$(aws iam get-role --role-name "${iamRoleNameUpdate}" 2>/dev/null | jq --arg roleName "${iamRoleNameUpdate}" -r '.Role | select(.RoleName==$roleName) | .RoleId' || echo "")
106+
if [ -n "$awsRoleIdUpdate" ]; then
107+
aws iam delete-role-policy --role-name "${iamRoleNameUpdate}" --policy-name "${policyName}" 2>/dev/null || true
108+
aws iam delete-role --role-name "${iamRoleNameUpdate}"
109+
echo "Deleted existing UPDATE role"
110+
fi
111+
112+
# Create UPDATE role
113+
awsRoleIdUpdate=$(aws iam create-role --role-name "${iamRoleNameUpdate}" --assume-role-policy-document file://"$(dirname "$0")"/lambda-trust-policy-update.json | jq --arg roleName "${iamRoleNameUpdate}" -r '.Role | select(.RoleName==$roleName) | .RoleId')
114+
echo "Created AWS IAM role for UPDATE: ${awsRoleIdUpdate}"
115+
116+
# Get role ARNs
117+
awsArnCreate=$(aws iam get-role --role-name "${iamRoleNameCreate}" | jq --arg roleName "${iamRoleNameCreate}" -r '.Role | select(.RoleName==$roleName) | .Arn')
118+
awsArnUpdate=$(aws iam get-role --role-name "${iamRoleNameUpdate}" | jq --arg roleName "${iamRoleNameUpdate}" -r '.Role | select(.RoleName==$roleName) | .Arn')
119+
120+
# Attach Lambda permissions to both roles
121+
aws iam put-role-policy --role-name "${iamRoleNameCreate}" --policy-name "${policyName}" --policy-document file://"$(dirname "$0")"/lambda-permissions-template.json
122+
aws iam put-role-policy --role-name "${iamRoleNameUpdate}" --policy-name "${policyName}" --policy-document file://"$(dirname "$0")"/lambda-permissions-template.json
123+
echo "Attached Lambda invoke permissions to both roles"
124+
125+
echo "--------------------------------AWS IAM Role creation ends ----------------------------"
126+
127+
# Wait for AWS IAM role to propagate (similar to encryption-at-rest pattern)
128+
echo "Waiting for IAM roles to propagate..."
129+
sleep 65
130+
131+
# Authorize the roles in Atlas
132+
echo "--------------------------------Authorize MongoDB Atlas Roles starts ----------------------------"
133+
atlas cloudProviders accessRoles aws authorize "${roleIdCreate}" --iamAssumedRoleArn "${awsArnCreate}" --projectId "${projectId}"
134+
echo "Authorized CREATE role: ${iamRoleNameCreate}"
135+
136+
atlas cloudProviders accessRoles aws authorize "${roleIdUpdate}" --iamAssumedRoleArn "${awsArnUpdate}" --projectId "${projectId}"
137+
echo "Authorized UPDATE role: ${iamRoleNameUpdate}"
138+
echo "--------------------------------Authorize MongoDB Atlas Roles ends ----------------------------"
139+
49140
jq --arg cluster_name "$clusterName" \
50141
--arg workspace_name "$workspaceName" \
51142
--arg project_id "$projectId" \
@@ -99,17 +190,21 @@ jq --arg workspace_name "$workspaceName" \
99190
jq --arg workspace_name "$workspaceName" \
100191
--arg project_id "$projectId" \
101192
--arg profile "$profile" \
193+
--arg role_arn "$awsArnCreate" \
102194
'.Profile?|=$profile
103195
| .ProjectId?|=$project_id
104-
| .WorkspaceName?|=$workspace_name' \
196+
| .WorkspaceName?|=$workspace_name
197+
| .Aws.RoleArn=$role_arn' \
105198
"$(dirname "$0")/inputs_4_create.json" >"inputs/inputs_4_create.json"
106199

107200
jq --arg workspace_name "$workspaceName" \
108201
--arg project_id "$projectId" \
109202
--arg profile "$profile" \
203+
--arg role_arn "$awsArnUpdate" \
110204
'.Profile?|=$profile
111205
| .ProjectId?|=$project_id
112-
| .WorkspaceName?|=$workspace_name' \
206+
| .WorkspaceName?|=$workspace_name
207+
| .Aws.RoleArn=$role_arn' \
113208
"$(dirname "$0")/inputs_4_update.json" >"inputs/inputs_4_update.json"
114209

115210
jq --arg workspace_name "$workspaceName" \
@@ -143,4 +238,3 @@ jq --arg workspace_name "$workspaceName" \
143238
| .ProjectId?|=$project_id
144239
| .WorkspaceName?|=$workspace_name' \
145240
"$(dirname "$0")/inputs_6_update.json" >"inputs/inputs_6_update.json"
146-

cfn-resources/stream-connection/test/cfn-test-delete-inputs.sh

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,70 @@ else
4545
echo "failed to delete the stream workspace/instance with name ${workspaceOrInstanceName}"
4646
fi
4747

48+
# Delete AWS Lambda IAM roles if they exist
49+
echo "--------------------------------delete AWS Lambda IAM roles starts ----------------------------"
50+
51+
# Check if Lambda input files exist
52+
if [ -f "./inputs/inputs_4_create.json" ]; then
53+
echo "Found Lambda connection inputs, cleaning up IAM roles..."
54+
55+
policyName="atlas-lambda-invoke-policy"
56+
57+
# Extract role ARN from CREATE input file
58+
roleArnCreate=$(jq -r '.Aws.RoleArn // empty' ./inputs/inputs_4_create.json)
59+
# Extract role name from ARN (everything after the last '/')
60+
iamRoleNameCreate=$(echo "${roleArnCreate}" | awk -F'/' '{print $NF}')
61+
62+
# Extract role ARN from UPDATE input file
63+
roleArnUpdate=$(jq -r '.Aws.RoleArn // empty' ./inputs/inputs_4_update.json)
64+
# Extract role name from ARN (everything after the last '/')
65+
iamRoleNameUpdate=$(echo "${roleArnUpdate}" | awk -F'/' '{print $NF}')
66+
67+
# Get external IDs from trust policy files and find roleIds in Atlas
68+
if [ -f "$(dirname "$0")/lambda-trust-policy-create.json" ]; then
69+
atlasAssumedRoleExternalIdCreate=$(jq -r '.Statement[0].Condition.StringEquals["sts:ExternalId"]' "$(dirname "$0")/lambda-trust-policy-create.json")
70+
roleIdCreate=$(atlas cloudProviders accessRoles list --projectId "${projectId}" --output json | jq --arg extId "${atlasAssumedRoleExternalIdCreate}" -r '.awsIamRoles[] | select(.atlasAssumedRoleExternalId | test($extId)) | .roleId')
71+
72+
if [ -n "${roleIdCreate}" ] && [ "${roleIdCreate}" != "null" ]; then
73+
echo "Deauthorizing CREATE role from Atlas: ${roleIdCreate}"
74+
atlas cloudProviders accessRoles aws deauthorize "${roleIdCreate}" --projectId "${projectId}" --force || echo "Failed to deauthorize CREATE role"
75+
fi
76+
fi
77+
78+
if [ -f "$(dirname "$0")/lambda-trust-policy-update.json" ]; then
79+
atlasAssumedRoleExternalIdUpdate=$(jq -r '.Statement[0].Condition.StringEquals["sts:ExternalId"]' "$(dirname "$0")/lambda-trust-policy-update.json")
80+
roleIdUpdate=$(atlas cloudProviders accessRoles list --projectId "${projectId}" --output json | jq --arg extId "${atlasAssumedRoleExternalIdUpdate}" -r '.awsIamRoles[] | select(.atlasAssumedRoleExternalId | test($extId)) | .roleId')
81+
82+
if [ -n "${roleIdUpdate}" ] && [ "${roleIdUpdate}" != "null" ]; then
83+
echo "Deauthorizing UPDATE role from Atlas: ${roleIdUpdate}"
84+
atlas cloudProviders accessRoles aws deauthorize "${roleIdUpdate}" --projectId "${projectId}" --force || echo "Failed to deauthorize UPDATE role"
85+
fi
86+
fi
87+
88+
# Delete CREATE IAM role
89+
if [ -n "${iamRoleNameCreate}" ] && [ "${iamRoleNameCreate}" != "null" ] && [ "${iamRoleNameCreate}" != "" ]; then
90+
echo "Deleting CREATE IAM role: ${iamRoleNameCreate}"
91+
aws iam delete-role-policy --role-name "${iamRoleNameCreate}" --policy-name "${policyName}" 2>/dev/null || echo "Policy already deleted or doesn't exist"
92+
aws iam delete-role --role-name "${iamRoleNameCreate}" 2>/dev/null || echo "Role already deleted or doesn't exist"
93+
fi
94+
95+
# Delete UPDATE IAM role
96+
if [ -n "${iamRoleNameUpdate}" ] && [ "${iamRoleNameUpdate}" != "null" ] && [ "${iamRoleNameUpdate}" != "" ]; then
97+
echo "Deleting UPDATE IAM role: ${iamRoleNameUpdate}"
98+
aws iam delete-role-policy --role-name "${iamRoleNameUpdate}" --policy-name "${policyName}" 2>/dev/null || echo "Policy already deleted or doesn't exist"
99+
aws iam delete-role --role-name "${iamRoleNameUpdate}" 2>/dev/null || echo "Role already deleted or doesn't exist"
100+
fi
101+
102+
# Clean up temporary files
103+
rm -f "$(dirname "$0")/lambda-trust-policy-create.json"
104+
rm -f "$(dirname "$0")/lambda-trust-policy-update.json"
105+
106+
echo "Cleaned up Lambda IAM roles and temporary files"
107+
else
108+
echo "No Lambda connection inputs found, skipping IAM role cleanup"
109+
fi
110+
echo "--------------------------------delete AWS Lambda IAM roles ends ----------------------------"
111+
48112
#delete project
49113
if atlas projects delete "$projectId" --force; then
50114
echo "$projectId project deletion OK"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"Version": "2012-10-17",
3+
"Statement": [
4+
{
5+
"Effect": "Allow",
6+
"Action": [
7+
"lambda:InvokeFunction",
8+
"lambda:InvokeAsync"
9+
],
10+
"Resource": "*"
11+
}
12+
]
13+
}
14+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"Version": "2012-10-17",
3+
"Statement": [
4+
{
5+
"Effect": "Allow",
6+
"Principal": {
7+
"AWS": ""
8+
},
9+
"Action": "sts:AssumeRole",
10+
"Condition": {
11+
"StringEquals": {
12+
"sts:ExternalId": ""
13+
}
14+
}
15+
}
16+
]
17+
}
18+

0 commit comments

Comments
 (0)