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

feat: QuickSightSubscription construct #505

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions framework/.projen/tasks.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

588 changes: 588 additions & 0 deletions framework/API.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions framework/src/consumption/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
export * from './redshift';
export * from './athena';
export * from './opensearch';
export * from './quicksight';
5 changes: 5 additions & 0 deletions framework/src/consumption/lib/quicksight/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

export * from './quicksight-subscription';
export * from './quicksight-subscription-props';
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { Duration, RemovalPolicy } from 'aws-cdk-lib';


/**
* The properties for the `QuickSightSubscription` construct
*/

export interface QuickSightSubscriptionProps {

/**
* The name of your Amazon QuickSight account.
* This name is unique over all of Amazon Web Services, and it appears only when users sign in.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is => must ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, will change it

* You can't change AccountName value after the Amazon QuickSight account is created.
*/
readonly accountName: string;

/**
* The email address that you want Amazon QuickSight to send notifications to regarding your Amazon QuickSight account or Amazon QuickSight subscription.
*/
readonly notificationEmail: string;

/**
* The edition of Amazon QuickSight that you want your account to have. Currently, you can choose from ENTERPRISE or ENTERPRISE_AND_Q .
* @default - ENTERPRISE is used as default.
*/
readonly edition: QuickSightEdition;

/**
* The Amazon Web Services account ID of the account that you're using to create your Amazon QuickSight account.
*/
readonly awsAccountId: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the benefit of configuring a different account than the CDK one?

Copy link
Author

@enriquh enriquh May 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mm, this could be benefitial to support the creation of pipelines if we want to support them in the future:

For me the CDK account would be the one used for the development account below in the architecture and then the user would be able to create constants for DEV, PRE, PRO (or any additional stages) they would want to configure. Does it make sense ?

image



/**
* The method that you want to use to authenticate your Amazon QuickSight account.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make this an enum

Copy link
Author

@enriquh enriquh Apr 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack.

* Only IAM_IDENTITY_CENTER, IAM_AND_QUICKSIGHT and IAM_ONLY are supported
* @default
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove @default

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

*/
readonly authenticationMethod: QuickSightAuthenticationMethod;


/**
* The admin group associated with your Active Directory or IAM Identity Center account. This field is required as IAM_IDENTITY_CENTER is
* the only supported authentication method of the new Amazon QuickSight account
*/
readonly adminGroup: string[];


/**
* The author group associated with your IAM Identity Center account.
*/
readonly authorGroup: string[];

/**
* The reader group associated with your IAM Identity Center account.
*/
readonly readerGroup: string[];

/**
* The region to use as main QuickSight region (used to store configuration and identities info)
*/
readonly identityRegion: string;

/**
* The timeout for the QuickSight account subscription.
* @default - 5mins
*/
readonly executionTimeout?: Duration;

/**
* The removal policy when deleting the CDK resource.
* If DESTROY is selected, context value `@data-solutions-framework-on-aws/removeDataOnDestroy` needs to be set to true.
* Otherwise, the removalPolicy is reverted to RETAIN.
* @default - The resources are not deleted (`RemovalPolicy.RETAIN`).
*/
readonly removalPolicy?: RemovalPolicy;

}

export enum QuickSightAuthenticationMethod {
IAM_IDENTITY_CENTER = 'IAM_IDENTITY_CENTER',
IAM_AND_QUICKSIGHT = 'IAM_AND_QUICKSIGHT',
IAM_ONLY = 'IAM_ONLY'
}

