From 50c70f0a169ed7356d40fcd8b9b814e16631b88f Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:24:58 -0400 Subject: [PATCH 01/24] i/lakeformation: Add enum file --- aws/internal/service/lakeformation/enum.go | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 aws/internal/service/lakeformation/enum.go diff --git a/aws/internal/service/lakeformation/enum.go b/aws/internal/service/lakeformation/enum.go new file mode 100644 index 000000000000..d6be8ccf03f7 --- /dev/null +++ b/aws/internal/service/lakeformation/enum.go @@ -0,0 +1,8 @@ +package lakeformation + +const ( + TableNameAllTables = "ALL_TABLES" + TableTypeTable = "Table" + TableTypeTableWithColumns = "TableWithColumns" + IAMAllowedPrincipals = "IAM_ALLOWED_PRINCIPALS" +) From fa5163176fa8be3e9ecc386fc0eb12525dddfbe4 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:28:30 -0400 Subject: [PATCH 02/24] docs/r/lakeformation_permissions: Add docs on IAMAllowedPrincipals --- .../r/lakeformation_permissions.html.markdown | 85 +++++++++++++++++-- 1 file changed, 80 insertions(+), 5 deletions(-) diff --git a/website/docs/r/lakeformation_permissions.html.markdown b/website/docs/r/lakeformation_permissions.html.markdown index 9fb3166fe722..d6b116689bf3 100644 --- a/website/docs/r/lakeformation_permissions.html.markdown +++ b/website/docs/r/lakeformation_permissions.html.markdown @@ -10,8 +10,83 @@ description: |- Grants permissions to the principal to access metadata in the Data Catalog and data organized in underlying data storage such as Amazon S3. Permissions are granted to a principal, in a Data Catalog, relative to a Lake Formation resource, which includes the Data Catalog, databases, and tables. For more information, see [Security and Access Control to Metadata and Data in Lake Formation](https://docs.aws.amazon.com/lake-formation/latest/dg/security-data-access.html). +!> **WARNING:** Lake Formation permissions are not in effect by default within AWS. Using this resource will not secure your data and will result in errors if you do not change the security settings for existing resources and the default security settings for new resources. See [Default Behavior and `IAMAllowedPrincipals`](#default-behavior-and-iamallowedprincipals) for additional details. + ~> **NOTE:** In general, the `principal` should _NOT_ be a Lake Formation administrator or the entity (e.g., IAM role) that is running Terraform. Administrators have implicit permissions. These should be managed by granting or not granting administrator rights using `aws_lakeformation_data_lake_settings`, _not_ with this resource. +## Default Behavior and `IAMAllowedPrincipals` + +**_Lake Formation permissions are not in effect by default within AWS._** `IAMAllowedPrincipals` (i.e., `IAM_ALLOWED_PRINCIPALS`) conflicts with individual Lake Formation permissions (i.e., non-`IAMAllowedPrincipals` permissions), will cause unexpected behavior, and may result in errors. + +When using Lake Formation, you need to choose between these two mutually exclusive options: + +1. Use this resource (`aws_lakeformation_permissions`), change the default security settings using [`aws_lakeformation_data_lake_settings`](/docs/providers/aws/r/lakeformation_data_lake_settings.html), and remove existing `IAMAllowedPrincipals` permissions +2. Use `IAMAllowedPrincipals` and not use this resource + +This example shows removing the `IAMAllowedPrincipals` default security settings and making the caller a Lake Formation admin. Since `create_database_default_permissions` and `create_table_default_permissions` are not set in the [`aws_lakeformation_data_lake_settings`](/docs/providers/aws/r/lakeformation_data_lake_settings.html) resource, they are cleared. + +```terraform +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" { + admins = [data.aws_iam_session_context.current.issuer_arn] +} +``` + +To remove existing `IAMAllowedPrincipals` permissions, use the [AWS Lake Formation Console](https://console.aws.amazon.com/lakeformation/) or [AWS CLI](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lakeformation/batch-revoke-permissions.html). + +`IAMAllowedPrincipals` is a hook to maintain backwards compatibility with AWS Glue. `IAMAllowedPrincipals` is a pseudo-entity group that acts like a Lake Formation principal. The group includes any IAM users and roles that are allowed access to your Data Catalog resources by your IAM policies. + +This is Lake Formation's default behavior: + +* Lake Formation grants `Super` permission to `IAMAllowedPrincipals` on all existing AWS Glue Data Catalog resources. +* Lake Formation enables "Use only IAM access control" for new Data Catalog resources. + +For more details, see [Changing the Default Security Settings for Your Data Lake](https://docs.aws.amazon.com/lake-formation/latest/dg/change-settings.html). + +### Example Problem Using `IAMAllowedPrincipals` + +AWS does not support combining `IAMAllowedPrincipals` permissions and non-`IAMAllowedPrincipals` permissions. Doing so results in unexpected permissions. For example, this configuration grants a user `SELECT` on a column in a table. + +```terraform +resource "aws_glue_catalog_database" "example" { + name = "sadabate" +} + +resource "aws_glue_catalog_table" "example" { + name = "abelt" + database_name = aws_glue_catalog_database.test.name + + storage_descriptor { + columns { + name = "event" + type = "string" + } + } +} + +resource "aws_lakeformation_permissions" "example" { + permissions = ["SELECT"] + principal = "arn:aws:iam:us-east-1:123456789012:user/SanHolo" + + table_with_columns { + database_name = aws_glue_catalog_table.example.database_name + name = aws_glue_catalog_table.example.name + column_names = ["event"] + } +} +``` + +The resulting permissions depend on whether the table had `IAMAllowedPrincipals` (IAP) permissions or not. + +| Result With IAP | Result Without IAP | +| ---- | ---- | +| `SELECT` on table with columns with column wildcard (i.e., all columns) | `SELECT` on `"event"` (as expected) | + ## Using Lake Formation Permissions Lake Formation grants implicit permissions to data lake administrators, database creators, and table creators. These implicit permissions cannot be revoked _per se_. If this resource reads implicit permissions, it will attempt to revoke them, which causes an error when the resource is destroyed. @@ -25,12 +100,12 @@ If the `principal` is also a data lake administrator, AWS grants implicit permis ### Grant Permissions For A Lake Formation S3 Resource ```terraform -resource "aws_lakeformation_permissions" "test" { +resource "aws_lakeformation_permissions" "example" { principal = aws_iam_role.workflow_role.arn permissions = ["ALL"] data_location { - arn = aws_lakeformation_resource.test.arn + arn = aws_lakeformation_resource.example.arn } } ``` @@ -38,12 +113,12 @@ resource "aws_lakeformation_permissions" "test" { ### Grant Permissions For A Glue Catalog Database ```terraform -resource "aws_lakeformation_permissions" "test" { +resource "aws_lakeformation_permissions" "example" { role = aws_iam_role.workflow_role.arn permissions = ["CREATE_TABLE", "ALTER", "DROP"] database { - name = aws_glue_catalog_database.test.name + name = aws_glue_catalog_database.example.name catalog_id = "110376042874" } } @@ -54,7 +129,7 @@ resource "aws_lakeformation_permissions" "test" { The following arguments are required: * `permissions` – (Required) List of permissions granted to the principal. Valid values may include `ALL`, `ALTER`, `CREATE_DATABASE`, `CREATE_TABLE`, `DATA_LOCATION_ACCESS`, `DELETE`, `DESCRIBE`, `DROP`, `INSERT`, and `SELECT`. For details on each permission, see [Lake Formation Permissions Reference](https://docs.aws.amazon.com/lake-formation/latest/dg/lf-permissions-reference.html). -* `principal` – (Required) Principal to be granted the permissions on the resource. Supported principals include IAM roles, users, groups, SAML groups and users, QuickSight groups, OUs, and organizations as well as AWS account IDs for cross-account permissions. For more information, see [Lake Formation Permissions Reference](https://docs.aws.amazon.com/lake-formation/latest/dg/lf-permissions-reference.html). +* `principal` – (Required) Principal to be granted the permissions on the resource. Supported principals include `IAM_ALLOWED_PRINCIPALS` (see [Default Behavior and `IAMAllowedPrincipals`](#default-behavior-and-iamallowedprincipals) above), IAM roles, users, groups, SAML groups and users, QuickSight groups, OUs, and organizations as well as AWS account IDs for cross-account permissions. For more information, see [Lake Formation Permissions Reference](https://docs.aws.amazon.com/lake-formation/latest/dg/lf-permissions-reference.html). ~> **NOTE:** We highly recommend that the `principal` _NOT_ be a Lake Formation administrator (granted using `aws_lakeformation_data_lake_settings`). The entity (e.g., IAM role) running Terraform will most likely need to be a Lake Formation administrator. As such, the entity will have implicit permissions and does not need permissions granted through this resource. From 10970c4e99ddf1988432f31b3b2c0a696fbcd2c7 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:29:06 -0400 Subject: [PATCH 03/24] tests/lakeformation: Add new tests, rename existing --- aws/resource_aws_lakeformation_test.go | 53 +++++++++++++++----------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/aws/resource_aws_lakeformation_test.go b/aws/resource_aws_lakeformation_test.go index 6f012aefe4e4..aef0bd5574ba 100644 --- a/aws/resource_aws_lakeformation_test.go +++ b/aws/resource_aws_lakeformation_test.go @@ -8,35 +8,42 @@ func TestAccAWSLakeFormation_serial(t *testing.T) { testCases := map[string]map[string]func(t *testing.T){ "DataLakeSettings": { "basic": testAccAWSLakeFormationDataLakeSettings_basic, + "dataSource": testAccAWSLakeFormationDataLakeSettingsDataSource_basic, "disappears": testAccAWSLakeFormationDataLakeSettings_disappears, "withoutCatalogId": testAccAWSLakeFormationDataLakeSettings_withoutCatalogId, - "dataSource": testAccAWSLakeFormationDataLakeSettingsDataSource_basic, }, - "BasicPermissions": { - "basic": testAccAWSLakeFormationPermissions_basic, - "dataLocation": testAccAWSLakeFormationPermissions_dataLocation, - "database": testAccAWSLakeFormationPermissions_database, - "disappears": testAccAWSLakeFormationPermissions_disappears, + "PermissionsBasic": { + "basic": testAccAWSLakeFormationPermissions_basic, + "database": testAccAWSLakeFormationPermissions_database, + "databaseIAMAllowed": testAccAWSLakeFormationPermissions_databaseIAMAllowed, + "databaseMultiple": testAccAWSLakeFormationPermissions_databaseMultiple, + "dataLocation": testAccAWSLakeFormationPermissions_dataLocation, + "disappears": testAccAWSLakeFormationPermissions_disappears, }, - "TablePermissions": { - "implicitTablePermissions": testAccAWSLakeFormationPermissions_implicitTablePermissions, - "selectPermissions": testAccAWSLakeFormationPermissions_selectPermissions, - "tableName": testAccAWSLakeFormationPermissions_tableName, - "tableWildcard": testAccAWSLakeFormationPermissions_tableWildcard, - "tableWildcardPermissions": testAccAWSLakeFormationPermissions_tableWildcardPermissions, + "PermissionsDataSource": { + "basic": testAccAWSLakeFormationPermissionsDataSource_basic, + "database": testAccAWSLakeFormationPermissionsDataSource_database, + "dataLocation": testAccAWSLakeFormationPermissionsDataSource_dataLocation, + "table": testAccAWSLakeFormationPermissionsDataSource_table, + "tableWithColumns": testAccAWSLakeFormationPermissionsDataSource_tableWithColumns, }, - "TableWithColumnsPermissions": { - "columnWildcardExcludedColumnsPermissions": testAccAWSLakeFormationPermissions_columnWildcardExcludedColumnsPermissions, - "columnWildcardPermissions": testAccAWSLakeFormationPermissions_columnWildcardPermissions, - "implicitTableWithColumnsPermissions": testAccAWSLakeFormationPermissions_implicitTableWithColumnsPermissions, - "tableWithColumns": testAccAWSLakeFormationPermissions_tableWithColumns, + "PermissionsTable": { + "basic": testAccAWSLakeFormationPermissions_tableBasic, + "iamAllowed": testAccAWSLakeFormationPermissions_tableIAMAllowed, + "implicit": testAccAWSLakeFormationPermissions_tableImplicit, + "multipleRoles": testAccAWSLakeFormationPermissions_tableMultipleRoles, + "selectOnly": testAccAWSLakeFormationPermissions_tableSelectOnly, + "selectPlus": testAccAWSLakeFormationPermissions_tableSelectPlus, + "wildcardNoSelect": testAccAWSLakeFormationPermissions_tableWildcardNoSelect, + "wildcardSelectOnly": testAccAWSLakeFormationPermissions_tableWildcardSelectOnly, + "wildcardSelectPlus": testAccAWSLakeFormationPermissions_tableWildcardSelectPlus, }, - "DataSourcePermissions": { - "basicDataSource": testAccAWSLakeFormationPermissionsDataSource_basic, - "dataLocationDataSource": testAccAWSLakeFormationPermissionsDataSource_dataLocation, - "databaseDataSource": testAccAWSLakeFormationPermissionsDataSource_database, - "tableDataSource": testAccAWSLakeFormationPermissionsDataSource_table, - "tableWithColumnsDataSource": testAccAWSLakeFormationPermissionsDataSource_tableWithColumns, + "PermissionsTableWithColumns": { + "basic": testAccAWSLakeFormationPermissions_twcBasic, + "implicit": testAccAWSLakeFormationPermissions_twcImplicit, + "wildcardExcludedColumns": testAccAWSLakeFormationPermissions_twcWildcardExcludedColumns, + "wildcardSelectOnly": testAccAWSLakeFormationPermissions_twcWildcardSelectOnly, + "wildcardSelectPlus": testAccAWSLakeFormationPermissions_twcWildcardSelectPlus, }, } From 81b10a55bcc58a59b13256bd7ef60cd9140c0955 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:29:42 -0400 Subject: [PATCH 04/24] tests/r/lakeformation_permissions: Fix bugs --- ...urce_aws_lakeformation_permissions_test.go | 1485 ++++++++++++----- 1 file changed, 1081 insertions(+), 404 deletions(-) diff --git a/aws/resource_aws_lakeformation_permissions_test.go b/aws/resource_aws_lakeformation_permissions_test.go index bfd87e3fd9fe..8fcbb28dcc4d 100644 --- a/aws/resource_aws_lakeformation_permissions_test.go +++ b/aws/resource_aws_lakeformation_permissions_test.go @@ -53,7 +53,7 @@ func testAccAWSLakeFormationPermissions_disappears(t *testing.T) { CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSLakeFormationPermissionsConfig_tableWithColumns(rName, "\"event\", \"timestamp\""), + Config: testAccAWSLakeFormationPermissionsConfig_twcBasic(rName, "\"event\", \"timestamp\""), Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationPermissionsExists(resourceName), testAccCheckResourceDisappears(testAccProvider, resourceAwsLakeFormationPermissions(), resourceName), @@ -64,11 +64,11 @@ func testAccAWSLakeFormationPermissions_disappears(t *testing.T) { }) } -func testAccAWSLakeFormationPermissions_dataLocation(t *testing.T) { +func testAccAWSLakeFormationPermissions_database(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_lakeformation_permissions.test" roleName := "aws_iam_role.test" - bucketName := "aws_s3_bucket.test" + dbName := "aws_glue_catalog_database.test" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(lakeformation.EndpointsID, t) }, @@ -77,25 +77,60 @@ func testAccAWSLakeFormationPermissions_dataLocation(t *testing.T) { CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSLakeFormationPermissionsConfig_dataLocation(rName), + Config: testAccAWSLakeFormationPermissionsConfig_database(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationPermissionsExists(resourceName), resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), - resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), - resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionDataLocationAccess), resource.TestCheckResourceAttr(resourceName, "catalog_resource", "false"), - resource.TestCheckResourceAttr(resourceName, "data_location.#", "1"), - resource.TestCheckResourceAttrPair(resourceName, "data_location.0.arn", bucketName, "arn"), + resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), + resource.TestCheckResourceAttr(resourceName, "database.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "database.0.name", dbName, "name"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "3"), + resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionAlter), + resource.TestCheckResourceAttr(resourceName, "permissions.1", lakeformation.PermissionCreateTable), + resource.TestCheckResourceAttr(resourceName, "permissions.2", lakeformation.PermissionDrop), + resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.#", "1"), + resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.0", lakeformation.PermissionCreateTable), ), }, }, }) } -func testAccAWSLakeFormationPermissions_database(t *testing.T) { +func testAccAWSLakeFormationPermissions_databaseIAMAllowed(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_lakeformation_permissions.test" + dbName := "aws_glue_catalog_database.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(lakeformation.EndpointsID, t) }, + ErrorCheck: testAccErrorCheck(t, lakeformation.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLakeFormationPermissionsConfig_databaseIAMAllowed(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSLakeFormationPermissionsExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "principal", tflakeformation.IAMAllowedPrincipals), + resource.TestCheckResourceAttr(resourceName, "catalog_resource", "false"), + resource.TestCheckResourceAttr(resourceName, "database.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "database.0.name", dbName, "name"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionAll), + resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.#", "0"), + ), + }, + }, + }) +} + +func testAccAWSLakeFormationPermissions_databaseMultiple(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_lakeformation_permissions.test" + resourceName2 := "aws_lakeformation_permissions.test2" roleName := "aws_iam_role.test" + roleName2 := "aws_iam_role.test2" dbName := "aws_glue_catalog_database.test" resource.Test(t, resource.TestCase{ @@ -105,7 +140,7 @@ func testAccAWSLakeFormationPermissions_database(t *testing.T) { CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSLakeFormationPermissionsConfig_database(rName), + Config: testAccAWSLakeFormationPermissionsConfig_databaseMultiple(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationPermissionsExists(resourceName), resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), @@ -114,18 +149,56 @@ func testAccAWSLakeFormationPermissions_database(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "database.#", "1"), resource.TestCheckResourceAttrPair(resourceName, "database.0.name", dbName, "name"), resource.TestCheckResourceAttr(resourceName, "permissions.#", "3"), - resource.TestCheckResourceAttr(resourceName, "permissions.0", "ALTER"), + resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionAlter), resource.TestCheckResourceAttr(resourceName, "permissions.1", lakeformation.PermissionCreateTable), resource.TestCheckResourceAttr(resourceName, "permissions.2", lakeformation.PermissionDrop), resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.#", "1"), resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.0", lakeformation.PermissionCreateTable), + testAccCheckAWSLakeFormationPermissionsExists(resourceName2), + resource.TestCheckResourceAttrPair(resourceName2, "principal", roleName2, "arn"), + resource.TestCheckResourceAttr(resourceName2, "catalog_resource", "false"), + resource.TestCheckResourceAttrPair(resourceName2, "principal", roleName2, "arn"), + resource.TestCheckResourceAttr(resourceName2, "database.#", "1"), + resource.TestCheckResourceAttrPair(resourceName2, "database.0.name", dbName, "name"), + resource.TestCheckResourceAttr(resourceName2, "permissions.#", "2"), + resource.TestCheckResourceAttr(resourceName2, "permissions.0", lakeformation.PermissionAlter), + resource.TestCheckResourceAttr(resourceName2, "permissions.1", lakeformation.PermissionDrop), + resource.TestCheckResourceAttr(resourceName2, "permissions_with_grant_option.#", "0"), + ), + }, + }, + }) +} + +func testAccAWSLakeFormationPermissions_dataLocation(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_lakeformation_permissions.test" + roleName := "aws_iam_role.test" + bucketName := "aws_s3_bucket.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(lakeformation.EndpointsID, t) }, + ErrorCheck: testAccErrorCheck(t, lakeformation.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLakeFormationPermissionsConfig_dataLocation(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSLakeFormationPermissionsExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionDataLocationAccess), + resource.TestCheckResourceAttr(resourceName, "catalog_resource", "false"), + resource.TestCheckResourceAttr(resourceName, "data_location.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "data_location.0.arn", bucketName, "arn"), ), }, }, }) } -func testAccAWSLakeFormationPermissions_tableName(t *testing.T) { +func testAccAWSLakeFormationPermissions_tableBasic(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_lakeformation_permissions.test" roleName := "aws_iam_role.test" @@ -138,7 +211,7 @@ func testAccAWSLakeFormationPermissions_tableName(t *testing.T) { CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSLakeFormationPermissionsConfig_tableName(rName), + Config: testAccAWSLakeFormationPermissionsConfig_tableBasic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationPermissionsExists(resourceName), resource.TestCheckResourceAttrPair(roleName, "arn", resourceName, "principal"), @@ -155,10 +228,10 @@ func testAccAWSLakeFormationPermissions_tableName(t *testing.T) { }) } -func testAccAWSLakeFormationPermissions_tableWildcard(t *testing.T) { +func testAccAWSLakeFormationPermissions_tableIAMAllowed(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_lakeformation_permissions.test" - databaseResourceName := "aws_glue_catalog_database.test" + dbName := "aws_glue_catalog_table.test" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(lakeformation.EndpointsID, t) }, @@ -167,19 +240,24 @@ func testAccAWSLakeFormationPermissions_tableWildcard(t *testing.T) { CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSLakeFormationPermissionsConfig_tableWildcard(rName), + Config: testAccAWSLakeFormationPermissionsConfig_tableIAMAllowed(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationPermissionsExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "principal", tflakeformation.IAMAllowedPrincipals), + resource.TestCheckResourceAttr(resourceName, "catalog_resource", "false"), resource.TestCheckResourceAttr(resourceName, "table.#", "1"), - resource.TestCheckResourceAttrPair(resourceName, "table.0.database_name", databaseResourceName, "name"), - resource.TestCheckResourceAttr(resourceName, "table.0.wildcard", "true"), + resource.TestCheckResourceAttrPair(resourceName, "table.0.database_name", dbName, "database_name"), + resource.TestCheckResourceAttrPair(resourceName, "table.0.name", dbName, "name"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionAll), + resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.#", "0"), ), }, }, }) } -func testAccAWSLakeFormationPermissions_tableWithColumns(t *testing.T) { +func testAccAWSLakeFormationPermissions_tableImplicit(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_lakeformation_permissions.test" roleName := "aws_iam_role.test" @@ -192,61 +270,80 @@ func testAccAWSLakeFormationPermissions_tableWithColumns(t *testing.T) { CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSLakeFormationPermissionsConfig_tableWithColumns(rName, "\"event\", \"timestamp\""), + Config: testAccAWSLakeFormationPermissionsConfig_tableImplicit(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationPermissionsExists(resourceName), resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.#", "1"), - resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.database_name", tableName, "database_name"), - resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.name", tableName, "name"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.#", "2"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.0", "event"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.1", "timestamp"), - resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), - resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionSelect), - ), - }, - { - Config: testAccAWSLakeFormationPermissionsConfig_tableWithColumns(rName, "\"timestamp\", \"event\""), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSLakeFormationPermissionsExists(resourceName), - resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.#", "1"), - resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.database_name", tableName, "database_name"), - resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.name", tableName, "name"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.#", "2"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.0", "event"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.1", "timestamp"), - resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), - resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionSelect), + resource.TestCheckResourceAttr(resourceName, "table.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "table.0.database_name", tableName, "database_name"), + resource.TestCheckResourceAttrPair(resourceName, "table.0.name", tableName, "name"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "7"), + resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.#", "7"), ), }, + }, + }) +} + +func testAccAWSLakeFormationPermissions_tableMultipleRoles(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_lakeformation_permissions.test" + resourceName2 := "aws_lakeformation_permissions.test2" + roleName := "aws_iam_role.test" + roleName2 := "aws_iam_role.test2" + tableName := "aws_glue_catalog_table.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(lakeformation.EndpointsID, t) }, + ErrorCheck: testAccErrorCheck(t, lakeformation.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, + Steps: []resource.TestStep{ { - Config: testAccAWSLakeFormationPermissionsConfig_tableWithColumns(rName, "\"timestamp\", \"event\", \"transactionamount\""), + Config: testAccAWSLakeFormationPermissionsConfig_tableMultipleRoles(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationPermissionsExists(resourceName), - resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.#", "1"), - resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.database_name", tableName, "database_name"), - resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.name", tableName, "name"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.#", "3"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.0", "event"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.1", "timestamp"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.2", "transactionamount"), - resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), - resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionSelect), + resource.TestCheckResourceAttrPair(roleName, "arn", resourceName, "principal"), + resource.TestCheckResourceAttr(resourceName, "table.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "table.0.database_name", tableName, "database_name"), + resource.TestCheckResourceAttrPair(resourceName, "table.0.name", tableName, "name"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "3"), + resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionAlter), + resource.TestCheckResourceAttr(resourceName, "permissions.1", lakeformation.PermissionDelete), + resource.TestCheckResourceAttr(resourceName, "permissions.2", lakeformation.PermissionDescribe), + testAccCheckAWSLakeFormationPermissionsExists(resourceName2), + resource.TestCheckResourceAttrPair(roleName2, "arn", resourceName2, "principal"), + resource.TestCheckResourceAttr(resourceName2, "table.#", "1"), + resource.TestCheckResourceAttrPair(resourceName2, "table.0.database_name", tableName, "database_name"), + resource.TestCheckResourceAttrPair(resourceName2, "table.0.name", tableName, "name"), + resource.TestCheckResourceAttr(resourceName2, "permissions.#", "1"), + resource.TestCheckResourceAttr(resourceName2, "permissions.0", lakeformation.PermissionSelect), ), }, + }, + }) +} + +func testAccAWSLakeFormationPermissions_tableSelectOnly(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_lakeformation_permissions.test" + roleName := "aws_iam_role.test" + tableName := "aws_glue_catalog_table.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(lakeformation.EndpointsID, t) }, + ErrorCheck: testAccErrorCheck(t, lakeformation.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, + Steps: []resource.TestStep{ { - Config: testAccAWSLakeFormationPermissionsConfig_tableWithColumns(rName, "\"event\""), + Config: testAccAWSLakeFormationPermissionsConfig_tableSelectOnly(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationPermissionsExists(resourceName), - resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.#", "1"), - resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.database_name", tableName, "database_name"), - resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.name", tableName, "name"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.#", "1"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.0", "event"), + resource.TestCheckResourceAttrPair(roleName, "arn", resourceName, "principal"), + resource.TestCheckResourceAttr(resourceName, "table.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "table.0.database_name", tableName, "database_name"), + resource.TestCheckResourceAttrPair(resourceName, "table.0.name", tableName, "name"), resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionSelect), ), @@ -255,11 +352,10 @@ func testAccAWSLakeFormationPermissions_tableWithColumns(t *testing.T) { }) } -func testAccAWSLakeFormationPermissions_implicitTableWithColumnsPermissions(t *testing.T) { +func testAccAWSLakeFormationPermissions_tableSelectPlus(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_lakeformation_permissions.test" roleName := "aws_iam_role.test" - tableName := "aws_glue_catalog_table.test" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(lakeformation.EndpointsID, t) }, @@ -268,14 +364,10 @@ func testAccAWSLakeFormationPermissions_implicitTableWithColumnsPermissions(t *t CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSLakeFormationPermissionsConfig_implicitTableWithColumnsPermissions(rName), + Config: testAccAWSLakeFormationPermissionsConfig_tableSelectPlus(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationPermissionsExists(resourceName), resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.#", "1"), - resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.database_name", tableName, "database_name"), - resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.name", tableName, "name"), - resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.wildcard", "true"), resource.TestCheckResourceAttr(resourceName, "permissions.#", "7"), resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.#", "7"), ), @@ -284,11 +376,10 @@ func testAccAWSLakeFormationPermissions_implicitTableWithColumnsPermissions(t *t }) } -func testAccAWSLakeFormationPermissions_implicitTablePermissions(t *testing.T) { +func testAccAWSLakeFormationPermissions_tableWildcardNoSelect(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_lakeformation_permissions.test" - roleName := "aws_iam_role.test" - tableName := "aws_glue_catalog_table.test" + databaseResourceName := "aws_glue_catalog_database.test" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(lakeformation.EndpointsID, t) }, @@ -297,22 +388,19 @@ func testAccAWSLakeFormationPermissions_implicitTablePermissions(t *testing.T) { CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSLakeFormationPermissionsConfig_implicitTablePermissions(rName), + Config: testAccAWSLakeFormationPermissionsConfig_tableWildcardNoSelect(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationPermissionsExists(resourceName), - resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), resource.TestCheckResourceAttr(resourceName, "table.#", "1"), - resource.TestCheckResourceAttrPair(resourceName, "table.0.database_name", tableName, "database_name"), - resource.TestCheckResourceAttrPair(resourceName, "table.0.name", tableName, "name"), - resource.TestCheckResourceAttr(resourceName, "permissions.#", "7"), - resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.#", "7"), + resource.TestCheckResourceAttrPair(resourceName, "table.0.database_name", databaseResourceName, "name"), + resource.TestCheckResourceAttr(resourceName, "table.0.wildcard", "true"), ), }, }, }) } -func testAccAWSLakeFormationPermissions_selectPermissions(t *testing.T) { +func testAccAWSLakeFormationPermissions_tableWildcardSelectOnly(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_lakeformation_permissions.test" roleName := "aws_iam_role.test" @@ -324,19 +412,20 @@ func testAccAWSLakeFormationPermissions_selectPermissions(t *testing.T) { CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSLakeFormationPermissionsConfig_selectPermissions(rName), + Config: testAccAWSLakeFormationPermissionsConfig_tableWildcardSelectOnly(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationPermissionsExists(resourceName), resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), - resource.TestCheckResourceAttr(resourceName, "permissions.#", "7"), - resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.#", "7"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionSelect), + resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.#", "0"), ), }, }, }) } -func testAccAWSLakeFormationPermissions_tableWildcardPermissions(t *testing.T) { +func testAccAWSLakeFormationPermissions_tableWildcardSelectPlus(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_lakeformation_permissions.test" roleName := "aws_iam_role.test" @@ -348,7 +437,7 @@ func testAccAWSLakeFormationPermissions_tableWildcardPermissions(t *testing.T) { CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSLakeFormationPermissionsConfig_tableWildcardPermissions(rName), + Config: testAccAWSLakeFormationPermissionsConfig_tableWildcardSelectPlus(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationPermissionsExists(resourceName), resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), @@ -360,10 +449,11 @@ func testAccAWSLakeFormationPermissions_tableWildcardPermissions(t *testing.T) { }) } -func testAccAWSLakeFormationPermissions_columnWildcardPermissions(t *testing.T) { +func testAccAWSLakeFormationPermissions_twcBasic(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_lakeformation_permissions.test" roleName := "aws_iam_role.test" + tableName := "aws_glue_catalog_table.test" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(lakeformation.EndpointsID, t) }, @@ -372,22 +462,74 @@ func testAccAWSLakeFormationPermissions_columnWildcardPermissions(t *testing.T) CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSLakeFormationPermissionsConfig_columnWildcardPermissions(rName), + Config: testAccAWSLakeFormationPermissionsConfig_twcBasic(rName, "\"event\", \"timestamp\""), Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationPermissionsExists(resourceName), resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), - resource.TestCheckResourceAttr(resourceName, "permissions.#", "7"), - resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.#", "0"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.database_name", tableName, "database_name"), + resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.name", tableName, "name"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.#", "2"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.0", "event"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.1", "timestamp"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionSelect), + ), + }, + { + Config: testAccAWSLakeFormationPermissionsConfig_twcBasic(rName, "\"timestamp\", \"event\""), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSLakeFormationPermissionsExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.database_name", tableName, "database_name"), + resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.name", tableName, "name"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.#", "2"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.0", "event"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.1", "timestamp"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionSelect), + ), + }, + { + Config: testAccAWSLakeFormationPermissionsConfig_twcBasic(rName, "\"timestamp\", \"event\", \"transactionamount\""), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSLakeFormationPermissionsExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.database_name", tableName, "database_name"), + resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.name", tableName, "name"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.#", "3"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.0", "event"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.1", "timestamp"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.2", "transactionamount"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionSelect), + ), + }, + { + Config: testAccAWSLakeFormationPermissionsConfig_twcBasic(rName, "\"event\""), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSLakeFormationPermissionsExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.database_name", tableName, "database_name"), + resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.name", tableName, "name"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.#", "1"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.0", "event"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionSelect), ), }, }, }) } -func testAccAWSLakeFormationPermissions_columnWildcardExcludedColumnsPermissions(t *testing.T) { +func testAccAWSLakeFormationPermissions_twcImplicit(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_lakeformation_permissions.test" roleName := "aws_iam_role.test" + tableName := "aws_glue_catalog_table.test" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(lakeformation.EndpointsID, t) }, @@ -396,34 +538,116 @@ func testAccAWSLakeFormationPermissions_columnWildcardExcludedColumnsPermissions CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSLakeFormationPermissionsConfig_columnWildcardExcludedColumnsPermissions(rName), + Config: testAccAWSLakeFormationPermissionsConfig_twcImplicit(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationPermissionsExists(resourceName), resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), - resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), - resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.#", "0"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.database_name", tableName, "database_name"), + resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.name", tableName, "name"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.wildcard", "true"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "7"), + resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.#", "7"), ), }, }, }) } -func testAccCheckAWSLakeFormationPermissionsDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).lakeformationconn +func testAccAWSLakeFormationPermissions_twcWildcardExcludedColumns(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_lakeformation_permissions.test" + roleName := "aws_iam_role.test" - for _, rs := range s.RootModule().Resources { - if rs.Type != "aws_lakeformation_permissions" { - continue - } + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(lakeformation.EndpointsID, t) }, + ErrorCheck: testAccErrorCheck(t, lakeformation.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLakeFormationPermissionsConfig_twcWildcardExcludedColumns(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSLakeFormationPermissionsExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.#", "0"), + ), + }, + }, + }) +} + +func testAccAWSLakeFormationPermissions_twcWildcardSelectOnly(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_lakeformation_permissions.test" + roleName := "aws_iam_role.test" + tableName := "aws_glue_catalog_table.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(lakeformation.EndpointsID, t) }, + ErrorCheck: testAccErrorCheck(t, lakeformation.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLakeFormationPermissionsConfig_twcWildcardSelectOnly(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSLakeFormationPermissionsExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.#", "1"), + resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.database_name", tableName, "database_name"), + resource.TestCheckResourceAttrPair(resourceName, "table_with_columns.0.name", tableName, "name"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.column_names.#", "0"), + resource.TestCheckResourceAttr(resourceName, "table_with_columns.0.wildcard", "true"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "permissions.0", lakeformation.PermissionSelect), + ), + }, + }, + }) +} + +func testAccAWSLakeFormationPermissions_twcWildcardSelectPlus(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_lakeformation_permissions.test" + roleName := "aws_iam_role.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPartitionHasServicePreCheck(lakeformation.EndpointsID, t) }, + ErrorCheck: testAccErrorCheck(t, lakeformation.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLakeFormationPermissionsDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLakeFormationPermissionsConfig_twcWildcardSelectPlus(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSLakeFormationPermissionsExists(resourceName), + resource.TestCheckResourceAttrPair(resourceName, "principal", roleName, "arn"), + resource.TestCheckResourceAttr(resourceName, "permissions.#", "7"), + resource.TestCheckResourceAttr(resourceName, "permissions_with_grant_option.#", "0"), + ), + }, + }, + }) +} + +func testAccCheckAWSLakeFormationPermissionsDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).lakeformationconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_lakeformation_permissions" { + continue + } permCount, err := permissionCountForLakeFormationResource(conn, rs) if err != nil { - return fmt.Errorf("error listing Lake Formation permissions (%s): %w", rs.Primary.ID, err) + return fmt.Errorf("acceptance test: error listing Lake Formation permissions (%s): %w", rs.Primary.ID, err) } if permCount != 0 { - return fmt.Errorf("Lake Formation permissions (%s) still exist: %d", rs.Primary.ID, permCount) + return fmt.Errorf("acceptance test: Lake Formation permissions (%s) still exist: %d", rs.Primary.ID, permCount) } return nil @@ -435,8 +659,9 @@ func testAccCheckAWSLakeFormationPermissionsDestroy(s *terraform.State) error { func testAccCheckAWSLakeFormationPermissionsExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[resourceName] + if !ok { - return fmt.Errorf("resource not found: %s", resourceName) + return fmt.Errorf("acceptance test: resource not found: %s", resourceName) } conn := testAccProvider.Meta().(*AWSClient).lakeformationconn @@ -444,11 +669,11 @@ func testAccCheckAWSLakeFormationPermissionsExists(resourceName string) resource permCount, err := permissionCountForLakeFormationResource(conn, rs) if err != nil { - return fmt.Errorf("error listing Lake Formation permissions (%s): %w", rs.Primary.ID, err) + return fmt.Errorf("acceptance test: error listing Lake Formation permissions (%s): %w", rs.Primary.ID, err) } if permCount == 0 { - return fmt.Errorf("Lake Formation permissions (%s) do not exist or could not be found", rs.Primary.ID) + return fmt.Errorf("acceptance test: Lake Formation permissions (%s) do not exist or could not be found", rs.Primary.ID) } return nil @@ -463,12 +688,18 @@ func permissionCountForLakeFormationResource(conn *lakeformation.LakeFormation, Resource: &lakeformation.Resource{}, } + noResource := true + if v, ok := rs.Primary.Attributes["catalog_id"]; ok && v != "" { input.CatalogId = aws.String(v) + + noResource = false } if v, ok := rs.Primary.Attributes["catalog_resource"]; ok && v != "" && v == "true" { input.Resource.Catalog = expandLakeFormationCatalogResource() + + noResource = false } if v, ok := rs.Primary.Attributes["data_location.#"]; ok && v != "" && v != "0" { @@ -483,6 +714,8 @@ func permissionCountForLakeFormationResource(conn *lakeformation.LakeFormation, } input.Resource.DataLocation = expandLakeFormationDataLocationResource(tfMap) + + noResource = false } if v, ok := rs.Primary.Attributes["database.#"]; ok && v != "" && v != "0" { @@ -497,6 +730,8 @@ func permissionCountForLakeFormationResource(conn *lakeformation.LakeFormation, } input.Resource.Database = expandLakeFormationDatabaseResource(tfMap) + + noResource = false } tableType := "" @@ -523,6 +758,8 @@ func permissionCountForLakeFormationResource(conn *lakeformation.LakeFormation, } input.Resource.Table = expandLakeFormationTableResource(tfMap) + + noResource = false } if v, ok := rs.Primary.Attributes["table_with_columns.#"]; ok && v != "" && v != "0" { @@ -543,6 +780,13 @@ func permissionCountForLakeFormationResource(conn *lakeformation.LakeFormation, } input.Resource.Table = expandLakeFormationTableWithColumnsResourceAsTable(tfMap) + + noResource = false + } + + if noResource { + // if after read, there is no resource, it has been deleted + return 0, nil } log.Printf("[DEBUG] Reading Lake Formation permissions: %v", input) @@ -565,7 +809,7 @@ func permissionCountForLakeFormationResource(conn *lakeformation.LakeFormation, return resource.RetryableError(err) } - return resource.NonRetryableError(fmt.Errorf("error listing Lake Formation Permissions: %w", err)) + return resource.NonRetryableError(fmt.Errorf("acceptance test: error listing Lake Formation Permissions getting permission count: %w", err)) } return nil }) @@ -592,7 +836,7 @@ func permissionCountForLakeFormationResource(conn *lakeformation.LakeFormation, } if err != nil { - return 0, fmt.Errorf("error listing Lake Formation permissions after retry: %w", err) + return 0, fmt.Errorf("acceptance test: error listing Lake Formation permissions after retry %v: %w", input, err) } columnNames := make([]*string, 0) @@ -610,7 +854,7 @@ func permissionCountForLakeFormationResource(conn *lakeformation.LakeFormation, colCount, err = strconv.Atoi(rs.Primary.Attributes["table_with_columns.0.column_names.#"]) if err != nil { - return 0, fmt.Errorf("could not convert string (%s) Atoi for column_names: %w", rs.Primary.Attributes["table_with_columns.0.column_names.#"], err) + return 0, fmt.Errorf("acceptance test: could not convert string (%s) Atoi for column_names: %w", rs.Primary.Attributes["table_with_columns.0.column_names.#"], err) } } @@ -624,7 +868,7 @@ func permissionCountForLakeFormationResource(conn *lakeformation.LakeFormation, colCount, err = strconv.Atoi(rs.Primary.Attributes["table_with_columns.0.excluded_column_names.#"]) if err != nil { - return 0, fmt.Errorf("could not convert string (%s) Atoi for excluded_column_names: %w", rs.Primary.Attributes["table_with_columns.0.excluded_column_names.#"], err) + return 0, fmt.Errorf("acceptance test: could not convert string (%s) Atoi for excluded_column_names: %w", rs.Primary.Attributes["table_with_columns.0.excluded_column_names.#"], err) } } @@ -643,36 +887,455 @@ func testAccAWSLakeFormationPermissionsConfig_basic(rName string) string { return fmt.Sprintf(` data "aws_partition" "current" {} -resource "aws_iam_role" "test" { - name = %[1]q +resource "aws_iam_role" "test" { + name = %[1]q + + assume_role_policy = jsonencode({ + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "glue.${data.aws_partition.current.dns_suffix}" + } + }] + Version = "2012-10-17" + }) +} + +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" { + admins = [data.aws_iam_session_context.current.issuer_arn] +} + +resource "aws_lakeformation_permissions" "test" { + principal = aws_iam_role.test.arn + permissions = ["CREATE_DATABASE"] + catalog_resource = true + + # for consistency, ensure that admins are setup before testing + depends_on = [aws_lakeformation_data_lake_settings.test] +} +`, rName) +} + +func testAccAWSLakeFormationPermissionsConfig_database(rName string) string { + return fmt.Sprintf(` +data "aws_partition" "current" {} + +resource "aws_iam_role" "test" { + name = %[1]q + path = "/" + + assume_role_policy = jsonencode({ + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "glue.${data.aws_partition.current.dns_suffix}" + } + }] + Version = "2012-10-17" + }) +} + +resource "aws_glue_catalog_database" "test" { + name = %[1]q +} + +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" { + admins = [data.aws_iam_session_context.current.issuer_arn] +} + +resource "aws_lakeformation_permissions" "test" { + permissions = ["ALTER", "CREATE_TABLE", "DROP"] + permissions_with_grant_option = ["CREATE_TABLE"] + principal = aws_iam_role.test.arn + + database { + name = aws_glue_catalog_database.test.name + } + + # for consistency, ensure that admins are setup before testing + depends_on = [aws_lakeformation_data_lake_settings.test] +} +`, rName) +} + +func testAccAWSLakeFormationPermissionsConfig_databaseIAMAllowed(rName string) string { + return fmt.Sprintf(` +data "aws_partition" "current" {} + +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" { + admins = [data.aws_iam_session_context.current.issuer_arn] +} + +resource "aws_glue_catalog_database" "test" { + name = %[1]q +} + +resource "aws_glue_catalog_table" "test" { + name = %[1]q + database_name = aws_glue_catalog_database.test.name + + storage_descriptor { + columns { + name = "event" + type = "string" + } + + columns { + name = "timestamp" + type = "date" + } + + columns { + name = "transactionamount" + type = "double" + } + } +} + +resource "aws_lakeformation_permissions" "test" { + permissions = ["ALL"] + principal = "IAM_ALLOWED_PRINCIPALS" + + database { + name = aws_glue_catalog_database.test.name + } + + # for consistency, ensure that admins are setup before testing + depends_on = [aws_lakeformation_data_lake_settings.test] +} +`, rName) +} + +func testAccAWSLakeFormationPermissionsConfig_databaseMultiple(rName string) string { + return fmt.Sprintf(` +data "aws_partition" "current" {} + +resource "aws_iam_role" "test" { + name = %[1]q + path = "/" + + assume_role_policy = jsonencode({ + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "glue.${data.aws_partition.current.dns_suffix}" + } + }] + Version = "2012-10-17" + }) +} + +resource "aws_iam_role" "test2" { + name = "%[1]s-2" + path = "/" + + assume_role_policy = jsonencode({ + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "glue.${data.aws_partition.current.dns_suffix}" + } + }] + Version = "2012-10-17" + }) +} + +resource "aws_glue_catalog_database" "test" { + name = %[1]q +} + +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" { + admins = [data.aws_iam_session_context.current.issuer_arn] +} + +resource "aws_lakeformation_permissions" "test" { + permissions = ["ALTER", "CREATE_TABLE", "DROP"] + permissions_with_grant_option = ["CREATE_TABLE"] + principal = aws_iam_role.test.arn + + database { + name = aws_glue_catalog_database.test.name + } + + # for consistency, ensure that admins are setup before testing + depends_on = [aws_lakeformation_data_lake_settings.test] +} + +resource "aws_lakeformation_permissions" "test2" { + permissions = ["ALTER", "DROP"] + principal = aws_iam_role.test2.arn + + database { + name = aws_glue_catalog_database.test.name + } + + # for consistency, ensure that admins are setup before testing + depends_on = [aws_lakeformation_data_lake_settings.test] +} +`, rName) +} + +func testAccAWSLakeFormationPermissionsConfig_dataLocation(rName string) string { + return fmt.Sprintf(` +data "aws_partition" "current" {} + +resource "aws_iam_role" "test" { + name = %[1]q + path = "/" + + assume_role_policy = jsonencode({ + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "glue.${data.aws_partition.current.dns_suffix}" + } + },{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "s3.${data.aws_partition.current.dns_suffix}" + } + }] + Version = "2012-10-17" + }) +} + +resource "aws_s3_bucket" "test" { + bucket = %[1]q + acl = "private" + force_destroy = true +} + +resource "aws_lakeformation_resource" "test" { + arn = aws_s3_bucket.test.arn + role_arn = aws_iam_role.test.arn +} + +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" { + admins = [data.aws_iam_session_context.current.issuer_arn] +} + +resource "aws_lakeformation_permissions" "test" { + principal = aws_iam_role.test.arn + permissions = ["DATA_LOCATION_ACCESS"] + + data_location { + arn = aws_s3_bucket.test.arn + } + + # for consistency, ensure that admins are setup before testing + depends_on = [aws_lakeformation_data_lake_settings.test] +} +`, rName) +} + +func testAccAWSLakeFormationPermissionsConfig_tableBasic(rName string) string { + return fmt.Sprintf(` +data "aws_partition" "current" {} + +resource "aws_iam_role" "test" { + name = %[1]q + path = "/" + + assume_role_policy = jsonencode({ + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "glue.${data.aws_partition.current.dns_suffix}" + } + }] + Version = "2012-10-17" + }) +} + +resource "aws_glue_catalog_database" "test" { + name = %[1]q +} + +resource "aws_glue_catalog_table" "test" { + name = %[1]q + database_name = aws_glue_catalog_database.test.name +} + +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" { + admins = [data.aws_iam_session_context.current.issuer_arn] +} + +resource "aws_lakeformation_permissions" "test" { + permissions = ["ALTER", "DELETE", "DESCRIBE"] + principal = aws_iam_role.test.arn + + table { + database_name = aws_glue_catalog_table.test.database_name + name = aws_glue_catalog_table.test.name + } + + # for consistency, ensure that admins are setup before testing + depends_on = [aws_lakeformation_data_lake_settings.test] +} +`, rName) +} + +func testAccAWSLakeFormationPermissionsConfig_tableIAMAllowed(rName string) string { + return fmt.Sprintf(` +data "aws_partition" "current" {} + +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" { + admins = [data.aws_iam_session_context.current.issuer_arn] +} + +resource "aws_glue_catalog_database" "test" { + name = %[1]q +} + +resource "aws_glue_catalog_table" "test" { + name = %[1]q + database_name = aws_glue_catalog_database.test.name + + storage_descriptor { + columns { + name = "event" + type = "string" + } + + columns { + name = "timestamp" + type = "date" + } + + columns { + name = "transactionamount" + type = "double" + } + } +} + +resource "aws_lakeformation_permissions" "test" { + permissions = ["ALL"] + principal = "IAM_ALLOWED_PRINCIPALS" + + table { + database_name = aws_glue_catalog_database.test.name + name = aws_glue_catalog_table.test.name + } +} +`, rName) +} + +func testAccAWSLakeFormationPermissionsConfig_tableImplicit(rName string) string { + return fmt.Sprintf(` +data "aws_partition" "current" {} + +resource "aws_iam_role" "test" { + name = %[1]q + path = "/" + + assume_role_policy = jsonencode({ + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "glue.${data.aws_partition.current.dns_suffix}" + } + }] + Version = "2012-10-17" + }) +} + +resource "aws_glue_catalog_database" "test" { + name = %[1]q +} + +resource "aws_glue_catalog_table" "test" { + name = %[1]q + database_name = aws_glue_catalog_database.test.name + + storage_descriptor { + columns { + name = "event" + type = "string" + } + + columns { + name = "timestamp" + type = "date" + } - assume_role_policy = < Date: Thu, 8 Jul 2021 14:30:02 -0400 Subject: [PATCH 05/24] r/lakeformation_permissions: Fix bugs --- aws/resource_aws_lakeformation_permissions.go | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_lakeformation_permissions.go b/aws/resource_aws_lakeformation_permissions.go index 93dc46901588..98c454df7edb 100644 --- a/aws/resource_aws_lakeformation_permissions.go +++ b/aws/resource_aws_lakeformation_permissions.go @@ -484,6 +484,18 @@ func resourceAwsLakeFormationPermissionsRead(d *schema.ResourceData, meta interf if v, ok := d.GetOk("table"); ok && len(v.([]interface{})) > 0 { // since perm list could include TableWithColumns, get the right one for _, perm := range cleanPermissions { + if perm.Resource == nil { + continue + } + + if perm.Resource.TableWithColumns != nil && perm.Resource.TableWithColumns.ColumnWildcard != nil { + if err := d.Set("table", []interface{}{flattenLakeFormationTableWithColumnsResourceAsTable(perm.Resource.TableWithColumns)}); err != nil { + return fmt.Errorf("error setting table: %w", err) + } + tableSet = true + break + } + if perm.Resource.Table != nil { if err := d.Set("table", []interface{}{flattenLakeFormationTableResource(perm.Resource.Table)}); err != nil { return fmt.Errorf("error setting table: %w", err) @@ -491,6 +503,7 @@ func resourceAwsLakeFormationPermissionsRead(d *schema.ResourceData, meta interf tableSet = true break } + } } @@ -585,7 +598,7 @@ func resourceAwsLakeFormationPermissionsDelete(d *schema.ResourceData, meta inte _, err = conn.RevokePermissions(input) } - if tfawserr.ErrMessageContains(err, lakeformation.ErrCodeInvalidInputException, "No permissions revoked. Grantee has no") { + if tfawserr.ErrMessageContains(err, lakeformation.ErrCodeInvalidInputException, "No permissions revoked. Grantee") { return nil } @@ -616,7 +629,11 @@ func resourceAwsLakeFormationPermissionsDelete(d *schema.ResourceData, meta inte _, err = conn.RevokePermissions(input) } - if err != nil && !tfawserr.ErrMessageContains(err, lakeformation.ErrCodeInvalidInputException, "No permissions revoked. Grantee has no") { + if tfawserr.ErrMessageContains(err, lakeformation.ErrCodeInvalidInputException, "No permissions revoked. Grantee") { + return nil + } + + if err != nil { return fmt.Errorf("unable to revoke LakeFormation Permissions (input: %v): %w", input, err) } @@ -844,6 +861,33 @@ func flattenLakeFormationTableWithColumnsResource(apiObject *lakeformation.Table return tfMap } +// This only happens in very specific situations: +// (Select) TWC + ColumnWildcard = (Select) Table +// (Select) TWC + ColumnWildcard + ALL_TABLES = (Select) Table + TableWildcard +func flattenLakeFormationTableWithColumnsResourceAsTable(apiObject *lakeformation.TableWithColumnsResource) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.CatalogId; v != nil { + tfMap["catalog_id"] = aws.StringValue(v) + } + + if v := apiObject.DatabaseName; v != nil { + tfMap["database_name"] = aws.StringValue(v) + } + + if v := apiObject.Name; v != nil && aws.StringValue(v) == tflakeformation.TableNameAllTables && apiObject.ColumnWildcard != nil { + tfMap["wildcard"] = true + } else if v := apiObject.Name; v != nil { + tfMap["name"] = aws.StringValue(v) + } + + return tfMap +} + func flattenLakeFormationPermissions(apiObjects []*lakeformation.PrincipalResourcePermissions) []string { if apiObjects == nil { return nil From 2199d55c8390d720be0ce28674e431d73bd10ab0 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:30:34 -0400 Subject: [PATCH 06/24] tests/lakeformation_data_lake_setting: Rework for STS --- ...s_lakeformation_data_lake_settings_test.go | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/aws/resource_aws_lakeformation_data_lake_settings_test.go b/aws/resource_aws_lakeformation_data_lake_settings_test.go index 3c3ec5375ae2..fcbfc1cb6366 100644 --- a/aws/resource_aws_lakeformation_data_lake_settings_test.go +++ b/aws/resource_aws_lakeformation_data_lake_settings_test.go @@ -12,7 +12,6 @@ import ( ) func testAccAWSLakeFormationDataLakeSettings_basic(t *testing.T) { - callerIdentityName := "data.aws_caller_identity.current" resourceName := "aws_lakeformation_data_lake_settings.test" resource.Test(t, resource.TestCase{ @@ -25,9 +24,9 @@ func testAccAWSLakeFormationDataLakeSettings_basic(t *testing.T) { Config: testAccAWSLakeFormationDataLakeSettingsConfig_basic, Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationDataLakeSettingsExists(resourceName), - resource.TestCheckResourceAttrPair(resourceName, "catalog_id", callerIdentityName, "account_id"), + resource.TestCheckResourceAttrPair(resourceName, "catalog_id", "data.aws_caller_identity.current", "account_id"), resource.TestCheckResourceAttr(resourceName, "admins.#", "1"), - resource.TestCheckResourceAttrPair(resourceName, "admins.0", callerIdentityName, "arn"), + resource.TestCheckResourceAttrPair(resourceName, "admins.0", "data.aws_iam_session_context.current", "issuer_arn"), ), }, }, @@ -56,7 +55,6 @@ func testAccAWSLakeFormationDataLakeSettings_disappears(t *testing.T) { } func testAccAWSLakeFormationDataLakeSettings_withoutCatalogId(t *testing.T) { - callerIdentityName := "data.aws_caller_identity.current" resourceName := "aws_lakeformation_data_lake_settings.test" resource.Test(t, resource.TestCase{ @@ -70,7 +68,7 @@ func testAccAWSLakeFormationDataLakeSettings_withoutCatalogId(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAWSLakeFormationDataLakeSettingsExists(resourceName), resource.TestCheckResourceAttr(resourceName, "admins.#", "1"), - resource.TestCheckResourceAttrPair(resourceName, "admins.0", callerIdentityName, "arn"), + resource.TestCheckResourceAttrPair(resourceName, "admins.0", "data.aws_iam_session_context.current", "issuer_arn"), ), }, }, @@ -137,6 +135,10 @@ func testAccCheckAWSLakeFormationDataLakeSettingsExists(resourceName string) res const testAccAWSLakeFormationDataLakeSettingsConfig_basic = ` 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 @@ -150,7 +152,7 @@ resource "aws_lakeformation_data_lake_settings" "test" { permissions = ["ALL"] } - admins = [data.aws_caller_identity.current.arn] + admins = [data.aws_iam_session_context.current.issuer_arn] trusted_resource_owners = [data.aws_caller_identity.current.account_id] } ` @@ -158,7 +160,11 @@ resource "aws_lakeformation_data_lake_settings" "test" { const testAccAWSLakeFormationDataLakeSettingsConfig_withoutCatalogId = ` 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" { - admins = [data.aws_caller_identity.current.arn] + admins = [data.aws_iam_session_context.current.issuer_arn] } ` From ab8c63fc7bd50a6bc2789c91910b1f3dd4bedcd2 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:31:30 -0400 Subject: [PATCH 07/24] i/lakeformation: Reduce permissions delete TO --- aws/internal/service/lakeformation/waiter/waiter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/internal/service/lakeformation/waiter/waiter.go b/aws/internal/service/lakeformation/waiter/waiter.go index 80e66a211594..ba7343e01abc 100644 --- a/aws/internal/service/lakeformation/waiter/waiter.go +++ b/aws/internal/service/lakeformation/waiter/waiter.go @@ -9,7 +9,7 @@ import ( const ( PermissionsReadyTimeout = 1 * time.Minute - PermissionsDeleteRetryTimeout = 3 * time.Minute + PermissionsDeleteRetryTimeout = 30 * time.Second StatusAvailable = "AVAILABLE" StatusNotFound = "NOT FOUND" From ddedf2ebc25c2973128ba2de81a82934f54df86f Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:32:12 -0400 Subject: [PATCH 08/24] i/lakeformation: Ensure same principal --- aws/internal/service/lakeformation/waiter/status.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/aws/internal/service/lakeformation/waiter/status.go b/aws/internal/service/lakeformation/waiter/status.go index fca281e92165..80beaa016a8f 100644 --- a/aws/internal/service/lakeformation/waiter/status.go +++ b/aws/internal/service/lakeformation/waiter/status.go @@ -3,6 +3,7 @@ package waiter import ( "fmt" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/lakeformation" "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -19,6 +20,10 @@ func PermissionsStatus(conn *lakeformation.LakeFormation, input *lakeformation.L continue } + if aws.StringValue(input.Principal.DataLakePrincipalIdentifier) != aws.StringValue(permission.Principal.DataLakePrincipalIdentifier) { + continue + } + permissions = append(permissions, permission) } return !lastPage From 1a3c9faad1b7deb112ec439ccb74b4fded8338d8 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:33:09 -0400 Subject: [PATCH 09/24] i/lakeformation: Filter out different principals --- aws/internal/service/lakeformation/filter.go | 46 +++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/aws/internal/service/lakeformation/filter.go b/aws/internal/service/lakeformation/filter.go index 916df407ebd1..1d53fb8fd6d5 100644 --- a/aws/internal/service/lakeformation/filter.go +++ b/aws/internal/service/lakeformation/filter.go @@ -8,12 +8,6 @@ import ( "github.com/aws/aws-sdk-go/service/lakeformation" ) -const ( - TableNameAllTables = "ALL_TABLES" - TableTypeTable = "Table" - TableTypeTableWithColumns = "TableWithColumns" -) - func FilterPermissions(input *lakeformation.ListPermissionsInput, tableType string, columnNames []*string, excludedColumnNames []*string, columnWildcard bool, allPermissions []*lakeformation.PrincipalResourcePermissions) []*lakeformation.PrincipalResourcePermissions { // For most Lake Formation resources, filtering within the provider is unnecessary. The input // contains everything for AWS to give you back exactly what you want. However, many challenges @@ -29,29 +23,29 @@ func FilterPermissions(input *lakeformation.ListPermissionsInput, tableType stri // permissions in the special cases to avoid extra permissions being included. if input.Resource.Catalog != nil { - return FilterLakeFormationCatalogPermissions(allPermissions) + return FilterLakeFormationCatalogPermissions(input.Principal.DataLakePrincipalIdentifier, allPermissions) } if input.Resource.DataLocation != nil { - return FilterLakeFormationDataLocationPermissions(allPermissions) + return FilterLakeFormationDataLocationPermissions(input.Principal.DataLakePrincipalIdentifier, allPermissions) } if input.Resource.Database != nil { - return FilterLakeFormationDatabasePermissions(allPermissions) + return FilterLakeFormationDatabasePermissions(input.Principal.DataLakePrincipalIdentifier, allPermissions) } if tableType == TableTypeTableWithColumns { - return FilterLakeFormationTableWithColumnsPermissions(input.Resource.Table, columnNames, excludedColumnNames, columnWildcard, allPermissions) + return FilterLakeFormationTableWithColumnsPermissions(input.Principal.DataLakePrincipalIdentifier, input.Resource.Table, columnNames, excludedColumnNames, columnWildcard, allPermissions) } if input.Resource.Table != nil || tableType == TableTypeTable { - return FilterLakeFormationTablePermissions(input.Resource.Table, allPermissions) + return FilterLakeFormationTablePermissions(input.Principal.DataLakePrincipalIdentifier, input.Resource.Table, allPermissions) } return nil } -func FilterLakeFormationTablePermissions(table *lakeformation.TableResource, allPermissions []*lakeformation.PrincipalResourcePermissions) []*lakeformation.PrincipalResourcePermissions { +func FilterLakeFormationTablePermissions(principal *string, table *lakeformation.TableResource, allPermissions []*lakeformation.PrincipalResourcePermissions) []*lakeformation.PrincipalResourcePermissions { // CREATE PERMS (in) = ALL, ALTER, DELETE, DESCRIBE, DROP, INSERT, SELECT on Table, Name = (Table Name) // LIST PERMS (out) = ALL, ALTER, DELETE, DESCRIBE, DROP, INSERT on Table, Name = (Table Name) // LIST PERMS (out) = SELECT on TableWithColumns, Name = (Table Name), ColumnWildcard @@ -63,6 +57,10 @@ func FilterLakeFormationTablePermissions(table *lakeformation.TableResource, all var cleanPermissions []*lakeformation.PrincipalResourcePermissions for _, perm := range allPermissions { + if aws.StringValue(principal) != aws.StringValue(perm.Principal.DataLakePrincipalIdentifier) { + continue + } + if perm.Resource.TableWithColumns != nil && perm.Resource.TableWithColumns.ColumnWildcard != nil { if aws.StringValue(perm.Resource.TableWithColumns.Name) == aws.StringValue(table.Name) || (table.TableWildcard != nil && aws.StringValue(perm.Resource.TableWithColumns.Name) == TableNameAllTables) { if len(perm.Permissions) > 0 && aws.StringValue(perm.Permissions[0]) == lakeformation.PermissionSelect { @@ -94,7 +92,7 @@ func FilterLakeFormationTablePermissions(table *lakeformation.TableResource, all return cleanPermissions } -func FilterLakeFormationTableWithColumnsPermissions(twc *lakeformation.TableResource, columnNames []*string, excludedColumnNames []*string, columnWildcard bool, allPermissions []*lakeformation.PrincipalResourcePermissions) []*lakeformation.PrincipalResourcePermissions { +func FilterLakeFormationTableWithColumnsPermissions(principal *string, twc *lakeformation.TableResource, columnNames []*string, excludedColumnNames []*string, columnWildcard bool, allPermissions []*lakeformation.PrincipalResourcePermissions) []*lakeformation.PrincipalResourcePermissions { // CREATE PERMS (in) = ALL, ALTER, DELETE, DESCRIBE, DROP, INSERT, SELECT on TableWithColumns, Name = (Table Name), ColumnWildcard // LIST PERMS (out) = ALL, ALTER, DELETE, DESCRIBE, DROP, INSERT on Table, Name = (Table Name) // LIST PERMS (out) = SELECT on TableWithColumns, Name = (Table Name), ColumnWildcard @@ -102,6 +100,10 @@ func FilterLakeFormationTableWithColumnsPermissions(twc *lakeformation.TableReso var cleanPermissions []*lakeformation.PrincipalResourcePermissions for _, perm := range allPermissions { + if aws.StringValue(principal) != aws.StringValue(perm.Principal.DataLakePrincipalIdentifier) { + continue + } + if perm.Resource.TableWithColumns != nil && perm.Resource.TableWithColumns.ColumnNames != nil { if StringSlicesEqualIgnoreOrder(perm.Resource.TableWithColumns.ColumnNames, columnNames) { cleanPermissions = append(cleanPermissions, perm) @@ -130,10 +132,14 @@ func FilterLakeFormationTableWithColumnsPermissions(twc *lakeformation.TableReso return cleanPermissions } -func FilterLakeFormationCatalogPermissions(allPermissions []*lakeformation.PrincipalResourcePermissions) []*lakeformation.PrincipalResourcePermissions { +func FilterLakeFormationCatalogPermissions(principal *string, allPermissions []*lakeformation.PrincipalResourcePermissions) []*lakeformation.PrincipalResourcePermissions { var cleanPermissions []*lakeformation.PrincipalResourcePermissions for _, perm := range allPermissions { + if aws.StringValue(principal) != aws.StringValue(perm.Principal.DataLakePrincipalIdentifier) { + continue + } + if perm.Resource.Catalog != nil { cleanPermissions = append(cleanPermissions, perm) } @@ -142,10 +148,14 @@ func FilterLakeFormationCatalogPermissions(allPermissions []*lakeformation.Princ return cleanPermissions } -func FilterLakeFormationDataLocationPermissions(allPermissions []*lakeformation.PrincipalResourcePermissions) []*lakeformation.PrincipalResourcePermissions { +func FilterLakeFormationDataLocationPermissions(principal *string, allPermissions []*lakeformation.PrincipalResourcePermissions) []*lakeformation.PrincipalResourcePermissions { var cleanPermissions []*lakeformation.PrincipalResourcePermissions for _, perm := range allPermissions { + if aws.StringValue(principal) != aws.StringValue(perm.Principal.DataLakePrincipalIdentifier) { + continue + } + if perm.Resource.DataLocation != nil { cleanPermissions = append(cleanPermissions, perm) } @@ -154,10 +164,14 @@ func FilterLakeFormationDataLocationPermissions(allPermissions []*lakeformation. return cleanPermissions } -func FilterLakeFormationDatabasePermissions(allPermissions []*lakeformation.PrincipalResourcePermissions) []*lakeformation.PrincipalResourcePermissions { +func FilterLakeFormationDatabasePermissions(principal *string, allPermissions []*lakeformation.PrincipalResourcePermissions) []*lakeformation.PrincipalResourcePermissions { var cleanPermissions []*lakeformation.PrincipalResourcePermissions for _, perm := range allPermissions { + if aws.StringValue(principal) != aws.StringValue(perm.Principal.DataLakePrincipalIdentifier) { + continue + } + if perm.Resource.Database != nil { cleanPermissions = append(cleanPermissions, perm) } From db714c3a32299f7a71d9810d400bf8a53af1480f Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:34:17 -0400 Subject: [PATCH 10/24] tests/d/lakeformation_data_lake_settings: Rework for STS --- ...ource_aws_lakeformation_data_lake_settings_test.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/aws/data_source_aws_lakeformation_data_lake_settings_test.go b/aws/data_source_aws_lakeformation_data_lake_settings_test.go index fa1fe4ab7d4a..09b424fe346a 100644 --- a/aws/data_source_aws_lakeformation_data_lake_settings_test.go +++ b/aws/data_source_aws_lakeformation_data_lake_settings_test.go @@ -8,7 +8,6 @@ import ( ) func testAccAWSLakeFormationDataLakeSettingsDataSource_basic(t *testing.T) { - callerIdentityName := "data.aws_caller_identity.current" resourceName := "data.aws_lakeformation_data_lake_settings.test" resource.Test(t, resource.TestCase{ @@ -20,9 +19,9 @@ func testAccAWSLakeFormationDataLakeSettingsDataSource_basic(t *testing.T) { { Config: testAccAWSLakeFormationDataLakeSettingsDataSourceConfig_basic, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrPair(resourceName, "catalog_id", callerIdentityName, "account_id"), + resource.TestCheckResourceAttrPair(resourceName, "catalog_id", "data.aws_caller_identity.current", "account_id"), resource.TestCheckResourceAttr(resourceName, "admins.#", "1"), - resource.TestCheckResourceAttrPair(resourceName, "admins.0", callerIdentityName, "arn"), + resource.TestCheckResourceAttrPair(resourceName, "admins.0", "data.aws_iam_session_context.current", "issuer_arn"), ), }, }, @@ -32,9 +31,13 @@ func testAccAWSLakeFormationDataLakeSettingsDataSource_basic(t *testing.T) { const testAccAWSLakeFormationDataLakeSettingsDataSourceConfig_basic = ` 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 - admins = [data.aws_caller_identity.current.arn] + admins = [data.aws_iam_session_context.current.issuer_arn] } data "aws_lakeformation_data_lake_settings" "test" { From 259c816a79ebcbd833120e67463f4f64569e3b11 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:34:47 -0400 Subject: [PATCH 11/24] tests/d/lakeformation_permissions: Rework for STS --- ...urce_aws_lakeformation_permissions_test.go | 168 +++++++++--------- 1 file changed, 82 insertions(+), 86 deletions(-) diff --git a/aws/data_source_aws_lakeformation_permissions_test.go b/aws/data_source_aws_lakeformation_permissions_test.go index fe111e051e23..47d2a77ca5af 100644 --- a/aws/data_source_aws_lakeformation_permissions_test.go +++ b/aws/data_source_aws_lakeformation_permissions_test.go @@ -148,28 +148,28 @@ data "aws_partition" "current" {} resource "aws_iam_role" "test" { name = %[1]q + path = "/" - assume_role_policy = < Date: Thu, 8 Jul 2021 14:35:15 -0400 Subject: [PATCH 12/24] d/lakeformation_permissions: Fix bugs --- aws/data_source_aws_lakeformation_permissions.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/aws/data_source_aws_lakeformation_permissions.go b/aws/data_source_aws_lakeformation_permissions.go index 9a9c48e777c9..97963b217158 100644 --- a/aws/data_source_aws_lakeformation_permissions.go +++ b/aws/data_source_aws_lakeformation_permissions.go @@ -277,6 +277,18 @@ func dataSourceAwsLakeFormationPermissionsRead(d *schema.ResourceData, meta inte if v, ok := d.GetOk("table"); ok && len(v.([]interface{})) > 0 { // since perm list could include TableWithColumns, get the right one for _, perm := range cleanPermissions { + if perm.Resource == nil { + continue + } + + if perm.Resource.TableWithColumns != nil && perm.Resource.TableWithColumns.ColumnWildcard != nil { + if err := d.Set("table", []interface{}{flattenLakeFormationTableWithColumnsResourceAsTable(perm.Resource.TableWithColumns)}); err != nil { + return fmt.Errorf("error setting table: %w", err) + } + tableSet = true + break + } + if perm.Resource.Table != nil { if err := d.Set("table", []interface{}{flattenLakeFormationTableResource(perm.Resource.Table)}); err != nil { return fmt.Errorf("error setting table: %w", err) From 8abe9aa435ee949a8de211ac01e64f2af44ad886 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:38:45 -0400 Subject: [PATCH 13/24] r/lakeformation_permissions: Add changelog --- .changelog/20108.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changelog/20108.txt diff --git a/.changelog/20108.txt b/.changelog/20108.txt new file mode 100644 index 000000000000..5edc7273ce89 --- /dev/null +++ b/.changelog/20108.txt @@ -0,0 +1,7 @@ +```release-note:bug +resource/aws_lakeformation_permissions: Fix various problems with permissions including select-only +``` + +```release-note:bug +data-source/aws_lakeformation_permissions: Fix various problems with permissions including select-only +``` \ No newline at end of file From 08bba8df4db7b24c6c4ea0fd798611957116f319 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:42:56 -0400 Subject: [PATCH 14/24] r/lakeformation_permissions: Linty McLintface --- aws/resource_aws_lakeformation_permissions_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/resource_aws_lakeformation_permissions_test.go b/aws/resource_aws_lakeformation_permissions_test.go index 8fcbb28dcc4d..1299494e0df1 100644 --- a/aws/resource_aws_lakeformation_permissions_test.go +++ b/aws/resource_aws_lakeformation_permissions_test.go @@ -2013,7 +2013,7 @@ resource "aws_lakeformation_permissions" "test" { table_with_columns { database_name = aws_glue_catalog_table.test.database_name name = aws_glue_catalog_table.test.name - wildcard = true + wildcard = true } # for consistency, ensure that admins are setup before testing From 0538764c74c173f82a5fb2530dcc3bf65b9cce64 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:45:06 -0400 Subject: [PATCH 15/24] r/lakeformation_permissions: Linty McLintface --- aws/resource_aws_lakeformation_permissions_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_lakeformation_permissions_test.go b/aws/resource_aws_lakeformation_permissions_test.go index 1299494e0df1..70803f348e5e 100644 --- a/aws/resource_aws_lakeformation_permissions_test.go +++ b/aws/resource_aws_lakeformation_permissions_test.go @@ -1015,7 +1015,7 @@ resource "aws_glue_catalog_table" "test" { resource "aws_lakeformation_permissions" "test" { permissions = ["ALL"] principal = "IAM_ALLOWED_PRINCIPALS" - + database { name = aws_glue_catalog_database.test.name } @@ -1261,7 +1261,7 @@ resource "aws_glue_catalog_table" "test" { resource "aws_lakeformation_permissions" "test" { permissions = ["ALL"] principal = "IAM_ALLOWED_PRINCIPALS" - + table { database_name = aws_glue_catalog_database.test.name name = aws_glue_catalog_table.test.name From ede6a1a40bc820a72bc1a7dc0842412371d7666c Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:52:03 -0400 Subject: [PATCH 16/24] r/lakeformation_permissions: Linty McLintface --- aws/resource_aws_lakeformation_permissions_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aws/resource_aws_lakeformation_permissions_test.go b/aws/resource_aws_lakeformation_permissions_test.go index 70803f348e5e..57db85a834a0 100644 --- a/aws/resource_aws_lakeformation_permissions_test.go +++ b/aws/resource_aws_lakeformation_permissions_test.go @@ -1090,8 +1090,8 @@ resource "aws_lakeformation_permissions" "test" { } resource "aws_lakeformation_permissions" "test2" { - permissions = ["ALTER", "DROP"] - principal = aws_iam_role.test2.arn + permissions = ["ALTER", "DROP"] + principal = aws_iam_role.test2.arn database { name = aws_glue_catalog_database.test.name @@ -1118,13 +1118,13 @@ resource "aws_iam_role" "test" { Principal = { Service = "glue.${data.aws_partition.current.dns_suffix}" } - },{ + }, { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "s3.${data.aws_partition.current.dns_suffix}" } - }] + }] Version = "2012-10-17" }) } From 9c50c5cb97f2a9ef58003e7062eca14c97ccb74f Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:53:58 -0400 Subject: [PATCH 17/24] docs/r/lakeformation_permissions: Curse you trailing whitespace --- website/docs/r/lakeformation_permissions.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/lakeformation_permissions.html.markdown b/website/docs/r/lakeformation_permissions.html.markdown index d6b116689bf3..a73c9e6bf31f 100644 --- a/website/docs/r/lakeformation_permissions.html.markdown +++ b/website/docs/r/lakeformation_permissions.html.markdown @@ -39,7 +39,7 @@ resource "aws_lakeformation_data_lake_settings" "test" { To remove existing `IAMAllowedPrincipals` permissions, use the [AWS Lake Formation Console](https://console.aws.amazon.com/lakeformation/) or [AWS CLI](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lakeformation/batch-revoke-permissions.html). -`IAMAllowedPrincipals` is a hook to maintain backwards compatibility with AWS Glue. `IAMAllowedPrincipals` is a pseudo-entity group that acts like a Lake Formation principal. The group includes any IAM users and roles that are allowed access to your Data Catalog resources by your IAM policies. +`IAMAllowedPrincipals` is a hook to maintain backwards compatibility with AWS Glue. `IAMAllowedPrincipals` is a pseudo-entity group that acts like a Lake Formation principal. The group includes any IAM users and roles that are allowed access to your Data Catalog resources by your IAM policies. This is Lake Formation's default behavior: From b60dbffe10e0cb1a53b18747fa42a4dd3f3f6e19 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 14:55:38 -0400 Subject: [PATCH 18/24] docs/r/lakeformation_permissions: Clarify behavior --- website/docs/r/lakeformation_permissions.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/lakeformation_permissions.html.markdown b/website/docs/r/lakeformation_permissions.html.markdown index a73c9e6bf31f..fa119544576b 100644 --- a/website/docs/r/lakeformation_permissions.html.markdown +++ b/website/docs/r/lakeformation_permissions.html.markdown @@ -85,7 +85,7 @@ The resulting permissions depend on whether the table had `IAMAllowedPrincipals` | Result With IAP | Result Without IAP | | ---- | ---- | -| `SELECT` on table with columns with column wildcard (i.e., all columns) | `SELECT` on `"event"` (as expected) | +| `SELECT` column wildcard (i.e., all columns) | `SELECT` on `"event"` (as expected) | ## Using Lake Formation Permissions From b880067a1fc07c1d3ccf7b2df319e25996fef593 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 15:00:32 -0400 Subject: [PATCH 19/24] docs/r/lakeformation_permissions: Heading --- website/docs/r/lakeformation_permissions.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/lakeformation_permissions.html.markdown b/website/docs/r/lakeformation_permissions.html.markdown index fa119544576b..7d98355ec117 100644 --- a/website/docs/r/lakeformation_permissions.html.markdown +++ b/website/docs/r/lakeformation_permissions.html.markdown @@ -48,7 +48,7 @@ This is Lake Formation's default behavior: For more details, see [Changing the Default Security Settings for Your Data Lake](https://docs.aws.amazon.com/lake-formation/latest/dg/change-settings.html). -### Example Problem Using `IAMAllowedPrincipals` +### Problem Using `IAMAllowedPrincipals` AWS does not support combining `IAMAllowedPrincipals` permissions and non-`IAMAllowedPrincipals` permissions. Doing so results in unexpected permissions. For example, this configuration grants a user `SELECT` on a column in a table. From 306bd032dd2ba78fb7f64dff9d687c637da05d79 Mon Sep 17 00:00:00 2001 From: Dirk Avery <31492422+YakDriver@users.noreply.github.com> Date: Thu, 8 Jul 2021 15:16:38 -0400 Subject: [PATCH 20/24] docs/r/lakeformation_permissions: Soften language Co-authored-by: Mary Elizabeth --- website/docs/r/lakeformation_permissions.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/lakeformation_permissions.html.markdown b/website/docs/r/lakeformation_permissions.html.markdown index 7d98355ec117..75cb4c478af7 100644 --- a/website/docs/r/lakeformation_permissions.html.markdown +++ b/website/docs/r/lakeformation_permissions.html.markdown @@ -18,7 +18,7 @@ Grants permissions to the principal to access metadata in the Data Catalog and d **_Lake Formation permissions are not in effect by default within AWS._** `IAMAllowedPrincipals` (i.e., `IAM_ALLOWED_PRINCIPALS`) conflicts with individual Lake Formation permissions (i.e., non-`IAMAllowedPrincipals` permissions), will cause unexpected behavior, and may result in errors. -When using Lake Formation, you need to choose between these two mutually exclusive options: +When using Lake Formation, choose ONE of the following options as they are mutually exclusive: 1. Use this resource (`aws_lakeformation_permissions`), change the default security settings using [`aws_lakeformation_data_lake_settings`](/docs/providers/aws/r/lakeformation_data_lake_settings.html), and remove existing `IAMAllowedPrincipals` permissions 2. Use `IAMAllowedPrincipals` and not use this resource From ddab58c36c488d4d77de8adece1ef2f7b7551ce3 Mon Sep 17 00:00:00 2001 From: Dirk Avery <31492422+YakDriver@users.noreply.github.com> Date: Thu, 8 Jul 2021 15:17:08 -0400 Subject: [PATCH 21/24] docs/r/lakeformation_permissions: Clarify Co-authored-by: Mary Elizabeth --- website/docs/r/lakeformation_permissions.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/lakeformation_permissions.html.markdown b/website/docs/r/lakeformation_permissions.html.markdown index 75cb4c478af7..81e5bb583f01 100644 --- a/website/docs/r/lakeformation_permissions.html.markdown +++ b/website/docs/r/lakeformation_permissions.html.markdown @@ -21,7 +21,7 @@ Grants permissions to the principal to access metadata in the Data Catalog and d When using Lake Formation, choose ONE of the following options as they are mutually exclusive: 1. Use this resource (`aws_lakeformation_permissions`), change the default security settings using [`aws_lakeformation_data_lake_settings`](/docs/providers/aws/r/lakeformation_data_lake_settings.html), and remove existing `IAMAllowedPrincipals` permissions -2. Use `IAMAllowedPrincipals` and not use this resource +2. Use `IAMAllowedPrincipals` without `aws_lakeformation_permissions` ``` This example shows removing the `IAMAllowedPrincipals` default security settings and making the caller a Lake Formation admin. Since `create_database_default_permissions` and `create_table_default_permissions` are not set in the [`aws_lakeformation_data_lake_settings`](/docs/providers/aws/r/lakeformation_data_lake_settings.html) resource, they are cleared. From fb040dd8f7429b1172616eb9423be5356e3f1298 Mon Sep 17 00:00:00 2001 From: Dirk Avery <31492422+YakDriver@users.noreply.github.com> Date: Thu, 8 Jul 2021 15:17:36 -0400 Subject: [PATCH 22/24] docs/r/lakeformation_permissions: Clean up language Co-authored-by: Mary Elizabeth --- website/docs/r/lakeformation_permissions.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/lakeformation_permissions.html.markdown b/website/docs/r/lakeformation_permissions.html.markdown index 81e5bb583f01..c23c637c16d7 100644 --- a/website/docs/r/lakeformation_permissions.html.markdown +++ b/website/docs/r/lakeformation_permissions.html.markdown @@ -50,7 +50,7 @@ For more details, see [Changing the Default Security Settings for Your Data Lake ### Problem Using `IAMAllowedPrincipals` -AWS does not support combining `IAMAllowedPrincipals` permissions and non-`IAMAllowedPrincipals` permissions. Doing so results in unexpected permissions. For example, this configuration grants a user `SELECT` on a column in a table. +AWS does not support combining `IAMAllowedPrincipals` permissions and non-`IAMAllowedPrincipals` permissions. Doing so results in unexpected permissions and behaviors. For example, this configuration grants a user `SELECT` on a column in a table. ```terraform resource "aws_glue_catalog_database" "example" { From ad016d2b0c2930ef853fdc29de7f6eb1f94eb8b1 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 15:20:37 -0400 Subject: [PATCH 23/24] r/lakeformation_permissions: Errant newline --- aws/resource_aws_lakeformation_permissions.go | 1 - 1 file changed, 1 deletion(-) diff --git a/aws/resource_aws_lakeformation_permissions.go b/aws/resource_aws_lakeformation_permissions.go index 98c454df7edb..0b95cc9ab0d6 100644 --- a/aws/resource_aws_lakeformation_permissions.go +++ b/aws/resource_aws_lakeformation_permissions.go @@ -503,7 +503,6 @@ func resourceAwsLakeFormationPermissionsRead(d *schema.ResourceData, meta interf tableSet = true break } - } } From 8b7cb8e715a8249f4eee3ce6aab60697673abbda Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 8 Jul 2021 16:07:18 -0400 Subject: [PATCH 24/24] docs/r/lakeformation_permissions: Remove errants ticks --- website/docs/r/lakeformation_permissions.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/lakeformation_permissions.html.markdown b/website/docs/r/lakeformation_permissions.html.markdown index c23c637c16d7..18f7e326d198 100644 --- a/website/docs/r/lakeformation_permissions.html.markdown +++ b/website/docs/r/lakeformation_permissions.html.markdown @@ -21,7 +21,7 @@ Grants permissions to the principal to access metadata in the Data Catalog and d When using Lake Formation, choose ONE of the following options as they are mutually exclusive: 1. Use this resource (`aws_lakeformation_permissions`), change the default security settings using [`aws_lakeformation_data_lake_settings`](/docs/providers/aws/r/lakeformation_data_lake_settings.html), and remove existing `IAMAllowedPrincipals` permissions -2. Use `IAMAllowedPrincipals` without `aws_lakeformation_permissions` ``` +2. Use `IAMAllowedPrincipals` without `aws_lakeformation_permissions` This example shows removing the `IAMAllowedPrincipals` default security settings and making the caller a Lake Formation admin. Since `create_database_default_permissions` and `create_table_default_permissions` are not set in the [`aws_lakeformation_data_lake_settings`](/docs/providers/aws/r/lakeformation_data_lake_settings.html) resource, they are cleared.