Skip to content

Commit 5aadf2a

Browse files
authored
chore(bootstrap): improve permissions boundary switch message (#24354)
If you were not applying a permissions boundary at all (previously or currently) then you would get a message like `Switching from to undefined...`. This PR fixes that and updates the wording a little. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent bb4311b commit 5aadf2a

File tree

2 files changed

+92
-3
lines changed

2 files changed

+92
-3
lines changed

packages/aws-cdk/lib/api/bootstrap/bootstrap-environment.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,16 +139,26 @@ export class Bootstrapper {
139139
* - the name indicating the custom permissions boundary to be used
140140
* Re-bootstrapping will NOT be blocked by either tightening or relaxing the permissions' boundary.
141141
*/
142-
const currentPermissionsBoundary = current.parameters.InputPermissionsBoundary;
142+
143+
// InputPermissionsBoundary is an `any` type and if it is not defined it
144+
// appears as an empty string ''. We need to force it to evaluate an empty string
145+
// as undefined
146+
const currentPermissionsBoundary: string | undefined = current.parameters.InputPermissionsBoundary || undefined;
143147
const inputPolicyName = params.examplePermissionsBoundary ? CDK_BOOTSTRAP_PERMISSIONS_BOUNDARY : params.customPermissionsBoundary;
144-
let policyName;
148+
let policyName: string | undefined;
145149
if (inputPolicyName) {
146150
// If the example policy is not already in place, it must be created.
147151
const sdk = (await sdkProvider.forEnvironment(environment, Mode.ForWriting)).sdk;
148152
policyName = await this.getPolicyName(environment, sdk, inputPolicyName, partition, params);
149153
}
150154
if (currentPermissionsBoundary !== policyName) {
151-
warning(`Switching from ${currentPermissionsBoundary} to ${policyName} as permissions boundary`);
155+
if (!currentPermissionsBoundary) {
156+
warning(`Adding new permissions boundary ${policyName}`);
157+
} else if (!policyName) {
158+
warning(`Removing existing permissions boundary ${currentPermissionsBoundary}`);
159+
} else {
160+
warning(`Changing permissions boundary from ${currentPermissionsBoundary} to ${policyName}`);
161+
}
152162
}
153163

154164
return current.update(

packages/aws-cdk/test/api/bootstrap2.test.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,15 @@ import { mockBootstrapStack, MockSdk, MockSdkProvider } from '../util/mock-sdk';
1212
let bootstrapper: Bootstrapper;
1313
let mockGetPolicyIamCode: (params: IAM.Types.GetPolicyRequest) => IAM.Types.GetPolicyResponse;
1414
let mockCreatePolicyIamCode: (params: IAM.Types.CreatePolicyRequest) => IAM.Types.CreatePolicyResponse;
15+
let stderrMock: jest.SpyInstance;
1516

1617
beforeEach(() => {
1718
bootstrapper = new Bootstrapper({ source: 'default' });
19+
stderrMock = jest.spyOn(process.stderr, 'write').mockImplementation(() => { return true; });
20+
});
21+
22+
afterEach(() => {
23+
stderrMock.mockRestore();
1824
});
1925

2026
function mockTheToolkitInfo(stackProps: Partial<AWS.CloudFormation.Stack>) {
@@ -114,6 +120,14 @@ describe('Bootstrapping v2', () => {
114120
});
115121

116122
test('passes value to PermissionsBoundary', async () => {
123+
mockTheToolkitInfo({
124+
Parameters: [
125+
{
126+
ParameterKey: 'InputPermissionsBoundary',
127+
ParameterValue: 'existing-pb',
128+
},
129+
],
130+
});
117131
await bootstrapper.bootstrapEnvironment(env, sdk, {
118132
parameters: {
119133
customPermissionsBoundary: 'permissions-boundary-name',
@@ -125,6 +139,71 @@ describe('Bootstrapping v2', () => {
125139
InputPermissionsBoundary: 'permissions-boundary-name',
126140
}),
127141
}));
142+
expect(stderrMock.mock.calls).toEqual(expect.arrayContaining([
143+
expect.arrayContaining([
144+
expect.stringMatching(/Changing permissions boundary from existing-pb to permissions-boundary-name/),
145+
]),
146+
]));
147+
});
148+
149+
test('permission boundary switch message does not appear', async () => {
150+
mockTheToolkitInfo({
151+
Parameters: [
152+
{
153+
ParameterKey: 'InputPermissionsBoundary',
154+
ParameterValue: '',
155+
},
156+
],
157+
});
158+
await bootstrapper.bootstrapEnvironment(env, sdk);
159+
160+
expect(stderrMock.mock.calls).toEqual(expect.arrayContaining([
161+
expect.not.arrayContaining([
162+
expect.stringMatching(/Changing permissions boundary/),
163+
]),
164+
]));
165+
});
166+
167+
test('adding new permissions boundary', async () => {
168+
mockTheToolkitInfo({
169+
Parameters: [
170+
{
171+
ParameterKey: 'InputPermissionsBoundary',
172+
ParameterValue: '',
173+
},
174+
],
175+
});
176+
await bootstrapper.bootstrapEnvironment(env, sdk, {
177+
parameters: {
178+
customPermissionsBoundary: 'permissions-boundary-name',
179+
},
180+
});
181+
182+
expect(stderrMock.mock.calls).toEqual(expect.arrayContaining([
183+
expect.arrayContaining([
184+
expect.stringMatching(/Adding new permissions boundary permissions-boundary-name/),
185+
]),
186+
]));
187+
});
188+
189+
test('removing existing permissions boundary', async () => {
190+
mockTheToolkitInfo({
191+
Parameters: [
192+
{
193+
ParameterKey: 'InputPermissionsBoundary',
194+
ParameterValue: 'permissions-boundary-name',
195+
},
196+
],
197+
});
198+
await bootstrapper.bootstrapEnvironment(env, sdk, {
199+
parameters: {},
200+
});
201+
202+
expect(stderrMock.mock.calls).toEqual(expect.arrayContaining([
203+
expect.arrayContaining([
204+
expect.stringMatching(/Removing existing permissions boundary permissions-boundary-name/),
205+
]),
206+
]));
128207
});
129208

130209
test('passing trusted accounts without CFN managed policies results in an error', async () => {

0 commit comments

Comments
 (0)