Skip to content

Commit 98aa956

Browse files
committed
Additional lake formation permission support.
1 parent fb37d05 commit 98aa956

File tree

10 files changed

+115
-59
lines changed

10 files changed

+115
-59
lines changed

DeployChemblOpenTargetsEnv.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
#!/bin/sh
12
npm run build
23
cdk bootstrap
34
cdk deploy BaselineStack --require-approval never
5+
currentPrincipalArn=$(aws sts get-caller-identity --query Arn --output text)
6+
jq '.context.starterLakeFormationAdmin = $currentPrincipalArn' --arg currentPrincipalArn $currentPrincipalArn cdk.json > tmp.$$.json && mv tmp.$$.json cdk.json
47
cdk deploy CoreDataLake --require-approval never
58
cdk deploy ChemblStack --require-approval never
69
cdk deploy OpenTargetsStack --require-approval never

bin/aws.ts

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const baseline = new BaselineStack(app, 'BaselineStack');
1515

1616

1717
const coreDataLake = new DataLakeStack(app, 'CoreDataLake', {
18-
18+
starterLakeFormationAdminPrincipalArn: app.node.tryGetContext("starterLakeFormationAdmin")
1919
});
2020

2121
const chemblStack = new ChemblStack(app, 'ChemblStack', {
@@ -36,6 +36,9 @@ const analyticsStack = new AnalyticsStack(app, 'AnalyticsStack', {
3636
});
3737

3838

39+
40+
41+
3942
chemblStack.grantIamRead(analyticsStack.NotebookRole);
4043
openTargetsStack.grantIamRead(analyticsStack.NotebookRole);
4144

@@ -46,44 +49,44 @@ openTargetsStack.grantIamRead(analyticsStack.NotebookRole);
4649

4750

4851

49-
const exampleUser = iam.User.fromUserName(coreDataLake, 'exampleGrantee', 'paul1' );
52+
// const exampleUser = iam.User.fromUserName(coreDataLake, 'exampleGrantee', 'paul1' );
5053

51-
var exampleGrant: DataLakeEnrollment.TablePermissionGrant = {
52-
tables: ["association_data", "evidence_data","target_list","disease_list"],
53-
DatabasePermissions: [DataLakeEnrollment.DatabasePermission.Alter, DataLakeEnrollment.DatabasePermission.CreateTable, DataLakeEnrollment.DatabasePermission.Drop],
54-
GrantableDatabasePermissions: [DataLakeEnrollment.DatabasePermission.Alter, DataLakeEnrollment.DatabasePermission.CreateTable, DataLakeEnrollment.DatabasePermission.Drop],
55-
TablePermissions: [DataLakeEnrollment.TablePermission.Select, DataLakeEnrollment.TablePermission.Insert, DataLakeEnrollment.TablePermission.Delete],
56-
GrantableTablePermissions: [DataLakeEnrollment.TablePermission.Select]
57-
};
54+
// var exampleGrant: DataLakeEnrollment.TablePermissionGrant = {
55+
// tables: ["association_data", "evidence_data","target_list","disease_list"],
56+
// DatabasePermissions: [DataLakeEnrollment.DatabasePermission.Alter, DataLakeEnrollment.DatabasePermission.CreateTable, DataLakeEnrollment.DatabasePermission.Drop],
57+
// GrantableDatabasePermissions: [DataLakeEnrollment.DatabasePermission.Alter, DataLakeEnrollment.DatabasePermission.CreateTable, DataLakeEnrollment.DatabasePermission.Drop],
58+
// TablePermissions: [DataLakeEnrollment.TablePermission.Select, DataLakeEnrollment.TablePermission.Insert, DataLakeEnrollment.TablePermission.Delete],
59+
// GrantableTablePermissions: [DataLakeEnrollment.TablePermission.Select]
60+
// };
5861

59-
openTargetsStack.grantTablePermissions(exampleUser, exampleGrant);
62+
// openTargetsStack.grantTablePermissions(exampleUser, exampleGrant);
6063

6164

6265

6366

64-
// In the example below, we are using the compound_structures table from ChEMBL. It has the following table definition:
65-
// ['molregno', 'molfile', 'standard_inchi', 'standard_inchi_key', 'canonical_smiles']
66-
// Lets say we want to give a principal ONLY select permissions to everything in the compound_structures table BUT the 'canonical_smiles' column.
67+
// // In the example below, we are using the compound_structures table from ChEMBL. It has the following table definition:
68+
// // ['molregno', 'molfile', 'standard_inchi', 'standard_inchi_key', 'canonical_smiles']
69+
// // Lets say we want to give a principal ONLY select permissions to everything in the compound_structures table BUT the 'canonical_smiles' column.
6770

68-
var exampleTableWithColumnsGrant: DataLakeEnrollment.TableWithColumnPermissionGrant = {
69-
table: "chembl_25_public_compound_structures",
70-
// Note that we are NOT including 'canonical_smiles'. That effectivley prevents this user from querying that column.
71-
columns: ['molregno', 'molfile', 'standard_inchi', 'standard_inchi_key'],
72-
DatabasePermissions: [],
73-
GrantableDatabasePermissions: [],
74-
TableColumnPermissions: [DataLakeEnrollment.TablePermission.Select],
75-
GrantableTableColumnPermissions: []
76-
};
71+
// var exampleTableWithColumnsGrant: DataLakeEnrollment.TableWithColumnPermissionGrant = {
72+
// table: "chembl_25_public_compound_structures",
73+
// // Note that we are NOT including 'canonical_smiles'. That effectivley prevents this user from querying that column.
74+
// columns: ['molregno', 'molfile', 'standard_inchi', 'standard_inchi_key'],
75+
// DatabasePermissions: [],
76+
// GrantableDatabasePermissions: [],
77+
// TableColumnPermissions: [DataLakeEnrollment.TablePermission.Select],
78+
// GrantableTableColumnPermissions: []
79+
// };
7780

78-
var exampleTableWithColumnsGrant_WithWildCard: DataLakeEnrollment.TableWithColumnPermissionGrant = {
79-
table: "chembl_25_public_compound_structures",
80-
wildCardFilter: DataLakeEnrollment.TableWithColumnFilter.Exclude,
81-
columns: ['canonical_smiles'],
82-
DatabasePermissions: [],
83-
GrantableDatabasePermissions: [],
84-
TableColumnPermissions: [DataLakeEnrollment.TablePermission.Select],
85-
GrantableTableColumnPermissions: []
86-
};
81+
// var exampleTableWithColumnsGrant_WithWildCard: DataLakeEnrollment.TableWithColumnPermissionGrant = {
82+
// table: "chembl_25_public_compound_structures",
83+
// wildCardFilter: DataLakeEnrollment.TableWithColumnFilter.Exclude,
84+
// columns: ['canonical_smiles'],
85+
// DatabasePermissions: [],
86+
// GrantableDatabasePermissions: [],
87+
// TableColumnPermissions: [DataLakeEnrollment.TablePermission.Select],
88+
// GrantableTableColumnPermissions: []
89+
// };
8790

88-
// Note that exampleTableWithColumnsGrant exampleTableWithColumnsGrant_WithWildCard grants the same effecitve permissions. One just uses a the wildcard.
89-
chemblStack.grantTableWithColumnPermissions(exampleUser, exampleTableWithColumnsGrant);
91+
// // Note that exampleTableWithColumnsGrant exampleTableWithColumnsGrant_WithWildCard grants the same effecitve permissions. One just uses a the wildcard.
92+
// chemblStack.grantTableWithColumnPermissions(exampleUser, exampleTableWithColumnsGrant);

cdk.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
{
2-
"app": "npx ts-node bin/aws.ts"
2+
"app": "npx ts-node bin/aws.ts",
3+
"context": {
4+
"starterLakeFormationAdmin": "XXXX-this value gets populated by DeployChemblOpenTargetsEnv.sh script-XXXXX"
5+
}
36
}

lib/chembl-25-stack.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ export class ChemblStack extends DataSetStack{
4242
"--DL_REGION": cdk.Stack.of(this).region,
4343
"--GLUE_SRC_DATABASE": "chembl_25_src"
4444
}
45-
});
45+
});
46+
47+
4648
}
4749
}
4850

