diff --git a/.changelog/33189.txt b/.changelog/33189.txt new file mode 100644 index 00000000000..e3e565b1a64 --- /dev/null +++ b/.changelog/33189.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +resource/aws_lakeformation_data_lake_settings: Add `read_only_admins` argument +``` + +```release-note:enhancement +data-source/aws_lakeformation_data_lake_settings: Add `read_only_admins` attribute +``` diff --git a/internal/service/lakeformation/data_lake_settings.go b/internal/service/lakeformation/data_lake_settings.go index 0385353a400..f9511521e6a 100644 --- a/internal/service/lakeformation/data_lake_settings.go +++ b/internal/service/lakeformation/data_lake_settings.go @@ -45,6 +45,15 @@ func ResourceDataLakeSettings() *schema.Resource { ValidateFunc: verify.ValidARN, }, }, + "read_only_admins": { + Type: schema.TypeSet, + Computed: true, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: verify.ValidARN, + }, + }, "allow_external_data_filtering": { Type: schema.TypeBool, Optional: true, @@ -148,6 +157,10 @@ func resourceDataLakeSettingsCreate(ctx context.Context, d *schema.ResourceData, settings.DataLakeAdmins = expandDataLakeSettingsAdmins(v.(*schema.Set)) } + if v, ok := d.GetOk("read_only_admins"); ok { + settings.ReadOnlyAdmins = expandDataLakeSettingsAdmins(v.(*schema.Set)) + } + if v, ok := d.GetOk("allow_external_data_filtering"); ok { settings.AllowExternalDataFiltering = aws.Bool(v.(bool)) } @@ -237,6 +250,7 @@ func resourceDataLakeSettingsRead(ctx context.Context, d *schema.ResourceData, m settings := output.DataLakeSettings d.Set("admins", flattenDataLakeSettingsAdmins(settings.DataLakeAdmins)) + d.Set("read_only_admins", flattenDataLakeSettingsAdmins(settings.ReadOnlyAdmins)) 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)) @@ -256,6 +270,7 @@ func resourceDataLakeSettingsDelete(ctx context.Context, d *schema.ResourceData, CreateDatabaseDefaultPermissions: make([]*lakeformation.PrincipalPermissions, 0), CreateTableDefaultPermissions: make([]*lakeformation.PrincipalPermissions, 0), DataLakeAdmins: make([]*lakeformation.DataLakePrincipal, 0), + ReadOnlyAdmins: make([]*lakeformation.DataLakePrincipal, 0), TrustedResourceOwners: make([]*string, 0), }, } diff --git a/internal/service/lakeformation/data_lake_settings_data_source.go b/internal/service/lakeformation/data_lake_settings_data_source.go index dd97d3bc08c..5ba440ed862 100644 --- a/internal/service/lakeformation/data_lake_settings_data_source.go +++ b/internal/service/lakeformation/data_lake_settings_data_source.go @@ -30,6 +30,11 @@ func DataSourceDataLakeSettings() *schema.Resource { Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, }, + "read_only_admins": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, "allow_external_data_filtering": { Type: schema.TypeBool, Computed: true, @@ -121,6 +126,7 @@ func dataSourceDataLakeSettingsRead(ctx context.Context, d *schema.ResourceData, settings := output.DataLakeSettings d.Set("admins", flattenDataLakeSettingsAdmins(settings.DataLakeAdmins)) + d.Set("read_only_admins", flattenDataLakeSettingsAdmins(settings.ReadOnlyAdmins)) 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)) diff --git a/internal/service/lakeformation/data_lake_settings_data_source_test.go b/internal/service/lakeformation/data_lake_settings_data_source_test.go index c70d98600b3..e4245c9e954 100644 --- a/internal/service/lakeformation/data_lake_settings_data_source_test.go +++ b/internal/service/lakeformation/data_lake_settings_data_source_test.go @@ -36,6 +36,28 @@ func testAccDataLakeSettingsDataSource_basic(t *testing.T) { }) } +func testAccDataLakeSettingsDataSource_readOnlyAdmins(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "data.aws_lakeformation_data_lake_settings.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckPartitionHasService(t, lakeformation.EndpointsID) }, + ErrorCheck: acctest.ErrorCheck(t, lakeformation.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDataLakeSettingsDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDataLakeSettingsDataSourceConfig_readOnlyAdmins, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrPair(resourceName, "catalog_id", "data.aws_caller_identity.current", "account_id"), + resource.TestCheckResourceAttr(resourceName, "read_only_admins.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "read_only_admins.0", "data.aws_iam_session_context.current", "issuer_arn"), + ), + }, + }, + }) +} + const testAccDataLakeSettingsDataSourceConfig_basic = ` data "aws_caller_identity" "current" {} @@ -52,3 +74,20 @@ data "aws_lakeformation_data_lake_settings" "test" { catalog_id = aws_lakeformation_data_lake_settings.test.catalog_id } ` + +const testAccDataLakeSettingsDataSourceConfig_readOnlyAdmins = ` +data "aws_caller_identity" "current" {} + +data "aws_iam_session_context" "current" { + arn = data.aws_caller_identity.current.arn +} + +resource "aws_lakeformation_data_lake_settings" "test" { + catalog_id = data.aws_caller_identity.current.account_id + read_only_admins = [data.aws_iam_session_context.current.issuer_arn] +} + +data "aws_lakeformation_data_lake_settings" "test" { + catalog_id = aws_lakeformation_data_lake_settings.test.catalog_id +} +` diff --git a/internal/service/lakeformation/data_lake_settings_test.go b/internal/service/lakeformation/data_lake_settings_test.go index fd325945cc9..84c3e831544 100644 --- a/internal/service/lakeformation/data_lake_settings_test.go +++ b/internal/service/lakeformation/data_lake_settings_test.go @@ -98,6 +98,28 @@ func testAccDataLakeSettings_withoutCatalogID(t *testing.T) { }) } +func testAccDataLakeSettings_readOnlyAdmins(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_lakeformation_data_lake_settings.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, lakeformation.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckDataLakeSettingsDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccDataLakeSettingsConfig_readOnlyAdmins, + Check: resource.ComposeTestCheckFunc( + testAccCheckDataLakeSettingsExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "read_only_admins.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "read_only_admins.0", "data.aws_iam_session_context.current", "issuer_arn"), + ), + }, + }, + }) +} + func testAccCheckDataLakeSettingsDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acctest.Provider.Meta().(*conns.AWSClient).LakeFormationConn(ctx) @@ -126,6 +148,10 @@ func testAccCheckDataLakeSettingsDestroy(ctx context.Context) resource.TestCheck if output != nil && output.DataLakeSettings != nil && len(output.DataLakeSettings.DataLakeAdmins) > 0 { return fmt.Errorf("Lake Formation data lake admin(s) (%s) still exist", rs.Primary.ID) } + + if output != nil && output.DataLakeSettings != nil && len(output.DataLakeSettings.ReadOnlyAdmins) > 0 { + return fmt.Errorf("Lake Formation data lake read only admin(s) (%s) still exist", rs.Primary.ID) + } } return nil @@ -196,3 +222,17 @@ resource "aws_lakeformation_data_lake_settings" "test" { admins = [data.aws_iam_session_context.current.issuer_arn] } ` + +const testAccDataLakeSettingsConfig_readOnlyAdmins = ` +data "aws_caller_identity" "current" {} + +data "aws_iam_session_context" "current" { + arn = data.aws_caller_identity.current.arn +} + +resource "aws_lakeformation_data_lake_settings" "test" { + catalog_id = data.aws_caller_identity.current.account_id + + read_only_admins = [data.aws_iam_session_context.current.issuer_arn] +} +` diff --git a/internal/service/lakeformation/lakeformation_test.go b/internal/service/lakeformation/lakeformation_test.go index 99422b50d36..40c8436475d 100644 --- a/internal/service/lakeformation/lakeformation_test.go +++ b/internal/service/lakeformation/lakeformation_test.go @@ -15,9 +15,13 @@ func TestAccLakeFormation_serial(t *testing.T) { testCases := map[string]map[string]func(t *testing.T){ "DataLakeSettings": { "basic": testAccDataLakeSettings_basic, - "dataSource": testAccDataLakeSettingsDataSource_basic, "disappears": testAccDataLakeSettings_disappears, "withoutCatalogId": testAccDataLakeSettings_withoutCatalogID, + "readOnlyAdmins": testAccDataLakeSettings_readOnlyAdmins, + }, + "DataLakeSettingsDataSource": { + "basic": testAccDataLakeSettingsDataSource_basic, + "readOnlyAdmins": testAccDataLakeSettingsDataSource_readOnlyAdmins, }, "PermissionsBasic": { "basic": testAccPermissions_basic, diff --git a/website/docs/d/lakeformation_data_lake_settings.html.markdown b/website/docs/d/lakeformation_data_lake_settings.html.markdown index d6da8a35940..1a1cdaef72a 100644 --- a/website/docs/d/lakeformation_data_lake_settings.html.markdown +++ b/website/docs/d/lakeformation_data_lake_settings.html.markdown @@ -29,6 +29,7 @@ The following arguments are optional: This data source exports the following attributes in addition to the arguments above: * `admins` – List of ARNs of AWS Lake Formation principals (IAM users or roles). +* `read_only_admins` – List of ARNs of AWS Lake Formation principals (IAM users or roles) with only view access to the resources. * `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). diff --git a/website/docs/r/lakeformation_data_lake_settings.html.markdown b/website/docs/r/lakeformation_data_lake_settings.html.markdown index 92b2ce69723..db938537c48 100644 --- a/website/docs/r/lakeformation_data_lake_settings.html.markdown +++ b/website/docs/r/lakeformation_data_lake_settings.html.markdown @@ -67,6 +67,7 @@ resource "aws_lakeformation_data_lake_settings" "example" { The following arguments are optional: * `admins` – (Optional) Set of ARNs of AWS Lake Formation principals (IAM users or roles). +* `read_only_admins` – (Optional) Set of ARNs of AWS Lake Formation principals (IAM users or roles) with only view access to the resources. * `catalog_id` – (Optional) Identifier for the Data Catalog. By default, the account ID. * `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.