Skip to content

Commit

Permalink
Merge branch 'main' into refactor/purpose-specific-constructs
Browse files Browse the repository at this point in the history
  • Loading branch information
tobuck-aws committed Jun 28, 2024
2 parents fd75f99 + f699f38 commit ad7ca7a
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 18 deletions.
25 changes: 13 additions & 12 deletions src/control-plane/auth/cognito-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
ServicePrincipal,
Effect,
} from 'aws-cdk-lib/aws-iam';
import { Runtime, IFunction, LayerVersion, ILayerVersion } from 'aws-cdk-lib/aws-lambda';
import { Runtime, IFunction, LayerVersion } from 'aws-cdk-lib/aws-lambda';
import { NagSuppressions } from 'cdk-nag';
import { Construct } from 'constructs';
import { CreateAdminUserProps, IAuth } from './auth-interface';
Expand Down Expand Up @@ -209,16 +209,17 @@ export class CognitoAuth extends Construct implements IAuth {
private readonly userPool: cognito.UserPool;

/**
* The Lambda Layer containing the Powertools library.
* The Lambda function for creating a new Admin User. This is used as part of a
* custom resource in CloudFormation to create an admin user.
*/
private readonly lambdaPowertoolsLayer: ILayerVersion;
private readonly createAdminUserFunction: IFunction;

constructor(scope: Construct, id: string, props?: CognitoAuthProps) {
super(scope, id);
addTemplateTag(this, 'CognitoAuth');

// https://docs.powertools.aws.dev/lambda/python/2.31.0/#lambda-layer
this.lambdaPowertoolsLayer = LayerVersion.fromLayerVersionArn(
const lambdaPowertoolsLayer = LayerVersion.fromLayerVersionArn(
this,
'LambdaPowerTools',
`arn:aws:lambda:${Stack.of(this).region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:59`
Expand Down Expand Up @@ -461,7 +462,7 @@ export class CognitoAuth extends Construct implements IAuth {
handler: 'lambda_handler',
timeout: Duration.seconds(60),
role: userManagementExecRole,
layers: [this.lambdaPowertoolsLayer],
layers: [lambdaPowertoolsLayer],
environment: {
USER_POOL_ID: this.userPool.userPoolId,
},
Expand Down Expand Up @@ -496,25 +497,23 @@ export class CognitoAuth extends Construct implements IAuth {
},
]
);
}

createAdminUser(scope: Construct, id: string, props: CreateAdminUserProps) {
const createAdminUserFunction = new PythonFunction(scope, `createAdminUserFunction-${id}`, {
this.createAdminUserFunction = new PythonFunction(scope, 'createAdminUserFunction', {
entry: path.join(__dirname, '../../../resources/functions/auth-custom-resource'),
runtime: Runtime.PYTHON_3_12,
index: 'index.py',
handler: 'handler',
timeout: Duration.seconds(60),
layers: [this.lambdaPowertoolsLayer],
layers: [lambdaPowertoolsLayer],
});
this.userPool.grant(
createAdminUserFunction,
this.createAdminUserFunction,
'cognito-idp:AdminCreateUser',
'cognito-idp:AdminDeleteUser'
);

NagSuppressions.addResourceSuppressions(
createAdminUserFunction.role!,
this.createAdminUserFunction.role!,
[
{
id: 'AwsSolutions-IAM4',
Expand All @@ -526,9 +525,11 @@ export class CognitoAuth extends Construct implements IAuth {
],
true // applyToChildren = true, so that it applies to policies created for the role.
);
}

createAdminUser(scope: Construct, id: string, props: CreateAdminUserProps) {
new CustomResource(scope, `createAdminUserCustomResource-${id}`, {
serviceToken: createAdminUserFunction.functionArn,
serviceToken: this.createAdminUserFunction.functionArn,
properties: {
UserPoolId: this.userPool.userPoolId,
Name: props.name,
Expand Down
6 changes: 1 addition & 5 deletions src/control-plane/control-plane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,7 @@ export class ControlPlane extends Construct {

cdk.Aspects.of(this).add(new DestroyPolicySetter());

const auth =
props.auth ||
new CognitoAuth(this, 'CognitoAuth', {
setAPIGWScopes: false,
});
const auth = props.auth || new CognitoAuth(this, 'CognitoAuth');

auth.createAdminUser(this, 'adminUser', {
name: systemAdminName,
Expand Down
7 changes: 6 additions & 1 deletion src/control-plane/integ.default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as cdk from 'aws-cdk-lib';
import { CfnRule, EventBus, Rule } from 'aws-cdk-lib/aws-events';
import { LogGroup, RetentionDays } from 'aws-cdk-lib/aws-logs';
import { AwsSolutionsChecks } from 'cdk-nag';
import { ControlPlane } from '.';
import { CognitoAuth, ControlPlane } from '.';
import { DestroyPolicySetter } from '../cdk-aspect/destroy-policy-setter';

export interface IntegStackProps extends cdk.StackProps {
Expand All @@ -16,7 +16,12 @@ export class IntegStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props: IntegStackProps) {
super(scope, id, props);

const cognitoAuth = new CognitoAuth(this, 'CognitoAuth', {
setAPIGWScopes: false, // only for testing purposes!
});

const controlPlane = new ControlPlane(this, 'ControlPlane', {
auth: cognitoAuth,
systemAdminEmail: props.systemAdminEmail,
});

Expand Down
2 changes: 2 additions & 0 deletions src/utils/event-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ export class EventManager extends Construct implements IEventManager {
deactivateRequest: this.controlPlaneEventSource,
deactivateSuccess: this.applicationPlaneEventSource,
deactivateFailure: this.applicationPlaneEventSource,
tenantUserCreated: this.controlPlaneEventSource,
tenantUserDeleted: this.controlPlaneEventSource,
};

for (const key in this.supportedEvents) {
Expand Down
17 changes: 17 additions & 0 deletions test/event-manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,21 @@ describe('EventManager', () => {
testForRulesInOtherStack(controlPlaneStack);
testForRulesInOtherStack(eventManagerStack);
});

describe('supportedEvents in event-manager', () => {
const app = new cdk.App();
const eventManagerStack = new cdk.Stack(app, 'EventManagerStack');
const eventManager = new EventManager(eventManagerStack, 'EventManager');

// This ensures that when we try and use supportedEvents to create a rule,
// and key-in using a DetailType, a value exists for the source,
// which is used in the getOrCreateRule(...) function to create
// a new event-manager rule.
// (ex. "source: [this.supportedEvents[eventType]]")
it('should have values for all DetailType enum entries', () => {
Object.values(DetailType).forEach((detailTypeValues) => {
expect(eventManager.supportedEvents[detailTypeValues]).toBeDefined();
});
});
});
});

0 comments on commit ad7ca7a

Please sign in to comment.