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: Lake Formation add external data filtering and session tags. #30207

Merged
merged 8 commits into from
Apr 17, 2023
7 changes: 7 additions & 0 deletions .changelog/30207.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
resource/aws_lakeformation_data_lake_settings: Add `allow_external_data_filtering`, `external_data_filtering_allow_list` and `authorized_session_tag_value_list` arguments
```

```release-note:enhancement
data-source/aws_lakeformation_data_lake_settings: Add `allow_external_data_filtering`, `external_data_filtering_allow_list` and `authorized_session_tag_value_list` attributes
```
73 changes: 69 additions & 4 deletions internal/service/lakeformation/data_lake_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func ResourceDataLakeSettings() *schema.Resource {
UpdateWithoutTimeout: resourceDataLakeSettingsCreate,
ReadWithoutTimeout: resourceDataLakeSettingsRead,
DeleteWithoutTimeout: resourceDataLakeSettingsDelete,

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Expand All @@ -41,6 +42,16 @@ func ResourceDataLakeSettings() *schema.Resource {
ValidateFunc: verify.ValidARN,
},
},
"allow_external_data_filtering": {
Type: schema.TypeBool,
Optional: true,
},
"authorized_session_tag_value_list": {
Type: schema.TypeList,
Computed: true,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"catalog_id": {
Type: schema.TypeString,
ForceNew: true,
Expand Down Expand Up @@ -96,6 +107,15 @@ func ResourceDataLakeSettings() *schema.Resource {
},
},
},
"external_data_filtering_allow_list": {
Type: schema.TypeSet,
Computed: true,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validPrincipal,
},
},
"trusted_resource_owners": {
Type: schema.TypeList,
Computed: true,
Expand All @@ -121,6 +141,18 @@ func resourceDataLakeSettingsCreate(ctx context.Context, d *schema.ResourceData,

settings := &lakeformation.DataLakeSettings{}

if v, ok := d.GetOk("admins"); ok {
settings.DataLakeAdmins = expandDataLakeSettingsAdmins(v.(*schema.Set))
}

if v, ok := d.GetOk("allow_external_data_filtering"); ok {
settings.AllowExternalDataFiltering = aws.Bool(v.(bool))
}

if v, ok := d.GetOk("authorized_session_tag_value_list"); ok {
settings.AuthorizedSessionTagValueList = flex.ExpandStringList(v.([]interface{}))
}

if v, ok := d.GetOk("create_database_default_permissions"); ok {
settings.CreateDatabaseDefaultPermissions = expandDataLakeSettingsCreateDefaultPermissions(v.([]interface{}))
}
Expand All @@ -129,8 +161,8 @@ func resourceDataLakeSettingsCreate(ctx context.Context, d *schema.ResourceData,
settings.CreateTableDefaultPermissions = expandDataLakeSettingsCreateDefaultPermissions(v.([]interface{}))
}

if v, ok := d.GetOk("admins"); ok {
settings.DataLakeAdmins = expandDataLakeSettingsAdmins(v.(*schema.Set))
if v, ok := d.GetOk("external_data_filtering_allow_list"); ok {
settings.ExternalDataFilteringAllowList = expandDataLakeSettingsDataFilteringAllowList(v.(*schema.Set))
}

if v, ok := d.GetOk("trusted_resource_owners"); ok {
Expand Down Expand Up @@ -201,9 +233,12 @@ func resourceDataLakeSettingsRead(ctx context.Context, d *schema.ResourceData, m

settings := output.DataLakeSettings

d.Set("admins", flattenDataLakeSettingsAdmins(settings.DataLakeAdmins))
d.Set("allow_external_data_filtering", settings.AllowExternalDataFiltering)
d.Set("authorized_session_tag_value_list", flex.FlattenStringList(settings.AuthorizedSessionTagValueList))
d.Set("create_database_default_permissions", flattenDataLakeSettingsCreateDefaultPermissions(settings.CreateDatabaseDefaultPermissions))
d.Set("create_table_default_permissions", flattenDataLakeSettingsCreateDefaultPermissions(settings.CreateTableDefaultPermissions))
d.Set("admins", flattenDataLakeSettingsAdmins(settings.DataLakeAdmins))
d.Set("external_data_filtering_allow_list", flattenDataLakeSettingsDataFilteringAllowList(settings.ExternalDataFilteringAllowList))
d.Set("trusted_resource_owners", flex.FlattenStringList(settings.TrustedResourceOwners))

return diags
Expand Down Expand Up @@ -316,7 +351,37 @@ func flattenDataLakeSettingsAdmins(apiObjects []*lakeformation.DataLakePrincipal
tfSlice := make([]interface{}, 0, len(apiObjects))

for _, apiObject := range apiObjects {
tfSlice = append(tfSlice, *apiObject.DataLakePrincipalIdentifier)
tfSlice = append(tfSlice, aws.StringValue(apiObject.DataLakePrincipalIdentifier))
}

return tfSlice
}

func expandDataLakeSettingsDataFilteringAllowList(tfSet *schema.Set) []*lakeformation.DataLakePrincipal {
tfSlice := tfSet.List()
apiObjects := make([]*lakeformation.DataLakePrincipal, 0, len(tfSlice))

for _, tfItem := range tfSlice {
val, ok := tfItem.(string)
if ok && val != "" {
apiObjects = append(apiObjects, &lakeformation.DataLakePrincipal{
DataLakePrincipalIdentifier: aws.String(tfItem.(string)),
})
}
}

return apiObjects
}

func flattenDataLakeSettingsDataFilteringAllowList(apiObjects []*lakeformation.DataLakePrincipal) []interface{} {
if apiObjects == nil {
return nil
}

tfSlice := make([]interface{}, 0, len(apiObjects))

for _, apiObject := range apiObjects {
tfSlice = append(tfSlice, aws.StringValue(apiObject.DataLakePrincipalIdentifier))
}

return tfSlice
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ func DataSourceDataLakeSettings() *schema.Resource {
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"allow_external_data_filtering": {
Type: schema.TypeBool,
Computed: true,
},
"authorized_session_tag_value_list": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"catalog_id": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -65,6 +74,11 @@ func DataSourceDataLakeSettings() *schema.Resource {
},
},
},
"external_data_filtering_allow_list": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"trusted_resource_owners": {
Type: schema.TypeList,
Computed: true,
Expand Down Expand Up @@ -103,9 +117,12 @@ func dataSourceDataLakeSettingsRead(ctx context.Context, d *schema.ResourceData,

settings := output.DataLakeSettings

d.Set("admins", flattenDataLakeSettingsAdmins(settings.DataLakeAdmins))
d.Set("allow_external_data_filtering", settings.AllowExternalDataFiltering)
d.Set("authorized_session_tag_value_list", flex.FlattenStringList(settings.AuthorizedSessionTagValueList))
d.Set("create_database_default_permissions", flattenDataLakeSettingsCreateDefaultPermissions(settings.CreateDatabaseDefaultPermissions))
d.Set("create_table_default_permissions", flattenDataLakeSettingsCreateDefaultPermissions(settings.CreateTableDefaultPermissions))
d.Set("admins", flattenDataLakeSettingsAdmins(settings.DataLakeAdmins))
d.Set("external_data_filtering_allow_list", flattenDataLakeSettingsDataFilteringAllowList(settings.ExternalDataFilteringAllowList))
d.Set("trusted_resource_owners", flex.FlattenStringList(settings.TrustedResourceOwners))

return diags
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ func testAccDataLakeSettingsDataSource_basic(t *testing.T) {
resource.TestCheckResourceAttrPair(resourceName, "catalog_id", "data.aws_caller_identity.current", "account_id"),
resource.TestCheckResourceAttr(resourceName, "admins.#", "1"),
resource.TestCheckResourceAttrPair(resourceName, "admins.0", "data.aws_iam_session_context.current", "issuer_arn"),
resource.TestCheckResourceAttr(resourceName, "allow_external_data_filtering", "false"),
resource.TestCheckResourceAttr(resourceName, "external_data_filtering_allow_list.#", "0"),
resource.TestCheckResourceAttr(resourceName, "authorized_session_tag_value_list.#", "0"),
),
},
},
Expand Down
20 changes: 18 additions & 2 deletions internal/service/lakeformation/data_lake_settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,19 @@ func testAccDataLakeSettings_basic(t *testing.T) {
resource.TestCheckResourceAttrPair(resourceName, "catalog_id", "data.aws_caller_identity.current", "account_id"),
resource.TestCheckResourceAttr(resourceName, "admins.#", "1"),
resource.TestCheckResourceAttrPair(resourceName, "admins.0", "data.aws_iam_session_context.current", "issuer_arn"),
resource.TestCheckResourceAttr(resourceName, "create_database_default_permissions.#", "1"),
resource.TestCheckResourceAttr(resourceName, "create_database_default_permissions.0.principal", "IAM_ALLOWED_PRINCIPALS"),
resource.TestCheckResourceAttr(resourceName, "create_database_default_permissions.0.permissions.#", "1"),
resource.TestCheckResourceAttr(resourceName, "create_database_default_permissions.0.permissions.0", "ALL"),
resource.TestCheckResourceAttr(resourceName, "create_table_default_permissions.#", "1"),
resource.TestCheckResourceAttr(resourceName, "create_table_default_permissions.0.principal", "IAM_ALLOWED_PRINCIPALS"),
resource.TestCheckResourceAttr(resourceName, "create_table_default_permissions.0.permissions.#", "1"),
resource.TestCheckResourceAttr(resourceName, "create_table_default_permissions.0.permissions.0", "ALL"),
resource.TestCheckResourceAttr(resourceName, "allow_external_data_filtering", "true"),
resource.TestCheckResourceAttr(resourceName, "external_data_filtering_allow_list.#", "1"),
resource.TestCheckResourceAttrPair(resourceName, "external_data_filtering_allow_list.0", "data.aws_caller_identity.current", "account_id"),
resource.TestCheckResourceAttr(resourceName, "authorized_session_tag_value_list.#", "1"),
resource.TestCheckResourceAttr(resourceName, "authorized_session_tag_value_list.0", "engine1"),
),
},
},
Expand Down Expand Up @@ -161,8 +174,11 @@ resource "aws_lakeformation_data_lake_settings" "test" {
permissions = ["ALL"]
}

admins = [data.aws_iam_session_context.current.issuer_arn]
trusted_resource_owners = [data.aws_caller_identity.current.account_id]
admins = [data.aws_iam_session_context.current.issuer_arn]
trusted_resource_owners = [data.aws_caller_identity.current.account_id]
allow_external_data_filtering = true
external_data_filtering_allow_list = [data.aws_caller_identity.current.account_id]
authorized_session_tag_value_list = ["engine1"]
}
`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ In addition to arguments above, the following attributes are exported.
* `create_database_default_permissions` - Up to three configuration blocks of principal permissions for default create database permissions. Detailed below.
* `create_table_default_permissions` - Up to three configuration blocks of principal permissions for default create table permissions. Detailed below.
* `trusted_resource_owners` – List of the resource-owning account IDs that the caller's account can use to share their user access details (user ARNs).
* `allow_external_data_filtering` - Whether to allow Amazon EMR clusters to access data managed by Lake Formation.
* `external_data_filtering_allow_list` - A list of the account IDs of Amazon Web Services accounts with Amazon EMR clusters that are to perform data filtering.
* `authorized_session_tag_value_list` - Lake Formation relies on a privileged process secured by Amazon EMR or the third party integrator to tag the user's role while assuming it.

