Skip to content

Commit 32e84c1

Browse files
dlvenableJonah Calvo
authored andcommitted
Updates the staging stack to allow multiple accounts to access the read permissions. This will allow us to grant access to the OpenSearch CI test accounts. Contributes toward opensearch-project#5796. (opensearch-project#5830)
Signed-off-by: David Venable <dlv@amazon.com> Signed-off-by: Jonah Calvo <caljonah@amazon.com>
1 parent bea9df4 commit 32e84c1

3 files changed

Lines changed: 83 additions & 8 deletions

File tree

release/staging-resources-cdk/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ The following CDK commands all require defining context. The context variables a
5252

5353
* `archivesBucketName` - The name of the S3 bucket you will use to deploy. This bucket must be in the same region as your stack.
5454
* `dataPrepperOrganization` - The name of the GitHub organization which has the `data-prepper` repository. This allows you to create staging environments for forks. The default value is `opensearch-project`.
55-
* `ciAccountId` - The AWS account Id of the OpenSearch CI release/build server.
55+
* `ciAccountIds` - The AWS account Ids of the OpenSearch CI release/build server and test environments. This is a comma-delimited value and requires at least one account.
5656

5757
The following command will deploy the CDK stack and create a new S3 bucket. If you'd like to use an existing S3 bucket, see the section below
5858
for deploying individual stacks.
5959

6060
```
61-
cdk deploy --all --context archivesBucketName={s3-bucket-name} --context dataPrepperOrganization={data-prepper-organization-name} --context ciAccountId={opensearch-ci-account-id}
61+
cdk deploy --all --context archivesBucketName={s3-bucket-name} --context dataPrepperOrganization={data-prepper-organization-name} --context ciAccountIds={opensearch-ci-account-id}
6262
```
6363

6464
#### Deploy to Use an Existing S3 Bucket

release/staging-resources-cdk/lib/OpenSearchCIAccessStack.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,27 @@ export class OpenSearchCIAccessStack extends Stack {
2121
super(scope, id, props);
2222

2323
const archivesBucketName: string = scope.node.tryGetContext('archivesBucketName');
24-
const ciAccountId: string = scope.node.tryGetContext('ciAccountId');
24+
const ciAccountIds: string = scope.node.tryGetContext('ciAccountIds');
25+
26+
const trustedAccountIds = ciAccountIds.split(',')
27+
.map(id => id.trim())
28+
.filter(id => id.length > 0);
29+
30+
if (trustedAccountIds.length === 0) {
31+
throw new Error('At least one account ID must be provided in ciAccountIds');
32+
}
33+
34+
const principals = [];
35+
36+
for (const accountId of trustedAccountIds) {
37+
principals.push(
38+
new ArnPrincipal(`arn:aws:iam::${accountId}:role/OpenSearch-CI-MainNodeRole`),
39+
new ArnPrincipal(`arn:aws:iam::${accountId}:role/OpenSearch-CI-AgentNodeRole`)
40+
);
41+
}
2542

2643
new Role(this, 'OpenSearchCIAccessRole', {
27-
assumedBy: new CompositePrincipal(
28-
new ArnPrincipal(`arn:aws:iam::${ciAccountId}:role/OpenSearch-CI-MainNodeRole`),
29-
new ArnPrincipal(`arn:aws:iam::${ciAccountId}:role/OpenSearch-CI-AgentNodeRole`)
30-
),
44+
assumedBy: new CompositePrincipal(...principals),
3145
inlinePolicies: {
3246
S3Access: new PolicyDocument({
3347
statements: [new PolicyStatement({

release/staging-resources-cdk/test/OpenSearchCIAccessStack.test.ts

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ beforeEach(() => {
1717
app = new App({
1818
context: {
1919
archivesBucketName: 'test-archives-bucket',
20-
ciAccountId: '123456789012'
20+
ciAccountIds: '123456789012'
2121
}
2222
});
2323
});
@@ -70,3 +70,64 @@ test('Creates IAM role with S3 access policy', () => {
7070
}]
7171
});
7272
});
73+
74+
test('Creates IAM role with assume role policy for multiple CI accounts', () => {
75+
const appWithMultipleAccounts = new App({
76+
context: {
77+
archivesBucketName: 'test-archives-bucket',
78+
ciAccountIds: '123456789012,210987654321'
79+
}
80+
});
81+
82+
const stackUnderTest = new OpenSearchCIAccessStack(appWithMultipleAccounts, 'TestStack');
83+
84+
const template = Template.fromStack(stackUnderTest);
85+
86+
template.hasResourceProperties('AWS::IAM::Role', {
87+
AssumeRolePolicyDocument: {
88+
Statement: [
89+
{
90+
Effect: 'Allow',
91+
Principal: {
92+
AWS: 'arn:aws:iam::123456789012:role/OpenSearch-CI-MainNodeRole'
93+
},
94+
Action: 'sts:AssumeRole'
95+
},
96+
{
97+
Effect: 'Allow',
98+
Principal: {
99+
AWS: 'arn:aws:iam::123456789012:role/OpenSearch-CI-AgentNodeRole'
100+
},
101+
Action: 'sts:AssumeRole'
102+
},
103+
{
104+
Effect: 'Allow',
105+
Principal: {
106+
AWS: 'arn:aws:iam::210987654321:role/OpenSearch-CI-MainNodeRole'
107+
},
108+
Action: 'sts:AssumeRole'
109+
},
110+
{
111+
Effect: 'Allow',
112+
Principal: {
113+
AWS: 'arn:aws:iam::210987654321:role/OpenSearch-CI-AgentNodeRole'
114+
},
115+
Action: 'sts:AssumeRole'
116+
}
117+
]
118+
}
119+
});
120+
});
121+
122+
test('Throws error when no account IDs are provided', () => {
123+
const appWithNoAccounts = new App({
124+
context: {
125+
archivesBucketName: 'test-archives-bucket',
126+
ciAccountIds: ''
127+
}
128+
});
129+
130+
expect(() => {
131+
new OpenSearchCIAccessStack(appWithNoAccounts, 'TestStack');
132+
}).toThrow('At least one account ID must be provided in ciAccountIds');
133+
});

0 commit comments

Comments
 (0)