in core/src/notebook-platform/notebook-platform.ts [325:446]
public addUser(userList: NotebookUserOptions []) {
//Initialize the managedEndpointArns
//Used to store the arn of managed endpoints after creation for each users
//This is used to update the IAM policy
let managedEndpointArns: string [] = [];
//let managedEndpointObjects: Map<string, CustomResource> = new Map <string, CustomResource> ();
let iamRolePolicy: ManagedPolicy;
let iamUserList: string [] = [];
//Loop through each user and create its managed endpoint(s) as defined by the user
for (let user of userList) {
//For each policy create a role and then pass it to addManageEndpoint to create an endpoint
user.notebookManagedEndpoints.forEach( (notebookManagedEndpoint, index) => {
//Check if the managedendpoint is already used in role which is created for a managed endpoint
//if there is no managedendpointArn create a new managedendpoint
//else get managedendpoint and push it to @managedEndpointArns
if (!this.managedEndpointExecutionPolicyArnMapping.has(notebookManagedEndpoint.executionPolicy.managedPolicyName)) {
//For each user or group, create a new managedEndpoint
//ManagedEndpoint ARN is used to update and scope the session policy of the user or group
let emrOnEksVersion: string | undefined = user.notebookManagedEndpoints[index].emrOnEksVersion;
let configOverride: string | undefined = user.notebookManagedEndpoints[index].configurationOverrides;
let managedEndpoint = this.emrEks.addManagedEndpoint(
this,
`${this.studioName}${Utils.stringSanitizer(notebookManagedEndpoint.executionPolicy.managedPolicyName)}`,
{
managedEndpointName: `${this.studioName}-${notebookManagedEndpoint.executionPolicy.managedPolicyName}`,
virtualClusterId: this.emrVirtCluster.attrId,
executionRole: this.emrEks.createExecutionRole(
this,
`${user.identityName}${index}`,
notebookManagedEndpoint.executionPolicy,
),
emrOnEksVersion: emrOnEksVersion ? emrOnEksVersion : undefined,
configurationOverrides: configOverride ? configOverride : undefined,
},
);
managedEndpoint.node.addDependency(this.emrEks);
//Get the Security Group of the ManagedEndpoint which is the Engine Security Group
let engineSecurityGroup: ISecurityGroup = SecurityGroup.fromSecurityGroupId(
this,
`engineSecurityGroup${user.identityName}${index}`,
managedEndpoint.getAttString('securityGroup'));
Tags.of(engineSecurityGroup).add('for-use-by-analytics-reference-architecture', 'true');
let vpcCidrBlock: string = this.emrEks.eksCluster.vpc.vpcCidrBlock;
//Update workspace Security Group to allow outbound traffic on port 18888 toward Engine Security Group
this.workSpaceSecurityGroup.addEgressRule(Peer.ipv4(vpcCidrBlock), Port.tcp(18888), 'Allow traffic to EMR');
this.engineSecurityGroup?.addIngressRule(Peer.ipv4(vpcCidrBlock), Port.tcp(18888), 'Allow traffic from EMR Studio');
this.workSpaceSecurityGroup.applyRemovalPolicy(RemovalPolicy.DESTROY);
//Tag the Security Group of the ManagedEndpoint to be used with EMR Studio
Tags.of(engineSecurityGroup).add('for-use-with-amazon-emr-managed-policies', 'true');
//Add the managedendpointArn to @managedEndpointExcutionPolicyArnMapping
//This is to avoid the creation an endpoint with the same policy twice
//Save resources and reduce the deployment time
// TODO check the emr version is the same => to be fixed on a later commit need to solve adding a tuple to a JS map
this.managedEndpointExecutionPolicyArnMapping.set(notebookManagedEndpoint.executionPolicy.managedPolicyName, managedEndpoint.getAttString('arn'));
//Push the managedendpoint arn to be used in to build the policy to attach to it
managedEndpointArns.push(managedEndpoint.getAttString('arn'));
} else {
let managedPolicyName = notebookManagedEndpoint.executionPolicy.managedPolicyName;
managedEndpointArns.push(<string> this.managedEndpointExecutionPolicyArnMapping.get(managedPolicyName));
}
});
if (this.authMode === 'IAM' && this.federatedIdPARN === undefined) {
//Create the role policy and gets its ARN
iamRolePolicy = createIAMRolePolicy(this, user, this.studioServiceRole.roleName,
managedEndpointArns, this.studioId);
let iamUserCredentials: string = createIAMUser(this, iamRolePolicy!, user.identityName);
if (this.nestedStackParent != undefined) {
new CfnOutput(this.nestedStackParent, `${user.identityName}`, {
value: iamUserCredentials,
});
}
} else if (this.authMode === 'IAM' && this.federatedIdPARN != undefined) {
//Create the role policy and gets its ARN
iamRolePolicy = createIAMRolePolicy(this, user, this.studioServiceRole.roleName,
managedEndpointArns, this.studioId);
createIAMFederatedRole(this, iamRolePolicy!, this.federatedIdPARN!, user.identityName, this.studioId);
} else if (this.authMode === 'SSO') {
//Create the session policy and gets its ARN
let sessionPolicyArn = createUserSessionPolicy(this, user, this.studioServiceRole.roleName,
managedEndpointArns, this.studioId);
if (user.identityType == 'USER' || user.identityType == 'GROUP') {
//Map a session to user or group
new CfnStudioSessionMapping(this, 'studioUser' + user.identityName + user.identityName, {
identityName: user.identityName,
identityType: user.identityType,
sessionPolicyArn: sessionPolicyArn,
studioId: this.studioId,
});
} else {
throw new Error(`identityType should be either USER or GROUP not ${user.identityType}`);
}
}
}
return iamUserList;
}