Skip to content

Commit 04acc9a

Browse files
(DL-22) Restrict Access to Glue Catalog Databases (#2502)
* refactor additional_glue_database implementation * add liberator databases access to parking * add tascomi db access to planning * add database access to cfs dept * add nndr access to revenues dept * add hben_raw_zone access to bens and housing needs dept * refactor additional_glue_database_access * ro and rw required when adding additional db access * restrict default permissions to department and undrestricted databases * add ctax_raw_zone access to revenues * move common department databases to local * add parking-ringgo-sftp-raw-zone access to parking department
1 parent 279d15d commit 04acc9a

File tree

3 files changed

+116
-27
lines changed

3 files changed

+116
-27
lines changed

terraform/core/05-departments.tf

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@ module "department_parking" {
7373
departmental_airflow_user = true
7474
mwaa_etl_scripts_bucket_arn = aws_s3_bucket.mwaa_etl_scripts_bucket.arn
7575
mwaa_key_arn = aws_kms_key.mwaa_key.arn
76+
additional_glue_database_access = {
77+
read_only = [
78+
"${local.identifier_prefix}-liberator*",
79+
"parking-ringgo-sftp-raw-zone",
80+
]
81+
read_write = []
82+
}
7683
}
7784

7885
module "department_finance" {
@@ -205,6 +212,10 @@ module "department_planning" {
205212
google_group_display_name = "[email protected]"
206213
mwaa_etl_scripts_bucket_arn = aws_s3_bucket.mwaa_etl_scripts_bucket.arn
207214
mwaa_key_arn = aws_kms_key.mwaa_key.arn
215+
additional_glue_database_access = {
216+
read_only = ["${local.identifier_prefix}-tascomi*"]
217+
read_write = []
218+
}
208219
}
209220

210221
module "department_unrestricted" {
@@ -305,6 +316,10 @@ module "department_benefits_and_housing_needs" {
305316
departmental_airflow_user = true
306317
mwaa_etl_scripts_bucket_arn = aws_s3_bucket.mwaa_etl_scripts_bucket.arn
307318
mwaa_key_arn = aws_kms_key.mwaa_key.arn
319+
additional_glue_database_access = {
320+
read_only = ["hben_raw_zone"]
321+
read_write = []
322+
}
308323
}
309324

310325
module "department_revenues" {
@@ -339,6 +354,13 @@ module "department_revenues" {
339354
departmental_airflow_user = true
340355
mwaa_etl_scripts_bucket_arn = aws_s3_bucket.mwaa_etl_scripts_bucket.arn
341356
mwaa_key_arn = aws_kms_key.mwaa_key.arn
357+
additional_glue_database_access = {
358+
read_only = [
359+
"nndr_raw_zone",
360+
"ctax_raw_zone",
361+
]
362+
read_write = []
363+
}
342364
}
343365

344366
module "department_environmental_services" {
@@ -421,16 +443,10 @@ module "department_housing" {
421443
actions = ["s3:Get*", "s3:List*", "s3:Put*", "s3:Delete*"]
422444
}
423445
]
424-
additional_glue_database_access = [
425-
{
426-
database_name = "housing_nec_migration"
427-
actions = ["glue:CreateTable", "glue:UpdateTable", "glue:DeleteTable", "glue:GetTable", "glue:GetTables", "glue:GetDatabase"]
428-
},
429-
{
430-
database_name = "housing_nec_migration_outputs"
431-
actions = ["glue:CreateTable", "glue:UpdateTable", "glue:DeleteTable", "glue:GetTable", "glue:GetTables", "glue:GetDatabase"]
432-
}
433-
]
446+
additional_glue_database_access = {
447+
read_only = []
448+
read_write = ["housing_nec_migration", "housing_nec_migration_outputs"]
449+
}
434450
}
435451

436452
module "department_children_and_education" {
@@ -598,4 +614,8 @@ module "department_children_family_services" {
598614
departmental_airflow_user = true
599615
mwaa_etl_scripts_bucket_arn = aws_s3_bucket.mwaa_etl_scripts_bucket.arn
600616
mwaa_key_arn = aws_kms_key.mwaa_key.arn
617+
additional_glue_database_access = {
618+
read_only = ["child_edu_refined", "hackney_casemanagement_live", "hackney_synergy_live"]
619+
read_write = []
620+
}
601621
}

terraform/modules/department/02-inputs-optional.tf

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,24 @@ variable "cloudtrail_bucket" {
7171
variable "additional_glue_database_access" {
7272
description = <<EOF
7373
Additional Glue database access to grant to the department.
74-
Allows specifying specific databases and the actions that can be performed on them.
74+
Databases are grouped by permission level.
75+
76+
Example:
77+
additional_glue_database_access = {
78+
read_only = ["database1", "database2*"]
79+
read_write = ["database3"]
80+
}
81+
82+
Permission levels:
83+
- "read_only": Grants Get* and BatchGet* permissions (for reading databases, tables, partitions)
84+
- "read_write": Grants Get*, BatchGet*, Create*, Update*, Delete*, BatchCreate*, BatchUpdate*, BatchDelete* permissions
7585
EOF
76-
type = list(object({
77-
database_name = string
78-
actions = list(string)
79-
}))
80-
default = []
86+
type = object({
87+
read_only = list(string)
88+
read_write = list(string)
89+
})
90+
default = {
91+
read_only = []
92+
read_write = []
93+
}
8194
}

terraform/modules/department/50-aws-iam-policies.tf

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,33 @@
11
// WARNING! All statement blocks MUST have a UNIQUE SID, this is to allow the individual documents to be merged.
22
// Statement blocks with the same SID will replace each other when merged.
33

4+
locals {
5+
glue_access_presets = {
6+
read_only = [
7+
"glue:Get*",
8+
"glue:BatchGet*",
9+
]
10+
read_write = [
11+
"glue:Get*",
12+
"glue:BatchGet*",
13+
"glue:Create*",
14+
"glue:Update*",
15+
"glue:Delete*",
16+
"glue:BatchCreate*",
17+
"glue:BatchUpdate*",
18+
"glue:BatchDelete*",
19+
]
20+
}
21+
22+
common_department_databases = [
23+
aws_glue_catalog_database.raw_zone_catalog_database.name,
24+
aws_glue_catalog_database.refined_zone_catalog_database.name,
25+
aws_glue_catalog_database.trusted_zone_catalog_database.name,
26+
"unrestricted-*-zone",
27+
"${var.identifier_prefix}-raw-zone-unrestricted-addresses-api"
28+
]
29+
}
30+
431
// S3 read only access policy
532
data "aws_iam_policy_document" "read_only_s3_department_access" {
633
# Include CloudTrail bucket access for data-and-insight department
@@ -176,21 +203,28 @@ data "aws_iam_policy_document" "read_only_glue_access" {
176203
"glue:SearchTables",
177204
"glue:Query*",
178205
]
179-
resources = ["*"]
206+
resources = flatten([
207+
["arn:aws:glue:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:catalog"],
208+
[for db in local.common_department_databases : "arn:aws:glue:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:database/${db}"],
209+
[for db in local.common_department_databases : "arn:aws:glue:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:table/${db}/*"]
210+
])
180211
}
181212

182213
dynamic "statement" {
183-
for_each = var.additional_glue_database_access
184-
iterator = additional_db_access
214+
for_each = {
215+
read_only = var.additional_glue_database_access.read_only
216+
read_write = var.additional_glue_database_access.read_write
217+
}
218+
iterator = access_level
185219
content {
186-
sid = "AdditionalGlueDatabaseAccess${replace(additional_db_access.value.database_name, "/[^a-zA-Z0-9]/", "")}"
220+
sid = "AdditionalGlueDatabaseAccess${title(replace(access_level.key, "_", ""))}"
187221
effect = "Allow"
188-
actions = additional_db_access.value.actions
189-
resources = [
190-
"arn:aws:glue:eu-west-2:${data.aws_caller_identity.current.account_id}:catalog",
191-
"arn:aws:glue:eu-west-2:${data.aws_caller_identity.current.account_id}:database/${additional_db_access.value.database_name}",
192-
"arn:aws:glue:eu-west-2:${data.aws_caller_identity.current.account_id}:table/${additional_db_access.value.database_name}/*"
193-
]
222+
actions = local.glue_access_presets[access_level.key]
223+
resources = length(access_level.value) > 0 ? flatten([
224+
["arn:aws:glue:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:catalog"],
225+
[for db in access_level.value : "arn:aws:glue:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:database/${db}"],
226+
[for db in access_level.value : "arn:aws:glue:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:table/${db}/*"]
227+
]) : []
194228
}
195229
}
196230
}
@@ -521,7 +555,29 @@ data "aws_iam_policy_document" "glue_access" {
521555
"glue:GetDatabases",
522556
"glue:Query*",
523557
]
524-
resources = ["*"]
558+
resources = flatten([
559+
["arn:aws:glue:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:catalog"],
560+
[for db in local.common_department_databases : "arn:aws:glue:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:database/${db}"],
561+
[for db in local.common_department_databases : "arn:aws:glue:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:table/${db}/*"]
562+
])
563+
}
564+
565+
dynamic "statement" {
566+
for_each = {
567+
read_only = var.additional_glue_database_access.read_only
568+
read_write = var.additional_glue_database_access.read_write
569+
}
570+
iterator = access_level
571+
content {
572+
sid = "AdditionalGlueDatabaseFullAccess${title(replace(access_level.key, "_", ""))}"
573+
effect = "Allow"
574+
actions = local.glue_access_presets[access_level.key]
575+
resources = length(access_level.value) > 0 ? flatten([
576+
["arn:aws:glue:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:catalog"],
577+
[for db in access_level.value : "arn:aws:glue:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:database/${db}"],
578+
[for db in access_level.value : "arn:aws:glue:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:table/${db}/*"]
579+
]) : []
580+
}
525581
}
526582
}
527583

0 commit comments

Comments
 (0)