From 5298adb678beca1359e803a6ec271de3aa9d5354 Mon Sep 17 00:00:00 2001 From: Ian Mobbs Date: Wed, 12 Oct 2022 09:35:18 -0700 Subject: [PATCH 1/4] ACCT-4178: Add raw permissions struct to provider --- internal/provider/data_source_api_token_permission_groups.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/provider/data_source_api_token_permission_groups.go b/internal/provider/data_source_api_token_permission_groups.go index 5945e19c48..0ba4e81c49 100644 --- a/internal/provider/data_source_api_token_permission_groups.go +++ b/internal/provider/data_source_api_token_permission_groups.go @@ -32,6 +32,11 @@ func dataSourceCloudflareApiTokenPermissionGroupsRead(ctx context.Context, d *sc return diag.FromErr(fmt.Errorf("error listing API Token Permission Groups: %w", err)) } + err = d.Set("raw_permissions", permissions) + if err != nil { + return diag.FromErr(fmt.Errorf("error setting API Token Permission Group structs: %w", err)) + } + permissionDetails := make(map[string]interface{}, 0) ids := []string{} for _, v := range permissions { From 5956ef9ef559cfdd5d64dde8113be3f3ae944093 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 16 Nov 2022 14:30:19 +1100 Subject: [PATCH 2/4] data-source/api_token_permission_groups: move to scoped based attributes --- .../api_token_permission_groups.md | 43 ++++++++---- .../data-source.tf | 16 +++++ ...data_source_api_token_permission_groups.go | 65 ++++++++++++++++--- ...source_api_token_permission_groups_test.go | 41 +++++++++++- .../api_token_permission_groups.md | 24 ------- 5 files changed, 141 insertions(+), 48 deletions(-) create mode 100644 examples/data-sources/cloudflare_api_token_permission_groups/data-source.tf delete mode 100644 templates/data-sources/api_token_permission_groups.md diff --git a/docs/data-sources/api_token_permission_groups.md b/docs/data-sources/api_token_permission_groups.md index ec1845361b..af4c8c9ffc 100644 --- a/docs/data-sources/api_token_permission_groups.md +++ b/docs/data-sources/api_token_permission_groups.md @@ -1,24 +1,45 @@ --- -layout: "cloudflare" -page_title: "Cloudflare: cloudflare_api_token_permission_groups" -description: List available API Token Permission Group IDs. +page_title: "cloudflare_api_token_permission_groups Data Source - Cloudflare" +subcategory: "" +description: |- + Use this data source to look up API Token Permission Groups https://developers.cloudflare.com/api/tokens/create/permissions. + Commonly used as references within cloudflare_token resources. --- -# cloudflare_api_token_permission_groups +# cloudflare_api_token_permission_groups (Data Source) -Use this data source to look up [API Token Permission Groups](https://developers.cloudflare.com/api/tokens/create/permissions). Commonly used as references within [`cloudflare_api_token`](/docs/providers/cloudflare/r/api_token.html) resources. +Use this data source to look up [API Token Permission Groups](https://developers.cloudflare.com/api/tokens/create/permissions). +Commonly used as references within [`cloudflare_token`](/docs/providers/cloudflare/r/api_token.html) resources. ## Example Usage -```hcl -data "cloudflare_api_token_permission_groups" "test" {} +```terraform +data "cloudflare_api_token_permission_groups" "all" {} +# Get zone level DNS read permission ID. output "dns_read_permission_id" { - value = data.cloudflare_api_token_permission_groups.test.permissions["DNS Read"] // 82e64a83756745bbbb1c9c2701bf816b + value = data.cloudflare_api_token_permission_groups.all.zone["DNS Read"] // 82e64a83756745bbbb1c9c2701bf816b +} + +# Get account level "Load Balancing: Monitors and Pools Read" permission ID. +output "account_lb_monitors_and_read_id" { + value = data.cloudflare_api_token_permission_groups.all.account["Load Balancing: Monitors and Pools Read"] // 9d24387c6e8544e2bc4024a03991339f +} + +# Get user level "Memberships Read" permission ID. +output "user_memberships_read_id" { + value = data.cloudflare_api_token_permission_groups.all.user["Memberships Read"] // 3518d0f75557482e952c6762d3e64903 } ``` + +## Schema + +### Read-Only + +- `account` (Map of String) Map of permissions for account level resources. +- `id` (String) The ID of this resource. +- `permissions` (Map of String, Deprecated) Map of all permissions available. Should not be used as some permissions will overlap resource scope. Instead, use resource level specific attributes. +- `user` (Map of String) Map of permissions for user level resources. +- `zone` (Map of String) Map of permissions for zone level resources. -## Attributes Reference -- `permissions` - A map of permission groups where keys are human-readable permission names - and values are permission IDs. diff --git a/examples/data-sources/cloudflare_api_token_permission_groups/data-source.tf b/examples/data-sources/cloudflare_api_token_permission_groups/data-source.tf new file mode 100644 index 0000000000..5017b304b3 --- /dev/null +++ b/examples/data-sources/cloudflare_api_token_permission_groups/data-source.tf @@ -0,0 +1,16 @@ +data "cloudflare_api_token_permission_groups" "all" {} + +# Get zone level DNS read permission ID. +output "dns_read_permission_id" { + value = data.cloudflare_api_token_permission_groups.all.zone["DNS Read"] // 82e64a83756745bbbb1c9c2701bf816b +} + +# Get account level "Load Balancing: Monitors and Pools Read" permission ID. +output "account_lb_monitors_and_read_id" { + value = data.cloudflare_api_token_permission_groups.all.account["Load Balancing: Monitors and Pools Read"] // 9d24387c6e8544e2bc4024a03991339f +} + +# Get user level "Memberships Read" permission ID. +output "user_memberships_read_id" { + value = data.cloudflare_api_token_permission_groups.all.user["Memberships Read"] // 3518d0f75557482e952c6762d3e64903 +} diff --git a/internal/provider/data_source_api_token_permission_groups.go b/internal/provider/data_source_api_token_permission_groups.go index 0ba4e81c49..e48952223f 100644 --- a/internal/provider/data_source_api_token_permission_groups.go +++ b/internal/provider/data_source_api_token_permission_groups.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/MakeNowJust/heredoc/v2" "github.com/cloudflare/cloudflare-go" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -13,11 +14,31 @@ import ( func dataSourceCloudflareApiTokenPermissionGroups() *schema.Resource { return &schema.Resource{ ReadContext: dataSourceCloudflareApiTokenPermissionGroupsRead, - + Description: heredoc.Docf(` + Use this data source to look up [API Token Permission Groups](https://developers.cloudflare.com/api/tokens/create/permissions). + Commonly used as references within [%s](/docs/providers/cloudflare/r/api_token.html) resources. + `, "`cloudflare_token`"), Schema: map[string]*schema.Schema{ "permissions": { - Computed: true, - Type: schema.TypeMap, + Computed: true, + Type: schema.TypeMap, + Deprecated: "Use specific account, zone or user attributes instead.", + Description: "Map of all permissions available. Should not be used as some permissions will overlap resource scope. Instead, use resource level specific attributes.", + }, + "zone": { + Computed: true, + Type: schema.TypeMap, + Description: "Map of permissions for zone level resources.", + }, + "account": { + Computed: true, + Type: schema.TypeMap, + Description: "Map of permissions for account level resources.", + }, + "user": { + Computed: true, + Type: schema.TypeMap, + Description: "Map of permissions for user level resources.", }, }, } @@ -32,20 +53,44 @@ func dataSourceCloudflareApiTokenPermissionGroupsRead(ctx context.Context, d *sc return diag.FromErr(fmt.Errorf("error listing API Token Permission Groups: %w", err)) } - err = d.Set("raw_permissions", permissions) - if err != nil { - return diag.FromErr(fmt.Errorf("error setting API Token Permission Group structs: %w", err)) - } - permissionDetails := make(map[string]interface{}, 0) + zoneScopes := make(map[string]interface{}, 0) + accountScopes := make(map[string]interface{}, 0) + userScopes := make(map[string]interface{}, 0) ids := []string{} + for _, v := range permissions { + // This is for backwards compatibility and shouldn't be used going forward + // due to some permissions overlapping and returning invalid IDs. permissionDetails[v.Name] = v.ID ids = append(ids, v.ID) + + switch v.Scopes[0] { + case "com.cloudflare.api.account": + accountScopes[v.Name] = v.ID + case "com.cloudflare.api.account.zone": + zoneScopes[v.Name] = v.ID + case "com.cloudflare.api.user": + userScopes[v.Name] = v.ID + default: + tflog.Warn(ctx, fmt.Sprintf("unknown permission scope found: %s", v.Scopes[0])) + } + } - err = d.Set("permissions", permissionDetails) - if err != nil { + if err = d.Set("account", accountScopes); err != nil { + return diag.FromErr(fmt.Errorf("error setting API Token Permission Groups for accounts: %w", err)) + } + + if err = d.Set("zone", zoneScopes); err != nil { + return diag.FromErr(fmt.Errorf("error setting API Token Permission Groups for zones: %w", err)) + } + + if err = d.Set("user", userScopes); err != nil { + return diag.FromErr(fmt.Errorf("error setting API Token Permission Groups for user: %w", err)) + } + + if err = d.Set("permissions", permissionDetails); err != nil { return diag.FromErr(fmt.Errorf("error setting API Token Permission Groups: %w", err)) } diff --git a/internal/provider/data_source_api_token_permission_groups_test.go b/internal/provider/data_source_api_token_permission_groups_test.go index 32c9c465e1..361f58b607 100644 --- a/internal/provider/data_source_api_token_permission_groups_test.go +++ b/internal/provider/data_source_api_token_permission_groups_test.go @@ -3,13 +3,14 @@ package provider import ( "fmt" "os" + "strconv" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) -func TestAccCloudflareApiTokenPermissionGroups(t *testing.T) { +func TestAccCloudflareApiTokenPermissionGroups_Basic(t *testing.T) { // Temporarily unset CLOUDFLARE_API_TOKEN if it is set as the API token // permission groups endpoint does not yet support the API tokens and it // results in misleading state error messages. @@ -39,13 +40,47 @@ func testAccCloudflareApiTokenPermissionGroups(n string) resource.TestCheckFunc r := s.RootModule().Resources[n] a := r.Primary.Attributes + permCount, err := strconv.Atoi(a["permissions.%"]) + if err != nil { + return fmt.Errorf("failed to convert total permission count to integer") + } + + if permCount < 100 { + return fmt.Errorf("total API token permission groups size is too small. expected: > 100, got: %d", permCount) + } + + zonePermCount, err := strconv.Atoi(a["zone.%"]) + if err != nil { + return fmt.Errorf("failed to convert zone permission count to integer") + } + + if zonePermCount < 50 { + return fmt.Errorf("zone API token permission groups size is too small. expected: > 50, got: %d", zonePermCount) + } + + accountPermCount, err := strconv.Atoi(a["account.%"]) + if err != nil { + return fmt.Errorf("failed to convert account permission count to integer") + } + + if accountPermCount < 80 { + return fmt.Errorf("account API token permission groups size is too small. expected: > 80, got: %d", accountPermCount) + } + + userPermCount, err := strconv.Atoi(a["user.%"]) + if err != nil { + return fmt.Errorf("failed to convert user permission count to integer") + } + + if userPermCount < 5 { + return fmt.Errorf("user API token permission groups size is too small. expected: > 5, got: %d", userPermCount) + } + apiTokenReadId, ok := a["permissions.API Tokens Read"] if !ok { return fmt.Errorf("couldn't get 'API Tokens Read' permission ID") } - // PermissionGroupsIDs can be found at - // https://developers.cloudflare.com/api/tokens/create/permissions apiTokenReadIdShouldBe := "0cc3a61731504c89b99ec1be78b77aa0" if apiTokenReadId != apiTokenReadIdShouldBe { diff --git a/templates/data-sources/api_token_permission_groups.md b/templates/data-sources/api_token_permission_groups.md deleted file mode 100644 index ec1845361b..0000000000 --- a/templates/data-sources/api_token_permission_groups.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -layout: "cloudflare" -page_title: "Cloudflare: cloudflare_api_token_permission_groups" -description: List available API Token Permission Group IDs. ---- - -# cloudflare_api_token_permission_groups - -Use this data source to look up [API Token Permission Groups](https://developers.cloudflare.com/api/tokens/create/permissions). Commonly used as references within [`cloudflare_api_token`](/docs/providers/cloudflare/r/api_token.html) resources. - -## Example Usage - -```hcl -data "cloudflare_api_token_permission_groups" "test" {} - -output "dns_read_permission_id" { - value = data.cloudflare_api_token_permission_groups.test.permissions["DNS Read"] // 82e64a83756745bbbb1c9c2701bf816b -} -``` - -## Attributes Reference - -- `permissions` - A map of permission groups where keys are human-readable permission names - and values are permission IDs. From cdc34073d8273a80e989ebadbb989ea7f60ed935 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 16 Nov 2022 14:33:39 +1100 Subject: [PATCH 3/4] add CHANGELOG entry --- .changelog/1960.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changelog/1960.txt diff --git a/.changelog/1960.txt b/.changelog/1960.txt new file mode 100644 index 0000000000..398dad6338 --- /dev/null +++ b/.changelog/1960.txt @@ -0,0 +1,7 @@ +```release-note:note +datasource/api_token_permission_groups: `permissions` attribute has been deprecated in favour of individual resource level attributes. +``` + +```release-note:bug +datasource/api_token_permission_groups: add `user`, `account` and `zone` attributes to contain only those specific resource level permissions. +``` From dc6e5d65d30c183820d03f9208f2ad55cd600518 Mon Sep 17 00:00:00 2001 From: Jacob Bednarz Date: Wed, 16 Nov 2022 14:36:33 +1100 Subject: [PATCH 4/4] fix lint --- internal/provider/data_source_api_token_permission_groups.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/provider/data_source_api_token_permission_groups.go b/internal/provider/data_source_api_token_permission_groups.go index e48952223f..724bc03c33 100644 --- a/internal/provider/data_source_api_token_permission_groups.go +++ b/internal/provider/data_source_api_token_permission_groups.go @@ -75,7 +75,6 @@ func dataSourceCloudflareApiTokenPermissionGroupsRead(ctx context.Context, d *sc default: tflog.Warn(ctx, fmt.Sprintf("unknown permission scope found: %s", v.Scopes[0])) } - } if err = d.Set("account", accountScopes); err != nil {