constructor()

in core/src/notebook-platform/notebook-platform.ts [192:317]


  constructor(scope: Construct, id: string, props: NotebookPlatformProps) {
    super(scope, id);

    this.studioServicePolicy = [];
    this.studioUserPolicy = [];
    this.studioSubnetList = [];
    this.managedEndpointExecutionPolicyArnMapping = new Map<string, string>();
    this.authMode = props.studioAuthMode;

    if (props.idpArn !== undefined) {
      this.federatedIdPARN = props.idpArn;
    }

    //Create encryption key to use with cloudwatch loggroup and S3 bucket storing notebooks and
    this.notebookPlatformEncryptionKey = new Key(
      this,
      'KMS-key-'+ Utils.stringSanitizer(props.studioName), {
        enableKeyRotation: true,
      },
    );

    this.emrVirtualClusterName = 'emr-vc-' + Utils.stringSanitizer(props.studioName);
    this.emrEks = props.emrEks;

    //Get the list of private subnets in VPC
    this.studioSubnetList = this.emrEks.eksCluster.vpc.selectSubnets({
      onePerAz: true,
      subnetType: SubnetType.PRIVATE_WITH_NAT,
    }).subnetIds;


    //Create a virtual cluster a give it a name of 'emr-vc-'+studioName provided by user
    this.emrVirtCluster = this.emrEks.addEmrVirtualCluster(this, {
      createNamespace: true,
      eksNamespace: props.eksNamespace,
      name: Utils.stringSanitizer(this.emrVirtualClusterName),
    });

    //Create a security group to be attached to the studio workspaces
    this.workSpaceSecurityGroup = new SecurityGroup(this, 'workspaceSecurityGroup', {
      vpc: this.emrEks.eksCluster.vpc,
      securityGroupName: 'workSpaceSecurityGroup-'+props.studioName,
      allowAllOutbound: false,
    });

    //Tag workSpaceSecurityGroup to be used with EMR Studio
    Tags.of(this.workSpaceSecurityGroup).add('for-use-with-amazon-emr-managed-policies', 'true');

    //Create a security group to be attached to the engine for EMR
    //This is mandatory for Amazon EMR Studio although we are not using EMR on EC2
    this.engineSecurityGroup = new SecurityGroup(this, 'engineSecurityGroup', {
      vpc: this.emrEks.eksCluster.vpc,
      securityGroupName: 'engineSecurityGroup-'+props.studioName,
      allowAllOutbound: false,
    });

    //Tag engineSecurityGroup to be used with EMR Studio
    Tags.of(this.engineSecurityGroup).add('for-use-with-amazon-emr-managed-policies', 'true');

    //Create S3 bucket to store EMR Studio workspaces
    //Bucket is kept after destroying the construct
    this.workspacesBucket = new Bucket(this, 'WorkspacesBucket' + props.studioName, {
      bucketName: 'ara-workspaces-bucket-' + Aws.ACCOUNT_ID + '-' + Utils.stringSanitizer(props.studioName),
      enforceSSL: true,
      encryptionKey: this.notebookPlatformEncryptionKey,
      encryption: BucketEncryption.KMS,
      blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
    });

    //Create a Managed policy for Studio service role
    this.studioServicePolicy.push(ManagedPolicy.fromManagedPolicyArn(this,
      'StudioServiceManagedPolicy', createStudioServiceRolePolicy(this, this.notebookPlatformEncryptionKey.keyArn, this.workspacesBucket.bucketName,
        props.studioName),
    ));

    //Create a role for the Studio
    this.studioServiceRole = new Role(this, 'studioServiceRole', {
      assumedBy: new ServicePrincipal(NotebookPlatform.STUDIO_PRINCIPAL),
      roleName: 'studioServiceRole+' + Utils.stringSanitizer(props.studioName),
      managedPolicies: this.studioServicePolicy,
    });

    // Create an EMR Studio user role only if the user uses SSO as authentication mode
    if (props.studioAuthMode === 'SSO') {
      //Get Managed policy for Studio user role and put it in an array to be assigned to a user role
      this.studioUserPolicy.push(ManagedPolicy.fromManagedPolicyArn(this,
        'StudioUserManagedPolicy',
        createStudioUserRolePolicy(this, props.studioName, this.studioServiceRole.roleName),
      ));

      //Create a role for the EMR Studio user, this roles is further restricted by session policy for each user
      this.studioUserRole = new Role(this, 'studioUserRole', {
        assumedBy: new ServicePrincipal(NotebookPlatform.STUDIO_PRINCIPAL),
        roleName: 'studioUserRole+' + Utils.stringSanitizer(props.studioName),
        managedPolicies: this.studioUserPolicy,
      });
    }
    // Create the EMR Studio
    this.studioInstance = new CfnStudio(this, 'Studio', <CfnStudioProps>{
      authMode: props.studioAuthMode,
      defaultS3Location: 's3://' + this.workspacesBucket.bucketName + '/',
      engineSecurityGroupId: this.engineSecurityGroup.securityGroupId,
      name: props.studioName,
      serviceRole: this.studioServiceRole.roleArn,
      subnetIds: this.studioSubnetList,
      userRole: this.studioUserRole ? this.studioUserRole.roleArn : undefined,
      vpcId: this.emrEks.eksCluster.vpc.vpcId,
      workspaceSecurityGroupId: this.workSpaceSecurityGroup.securityGroupId,
      idpAuthUrl: props.idpAuthUrl ? props.idpAuthUrl : undefined,
      idpRelayStateParameterName: props.idpRelayStateParameterName ? props.idpRelayStateParameterName: undefined,
    });

    // Set the Studio URL and Studio Id this is used in session Mapping for
    // EMR Studio when {@linkcode addFederatedUsers} or {@linkcode addSSOUsers} are called
    this.studioName = props.studioName;

    //Set the Studio Id to use for SessionMapping
    this.studioId = this.studioInstance.attrStudioId;

    //Return EMR Studio URL as CfnOutput
    if (this.nestedStackParent != undefined) {
      new CfnOutput(this.nestedStackParent, `URL for EMR Studio: ${this.studioName}`, {
        value: this.studioInstance.attrUrl,
      });
    }
  }