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

fix(appconfig): sourcedConfiguration doesn't use retrievalRole #30733

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
29 changes: 18 additions & 11 deletions packages/aws-cdk-lib/aws-appconfig/lib/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ export interface SourcedConfigurationProps extends ConfigurationProps {
/**
* The IAM role to retrieve the configuration.
*
* @default - A role is generated.
* @default - Auto generated if location type is not ConfigurationSourceType.CODE_PIPELINE otherwise no role specified.
*/
readonly retrievalRole?: iam.IRole;
}
Expand Down Expand Up @@ -564,16 +564,7 @@ export class SourcedConfiguration extends ConfigurationBase {
this.locationUri = this.location.locationUri;
this.versionNumber = props.versionNumber;
this.sourceKey = this.location.key;
this.retrievalRole = props.retrievalRole || this.location.type != ConfigurationSourceType.CODE_PIPELINE
? new iam.Role(this, 'Role', {
roleName: PhysicalName.GENERATE_IF_NEEDED,
assumedBy: new iam.ServicePrincipal('appconfig.amazonaws.com'),
inlinePolicies: {
['AllowAppConfigReadFromSourcePolicy']: this.getPolicyForRole(),
},
})
: undefined;

this.retrievalRole = props.retrievalRole ?? this.getRetrievalRole();
this._cfnConfigurationProfile = new CfnConfigurationProfile(this, 'Resource', {
applicationId: this.applicationId,
locationUri: this.locationUri,
Expand All @@ -596,6 +587,22 @@ export class SourcedConfiguration extends ConfigurationBase {
this.deployConfigToEnvironments();
}

private getRetrievalRole(): iam.Role | undefined {
// Check if the configuration source is not from CodePipeline
if (this.location.type != ConfigurationSourceType.CODE_PIPELINE) {
return new iam.Role(this, 'Role', {
roleName: PhysicalName.GENERATE_IF_NEEDED,
assumedBy: new iam.ServicePrincipal('appconfig.amazonaws.com'),
inlinePolicies: {
['AllowAppConfigReadFromSourcePolicy']: this.getPolicyForRole(),
},
});
} else {
// No role is needed if the configuration source is from CodePipeline
return undefined;
}
}

private getPolicyForRole(): iam.PolicyDocument {
const policy = new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
Expand Down
143 changes: 142 additions & 1 deletion packages/aws-cdk-lib/aws-appconfig/test/configuration.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Template } from '../../assertions';
import { Template, Match } from '../../assertions';
import { Artifact, Pipeline } from '../../aws-codepipeline';
import { S3DeployAction, S3SourceAction } from '../../aws-codepipeline-actions';
import * as iam from '../../aws-iam';
Expand Down Expand Up @@ -283,6 +283,147 @@ describe('configuration', () => {
Template.fromStack(stack).resourceCountIs('AWS::AppConfig::Deployment', 2);
});

test('configuration with retrievalRole undefined from bucket source should create a new role', () => {
// GIVEN
const stack = new cdk.Stack();
const app = new Application(stack, 'MyAppConfig', {
applicationName: 'MyApplication',
});
const bucket = new Bucket(stack, 'MyBucket');

// WHEN
new SourcedConfiguration(stack, 'MySourcedConfig', {
versionNumber: '1',
location: ConfigurationSource.fromBucket(bucket, 'path/to/object'),
application: app,
});

// THEN
// should have a new role provisioned with AllowAppConfigReadFromSourcePolicy
Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', {
AssumeRolePolicyDocument: {
Statement: [
{
Action: 'sts:AssumeRole',
Effect: 'Allow',
Principal: {
Service: 'appconfig.amazonaws.com',
},
},
],
Version: '2012-10-17',
},
Policies: [
{
PolicyName: 'AllowAppConfigReadFromSourcePolicy',
},
],
});
});

test('configuration with retrievalRole defined should NOT create a new role', () => {
// GIVEN
const stack = new cdk.Stack();
const app = new Application(stack, 'MyAppConfig', {
applicationName: 'MyApplication',
});
const bucket = new Bucket(stack, 'MyBucket');

// WHEN
new SourcedConfiguration(stack, 'MySourcedConfig', {
versionNumber: '1',
location: ConfigurationSource.fromBucket(bucket, 'path/to/object'),
application: app,
retrievalRole: new iam.Role(stack, 'MyRole', {
assumedBy: new iam.ServicePrincipal('appconfig.amazonaws.com'),
}),
});

// THEN
// should have a new role provisioned with AllowAppConfigReadFromSourcePolicy
Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', Match.not({
pahud marked this conversation as resolved.
Show resolved Hide resolved
AssumeRolePolicyDocument: {
Statement: [
{
Action: 'sts:AssumeRole',
Effect: 'Allow',
Principal: {
Service: 'appconfig.amazonaws.com',
},
},
],
Version: '2012-10-17',
},
Policies: [
{
PolicyName: 'AllowAppConfigReadFromSourcePolicy',
},
],
}));
});

test('configuration with retrievalRole undefined from CodePipeline source should NOT create a new role', () => {
// GIVEN
const stack = new cdk.Stack();
const app = new Application(stack, 'MyAppConfig', {
applicationName: 'MyApplication',
});
const bucket = new Bucket(stack, 'MyBucket');
const sourceAction = new S3SourceAction({
actionName: 'Source',
bucket: bucket,
bucketKey: 'hello/world/codepipeline.txt',
output: new Artifact('SourceOutput'),
});
const deployAction = new S3DeployAction({
actionName: 'Deploy',
input: Artifact.artifact('SourceOutput'),
bucket: bucket,
extract: true,
});
const pipeline = new Pipeline(stack, 'MyPipeline', {
stages: [
{
stageName: 'beta',
actions: [sourceAction],
},
{
stageName: 'prod',
actions: [deployAction],
},
],
});

// WHEN
new SourcedConfiguration(stack, 'MySourcedConfig', {
versionNumber: '1',
location: ConfigurationSource.fromPipeline(pipeline),
application: app,
});

// THEN
// should NOT have a new role provisioned with AllowAppConfigReadFromSourcePolicy
Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', Match.not({
AssumeRolePolicyDocument: {
Statement: [
{
Action: 'sts:AssumeRole',
Effect: 'Allow',
Principal: {
Service: 'appconfig.amazonaws.com',
},
},
],
Version: '2012-10-17',
},
Policies: [
{
PolicyName: 'AllowAppConfigReadFromSourcePolicy',
},
],
}));
});

test('configuration with two configurations and no deployment strategy specified', () => {
const stack = new cdk.Stack();
const app = new Application(stack, 'MyAppConfig', {
Expand Down
Loading