export enum QuickSightEdition {
ENTERPRISE = 'ENTERPRISE',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add another option?

Copy link
Author

@enriquh enriquh May 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can add the ENTERPRISE_AND_Q (as standard is rarely used and also won't support templates, or assets as bundle functionality so will break the support to pipelines once we support them).

The only thing with supporting ENTERPRISE_AND_Q is that we need to make aware the customer of the 250$/month fee of enabling Q in the account (irrelevant on whether they use it or no)

}
229 changes: 229 additions & 0 deletions framework/src/consumption/lib/quicksight/quicksight-subscription.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { CustomResource, Duration, RemovalPolicy } from 'aws-cdk-lib';
import { IRole, PolicyDocument, Role, ServicePrincipal, PolicyStatement, Effect } from 'aws-cdk-lib/aws-iam';
import { IFunction } from 'aws-cdk-lib/aws-lambda';
import { ILogGroup } from 'aws-cdk-lib/aws-logs';
import { Construct } from 'constructs';
import { QuickSightSubscriptionProps, QuickSightAuthenticationMethod } from './quicksight-subscription-props';
import { Context, TrackedConstruct, TrackedConstructProps } from '../../../utils';
import { DsfProvider } from '../../../utils/lib/dsf-provider';


/**
* Creates an asynchronous custom resource that handles the creation of a QuickSight subscription
*
* @example
* const subscription = new dsf.consumption.QuickSightSubscription(this, 'RedshiftNamespace', {
* name: "default",
* dbName: 'defaultdb',
* });
*
*/

export class QuickSightSubscription extends TrackedConstruct {

/**
*
*/
public static readonly RESOURCE_TYPE = 'Custom::QuickSightSubscription';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be private or directly stored in the constructor

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will move it to the constructor along with the custom resource creation


/**
* The CloudWatch Log Group for the QuickSight account subscription submission
*/
public readonly submitLogGroup: ILogGroup;
/**
* The Lambda Function for the the Redshift Data submission
*/
public readonly submitFunction: IFunction;
/**
* The IAM Role for the QuickSight account subscription execution
*/
public readonly executionRole: IRole;

/**
* The CloudWatch Log Group for the QuickSight account subscription status checks
*/
public readonly statusLogGroup: ILogGroup;
/**
* The Lambda Function for the QuickSight account subscription status checks
*/
public readonly statusFunction: IFunction;

/**
* The CloudWatch Log Group for the QuickSight account subscription cleaning up lambda
*/
public readonly cleanUpLogGroup?: ILogGroup;
/**
* The Lambda function for the QuickSight account subscription cleaning up lambda
*/
public readonly cleanUpFunction?: IFunction;
/**
* The IAM Role for the the QuickSight account subscription cleaning up lambda
*/
public readonly cleanUpRole?: IRole;

/**
* The name of your Amazon QuickSight account. This name is unique over all of Amazon Web Services, and it appears only when users sign in.
* You can't change AccountName value after the Amazon QuickSight account is created.
*/
public readonly accountName: string;

/**
* The email address that you want Amazon QuickSight to send notifications to regarding your Amazon QuickSight account or Amazon QuickSight subscription.
*/
readonly notificationEmail: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be private? same for the following members?


/**
* The admin group associated with your Active Directory or IAM Identity Center account. This field is required as IAM_IDENTITY_CENTER is
* the only supported authentication method of the new Amazon QuickSight account
*/
readonly adminGroup: string[];

/**
* The author group associated with your IAM Identity Center account.
*/
readonly authorGroup: string[];

/**
* The reader group associated with your IAM Identity Center account.
*/
readonly readerGroup: string[];

/**
* The region to use as main QuickSight region (used to store configuration and identities info)
*/
readonly identityRegion: string;

private readonly removalPolicy: RemovalPolicy;

private readonly serviceToken: string;
private readonly policyActions: string[];

constructor (scope: Construct, id: string, props: QuickSightSubscriptionProps) {
const trackedConstructProps: TrackedConstructProps = {
trackingTag: QuickSightSubscription.name,
};
super(scope, id, trackedConstructProps);

this.removalPolicy = Context.revertRemovalPolicy(scope, props.removalPolicy);
this.accountName = props.accountName;
this.notificationEmail = props.notificationEmail;
this.adminGroup = props.adminGroup;
this.authorGroup = props.authorGroup;
this.readerGroup = props.readerGroup;
this.identityRegion = props.identityRegion;

this.policyActions = [
'quicksight:Subscribe',
'quicksight:UpdateAccountSettings',
'quicksight:Create*',
'quicksight:Unsubscribe',
'quicksight:DescribeAccountSubscription',
'sso:GetManagedApplicationInstance',
'sso:CreateManagedApplicationInstance',
'sso:GetManagedApplicationInstance',
'sso:DeleteManagedApplicationInstance',
'sso:GetManagedApplicationInstance',
'sso:DescribeGroup',
'sso:SearchGroups',
'sso:GetProfile',
'sso:AssociateProfile',
'sso:DisassociateProfile',
'sso:ListProfiles',
'sso:ListDirectoryAssociations',
'sso:DescribeRegisteredRegions',
];

if (props.authenticationMethod != QuickSightAuthenticationMethod.IAM_IDENTITY_CENTER) {
this.policyActions = this.policyActions.concat(
[
'ds:AuthorizeApplication',
'ds:UnauthorizeApplication',
'ds:CheckAlias',
'ds:CreateAlias',
'ds:DescribeDirectories',
'ds:DescribeTrusts',
'ds:DeleteDirectory',
'ds:CreateIdentityPoolDirectory',
],
);
}

this.executionRole = new Role(this, 'Role', {
assumedBy: new ServicePrincipal('lambda.amazonaws.com'),
inlinePolicies: {
QuickSightSubscription: new PolicyDocument({
statements: [
new PolicyStatement({
effect: Effect.ALLOW,
actions: this.policyActions,
resources: ['*'],
}),
],
}),
},
});

const timeout = props.executionTimeout ?? Duration.minutes(5);

const provider = new DsfProvider(this, 'CrProvider', {
providerName: 'QuickSightSubscriptionProvider',
onEventHandlerDefinition: {
depsLockFilePath: __dirname+'/resources/QuickSightSubscription/package-lock.json',
entryFile: __dirname+'/resources/QuickSightSubscription/index.mjs',
handler: 'index.onEventHandler',
environment: {
AUTHENTICATION_METHOD: props.authenticationMethod,
AWS_ACCOUNT_ID: props.awsAccountId,
EDITION: props.edition,
IDENTITY_REGION: props.identityRegion,
},
iamRole: this.executionRole,
timeout,
},
isCompleteHandlerDefinition: {
iamRole: this.executionRole,
handler: 'index.isCompleteHandler',
depsLockFilePath: __dirname+'/resources/QuickSightSubscription/package-lock.json',
entryFile: __dirname+'/resources/QuickSightSubscription/index.mjs',
timeout,
environment: {
AUTHENTICATION_METHOD: props.authenticationMethod,
AWS_ACCOUNT_ID: props.awsAccountId,
EDITION: props.edition,
IDENTITY_REGION: props.identityRegion,
},
},
queryInterval: Duration.seconds(10),
removalPolicy: this.removalPolicy,
});

this.serviceToken = provider.serviceToken;
this.submitLogGroup = provider.onEventHandlerLogGroup;
this.statusLogGroup = provider.isCompleteHandlerLog!;
this.cleanUpLogGroup = provider.cleanUpLogGroup;
this.submitFunction = provider.onEventHandlerFunction;
this.statusFunction = provider.isCompleteHandlerFunction!;
this.cleanUpFunction = provider.cleanUpFunction;
this.cleanUpRole = provider.cleanUpRole;

}


public createQuickSightSubscription() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you bundle the custom resource directly in the constructor?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

return new CustomResource(this, 'QuickSightSubscription', {
resourceType: QuickSightSubscription.RESOURCE_TYPE,
serviceToken: this.serviceToken,
properties: {
accountName: this.accountName,
notificationEmail: this.notificationEmail,
readerGroup: this.readerGroup,
authorGroup: this.authorGroup,
adminGroup: this.adminGroup,
},
removalPolicy: this.removalPolicy,
});
}
}
Loading
Loading