lib/constructs/data-lake-enrollment.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export class DataLakeEnrollment extends cdk.Construct {
2727
this.CoarseIamPolciesApplied = false;
2828

2929
}
30+
3031

3132
public createCoarseIamPolicy(){
3233

@@ -277,7 +278,7 @@ export class DataLakeEnrollment extends cdk.Construct {
277278

278279
}
279280

280-
public grantDatabasePermission(principal: iam.IPrincipal, permissionGrant: DataLakeEnrollment.DatabasePermissionGrant){
281+
public grantDatabasePermission(principal: iam.IPrincipal, permissionGrant: DataLakeEnrollment.DatabasePermissionGrant, includeSourceDb: boolean = false){
281282

282283

283284
var grantIdPrefix = ""
@@ -293,7 +294,12 @@ export class DataLakeEnrollment extends cdk.Construct {
293294

294295
if(resolvedPrincipalType === iam.Role) {
295296
const resolvedPrincipal = principal as iam.Role;
296-
grantIdPrefix = `${resolvedPrincipal.roleArn}-${this.DataSetName}`
297+
298+
if(permissionGrant.GrantResourcePrefix){
299+
grantIdPrefix = `${permissionGrant.GrantResourcePrefix}-${this.DataSetName}`
300+
}else{
301+
grantIdPrefix = `${resolvedPrincipal.roleName}-${this.DataSetName}`
302+
}
297303
dataLakePrincipal = { dataLakePrincipalIdentifier: resolvedPrincipal.roleArn };
298304
}
299305

@@ -305,6 +311,18 @@ export class DataLakeEnrollment extends cdk.Construct {
305311

306312
this.createLakeFormationPermission(`${grantIdPrefix}-databaseGrant`,dataLakePrincipal , databaseResourceProperty, permissionGrant.DatabasePermissions, permissionGrant.GrantableDatabasePermissions)
307313

314+
if(includeSourceDb){
315+
316+
databaseResourceProperty = {
317+
//dataLocationResource: {resourceArn: this.DataEnrollment.DataLakeBucketName},
318+
databaseResource: {name: this.DataEnrollment.Dataset_Source.databaseName}
319+
};
320+
321+
this.createLakeFormationPermission(`${grantIdPrefix}-databaseSrcGrant`,dataLakePrincipal , databaseResourceProperty, permissionGrant.DatabasePermissions, permissionGrant.GrantableDatabasePermissions)
322+
323+
}
324+
325+
308326
}
309327

310328

@@ -462,6 +480,7 @@ export namespace DataLakeEnrollment
462480
export interface DatabasePermissionGrant {
463481
DatabasePermissions: Array<DatabasePermission>;
464482
GrantableDatabasePermissions: Array<DatabasePermission>;
483+
GrantResourcePrefix?: string;
465484
}
466485

467486

lib/constructs/rds-data-set-enrollment.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export class RDSPostgresDataSetEnrollment extends DataLakeEnrollment {
3434
});
3535

3636
}
37-
37+
3838
this.DataEnrollment = new DataSetEnrollment(this, 'rdsDatasetEnrollment', {
3939
dataLakeBucket: props.dataLakeBucket,
4040
dataSetName: dataSetName,
@@ -61,7 +61,15 @@ export class RDSPostgresDataSetEnrollment extends DataLakeEnrollment {
6161
GlueScriptArguments: props.GlueScriptArguments
6262

6363
});
64-
64+
65+
6566
this.createCoarseIamPolicy();
67+
68+
this.grantDatabasePermission(this.DataEnrollment.DataSetGlueRole, {
69+
DatabasePermissions: [DataLakeEnrollment.DatabasePermission.All],
70+
GrantableDatabasePermissions: [DataLakeEnrollment.DatabasePermission.All],
71+
GrantResourcePrefix: `${props.DataSetName}RoleGrant`
72+
}, true);
73+
6674
}
6775
}

lib/constructs/s3-data-set-enrollment.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export class S3dataSetEnrollment extends DataLakeEnrollment{
4747

4848
}
4949

50-
this.DataEnrollment = new DataSetEnrollment(this, 'openTargetsEnrollment', {
50+
this.DataEnrollment = new DataSetEnrollment(this, `${props.DataSetName}-s3Enrollment`, {
5151
dataLakeBucket: props.dataLakeBucket,
5252
dataSetName: dataSetName,
5353
SourceAccessPolicy: s3AccessPolicy,
@@ -58,6 +58,15 @@ export class S3dataSetEnrollment extends DataLakeEnrollment{
5858
GlueScriptArguments: props.GlueScriptArguments
5959
});
6060

61-
this.createCoarseIamPolicy();
61+
this.createCoarseIamPolicy();
62+
63+
64+
this.grantDatabasePermission(this.DataEnrollment.DataSetGlueRole, {
65+
DatabasePermissions: [DataLakeEnrollment.DatabasePermission.All],
66+
GrantableDatabasePermissions: [DataLakeEnrollment.DatabasePermission.All],
67+
GrantResourcePrefix: `${props.DataSetName}RoleGrant`
68+
}, true);
69+
70+
6271
}
6372
}

lib/stacks/datalake-stack.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import cfn = require("@aws-cdk/aws-cloudformation");
88
import s3 = require('@aws-cdk/aws-s3');
99
import s3assets = require('@aws-cdk/aws-s3-assets');
1010
import lakeformation = require('@aws-cdk/aws-lakeformation');
11-
import lambda = require('@aws-cdk/aws-lambda')
11+
import { CustomResource } from '@aws-cdk/core';
12+
import * as cr from '@aws-cdk/custom-resources';
13+
import lambda = require('@aws-cdk/aws-lambda');
1214
import fs = require('fs');
1315

1416
import { DataSetEnrollmentProps, DataSetEnrollment } from '../constructs/data-set-enrollment';
1517

1618
export interface DataLakeStackProps extends cdk.StackProps {
17-
19+
starterLakeFormationAdminPrincipalArn: string;
1820
}
1921

2022
export class DataLakeStack extends cdk.Stack {
@@ -25,6 +27,7 @@ export class DataLakeStack extends cdk.Stack {
2527
public readonly LakeFormationResource: lakeformation.CfnResource;
2628
public readonly PrimaryAthenaWorkgroup: athena.CfnWorkGroup;
2729
private readonly bucketRole: iam.Role;
30+
private readonly starterAdminArn: string;
2831

2932
public grantAthenaResultsBucketPermission(principal: iam.IPrincipal){
3033

@@ -63,9 +66,14 @@ export class DataLakeStack extends cdk.Stack {
6366
super(scope, id, props);
6467

6568
this.DataLakeBucket = new s3.Bucket(this, 'dataLakeBucket');
66-
this.AthenaResultsBucket = new s3.Bucket(this, 'athenaResultsBucket');
67-
68-
69+
this.AthenaResultsBucket = new s3.Bucket(this, 'athenaResultsBucket');
70+
71+
new lakeformation.CfnDataLakeSettings(this, 'starterAdminPermission', {
72+
admins: [{
73+
dataLakePrincipalIdentifier: props.starterLakeFormationAdminPrincipalArn
74+
}]
75+
});
76+
6977
const coarseAthenaResultBucketAccess = {
7078
"Version": "2012-10-17",
7179
"Statement": [

lib/stacks/dataset-stack.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class DataSetStack extends cdk.Stack {
2424
this.DataLake = props.DataLake;
2525
}
2626

27-
27+
2828
public grantDatabasePermissions( principal: iam.IPrincipal, permissionGrant: DataLakeEnrollment.DatabasePermissionGrant){
2929
this.Enrollment.grantDatabasePermission(principal, permissionGrant);
3030
}

package.json

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,26 @@
1111
"cdk": "cdk"
1212
},
1313
"devDependencies": {
14-
"@aws-cdk/assert": "^1.36.1",
14+
"@aws-cdk/assert": "^1.38.0",
1515
"@types/jest": "^25.2.1",
16-
"@types/node": "13.13.4",
17-
"aws-cdk": "^1.36.1",
16+
"@types/node": "^13.13.6",
17+
"aws-cdk": "^1.38.0",
1818
"jest": "^25.5.2",
1919
"ts-jest": "^25.4.0",
2020
"ts-node": "^8.9.1",
2121
"typescript": "~3.8.3"
2222
},
2323
"dependencies": {
24-
"@aws-cdk/aws-athena": "^1.36.1",
25-
"@aws-cdk/aws-cloudformation": "^1.36.1",
26-
"@aws-cdk/aws-ec2": "^1.36.1",
27-
"@aws-cdk/aws-glue": "^1.36.1",
28-
"@aws-cdk/aws-lakeformation": "^1.36.1",
29-
"@aws-cdk/aws-lambda": "^1.36.1",
30-
"@aws-cdk/aws-rds": "^1.36.1",
31-
"@aws-cdk/aws-sagemaker": "^1.36.1",
32-
"@aws-cdk/core": "^1.36.1",
24+
"@aws-cdk/aws-athena": "^1.38.0",
25+
"@aws-cdk/aws-cloudformation": "^1.38.0",
26+
"@aws-cdk/aws-ec2": "^1.38.0",
27+
"@aws-cdk/aws-glue": "^1.38.0",
28+
"@aws-cdk/aws-lakeformation": "^1.38.0",
29+
"@aws-cdk/aws-lambda": "^1.38.0",
30+
"@aws-cdk/aws-rds": "^1.38.0",
31+
"@aws-cdk/aws-sagemaker": "^1.38.0",
32+
"@aws-cdk/core": "^1.38.0",
33+
"@aws-cdk/custom-resources": "^1.38.0",
3334
"source-map-support": "^0.5.19",
3435
"update": "^0.7.4"
3536
}

0 commit comments

Comments
 (0)