### create_database_default_permissions

Expand Down
25 changes: 25 additions & 0 deletions website/docs/r/lakeformation_data_lake_settings.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,28 @@ resource "aws_lakeformation_data_lake_settings" "example" {
}
```

### Enable EMR access to LakeFormation resources

```terraform
resource "aws_lakeformation_data_lake_settings" "example" {
admins = [aws_iam_user.test.arn, aws_iam_role.test.arn]

create_database_default_permissions {
permissions = ["SELECT", "ALTER", "DROP"]
principal = aws_iam_user.test.arn
}

create_table_default_permissions {
permissions = ["ALL"]
principal = aws_iam_role.test.arn
}

allow_external_data_filtering = true
external_data_filtering_allow_list = [data.aws_caller_identity.current.account_id, data.aws_caller_identity.third_party.account_id]
authorized_session_tag_value_list = ["Amazon EMR"]
}
```

## Argument Reference

The following arguments are optional:
Expand All @@ -49,6 +71,9 @@ The following arguments are optional:
* `create_database_default_permissions` - (Optional) Up to three configuration blocks of principal permissions for default create database permissions. Detailed below.
* `create_table_default_permissions` - (Optional) Up to three configuration blocks of principal permissions for default create table permissions. Detailed below.
* `trusted_resource_owners` – (Optional) List of the resource-owning account IDs that the caller's account can use to share their user access details (user ARNs).
* `allow_external_data_filtering` - (Optional) Whether to allow Amazon EMR clusters to access data managed by Lake Formation.
* `external_data_filtering_allow_list` - (Optional) A list of the account IDs of Amazon Web Services accounts with Amazon EMR clusters that are to perform data filtering.
* `authorized_session_tag_value_list` - (Optional) Lake Formation relies on a privileged process secured by Amazon EMR or the third party integrator to tag the user's role while assuming it.

~> **NOTE:** Although optional, not including `admins`, `create_database_default_permissions`, `create_table_default_permissions`, and/or `trusted_resource_owners` results in the setting being cleared.

Expand Down