Skip to content

Commit e2a2984

Browse files
feat: Add grafana_cloud_access_policy_rotating_token resource (#2390)
1 parent c8bb737 commit e2a2984

14 files changed

+887
-87
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "grafana_cloud_access_policy_rotating_token Resource - terraform-provider-grafana"
4+
subcategory: "Cloud"
5+
description: |-
6+
Official documentation https://grafana.com/docs/grafana-cloud/security-and-account-management/authentication-and-permissions/access-policies/API documentation https://grafana.com/docs/grafana-cloud/developer-resources/api-reference/cloud-api/#create-a-token
7+
Required access policy scopes:
8+
accesspolicies:readaccesspolicies:writeaccesspolicies:delete
9+
This is similar to the grafana_cloud_access_policy_token resource, but it represents a token that will be rotated automatically over time.
10+
---
11+
12+
# grafana_cloud_access_policy_rotating_token (Resource)
13+
14+
* [Official documentation](https://grafana.com/docs/grafana-cloud/security-and-account-management/authentication-and-permissions/access-policies/)
15+
* [API documentation](https://grafana.com/docs/grafana-cloud/developer-resources/api-reference/cloud-api/#create-a-token)
16+
17+
Required access policy scopes:
18+
19+
* accesspolicies:read
20+
* accesspolicies:write
21+
* accesspolicies:delete
22+
23+
This is similar to the grafana_cloud_access_policy_token resource, but it represents a token that will be rotated automatically over time.
24+
25+
## Example Usage
26+
27+
```terraform
28+
data "grafana_cloud_organization" "current" {
29+
slug = "<your org slug>"
30+
}
31+
32+
resource "grafana_cloud_access_policy" "test" {
33+
region = "prod-us-east-0"
34+
name = "my-policy"
35+
display_name = "My Policy"
36+
37+
scopes = ["metrics:read", "logs:read"]
38+
39+
realm {
40+
type = "org"
41+
identifier = data.grafana_cloud_organization.current.id
42+
43+
label_policy {
44+
selector = "{namespace=\"default\"}"
45+
}
46+
}
47+
}
48+
49+
resource "grafana_cloud_access_policy_rotating_token" "test" {
50+
region = "prod-us-east-0"
51+
access_policy_id = grafana_cloud_access_policy.test.policy_id
52+
name_prefix = "my-policy-rotating-token"
53+
display_name = "My Policy Rotating Token"
54+
expire_after = "30d"
55+
early_rotation_window = "24h"
56+
}
57+
```
58+
59+
<!-- schema generated by tfplugindocs -->
60+
## Schema
61+
62+
### Required
63+
64+
- `access_policy_id` (String) ID of the access policy for which to create a token.
65+
- `early_rotation_window` (String) Duration of the window before expiring where the token can be rotated (e.g. '24h', '30m', '1h30m').
66+
- `expire_after` (String) Duration after which the token will expire (e.g. '24h', '30m', '1h30m').
67+
- `name_prefix` (String) Prefix for the name of the access policy token. The actual name will be stored in the computed field `name`, which will be in the format '<name_prefix>-<expiration_timestamp>'
68+
- `region` (String) Region of the access policy. Should be set to the same region as the access policy. Use the region list API to get the list of available regions: https://grafana.com/docs/grafana-cloud/developer-resources/api-reference/cloud-api/#list-regions.
69+
70+
### Optional
71+
72+
- `delete_on_destroy` (Boolean) Deletes the token in Grafana Cloud when the resource is destroyed in Terraform, instead of leaving it to expire at its `expires_at` time. Use it with `lifecycle { create_before_destroy = true }` to make sure that the new token is created before the old one is deleted. Defaults to `false`.
73+
- `display_name` (String) Display name of the access policy token. Defaults to the name.
74+
75+
### Read-Only
76+
77+
- `created_at` (String) Creation date of the access policy token.
78+
- `expires_at` (String) Expiration date of the access policy token.
79+
- `id` (String) The ID of this resource.
80+
- `name` (String) Name of the access policy token.
81+
- `ready_for_rotation` (Boolean) Signals that the token is either expired or within the period to be early rotated.
82+
- `token` (String, Sensitive)
83+
- `updated_at` (String) Last update date of the access policy token.
84+
85+
## Import
86+
87+
Import is supported using the following syntax:
88+
89+
```shell
90+
terraform import grafana_cloud_access_policy_rotating_token.name "{{ region }}:{{ tokenId }}"
91+
```
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
terraform import grafana_cloud_access_policy_rotating_token.name "{{ region }}:{{ tokenId }}"
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
data "grafana_cloud_organization" "current" {
2+
slug = "<your org slug>"
3+
}
4+
5+
resource "grafana_cloud_access_policy" "test" {
6+
region = "prod-us-east-0"
7+
name = "my-policy"
8+
display_name = "My Policy"
9+
10+
scopes = ["metrics:read", "logs:read"]
11+
12+
realm {
13+
type = "org"
14+
identifier = data.grafana_cloud_organization.current.id
15+
16+
label_policy {
17+
selector = "{namespace=\"default\"}"
18+
}
19+
}
20+
}
21+
22+
resource "grafana_cloud_access_policy_rotating_token" "test" {
23+
region = "prod-us-east-0"
24+
access_policy_id = grafana_cloud_access_policy.test.policy_id
25+
name_prefix = "my-policy-rotating-token"
26+
display_name = "My Policy Rotating Token"
27+
expire_after = "30d"
28+
early_rotation_window = "24h"
29+
}

internal/resources/cloud/catalog-resource.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,19 @@ spec:
2727
---
2828
apiVersion: backstage.io/v1alpha1
2929
kind: Component
30+
metadata:
31+
name: resource-grafana_cloud_access_policy_rotating_token
32+
title: grafana_cloud_access_policy_rotating_token (resource)
33+
description: |
34+
resource `grafana_cloud_access_policy_rotating_token` in Grafana Labs' Terraform Provider
35+
spec:
36+
subcomponentOf: component:default/terraform-provider-grafana
37+
type: terraform-resource
38+
owner: group:default/identity-squad
39+
lifecycle: production
40+
---
41+
apiVersion: backstage.io/v1alpha1
42+
kind: Component
3043
metadata:
3144
name: resource-grafana_cloud_org_member
3245
title: grafana_cloud_org_member (resource)

internal/resources/cloud/common.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ package cloud
33
import (
44
"context"
55
"fmt"
6+
"time"
67

78
"github.com/grafana/grafana-com-public-clients/go/gcom"
8-
"github.com/grafana/terraform-provider-grafana/v4/internal/common"
99
"github.com/hashicorp/go-uuid"
1010
"github.com/hashicorp/terraform-plugin-framework/datasource"
1111
"github.com/hashicorp/terraform-plugin-framework/resource"
1212
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1313
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
14+
15+
"github.com/grafana/terraform-provider-grafana/v4/internal/common"
1416
)
1517

1618
func ClientRequestID() string {
@@ -115,3 +117,11 @@ func (r *basePluginFrameworkResource) Configure(ctx context.Context, req resourc
115117

116118
r.client = client.GrafanaCloudAPI
117119
}
120+
121+
// Now returns the current time.
122+
// It can be overridden in tests to provide a different time.
123+
var Now = time.Now
124+
125+
type getter interface {
126+
GetOk(key string) (interface{}, bool)
127+
}

internal/resources/cloud/data_source_cloud_access_policies_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ package cloud_test
22

33
import (
44
"fmt"
5-
"time"
6-
75
"testing"
6+
"time"
87

98
"github.com/grafana/grafana-com-public-clients/go/gcom"
10-
"github.com/grafana/terraform-provider-grafana/v4/internal/common"
11-
"github.com/grafana/terraform-provider-grafana/v4/internal/testutils"
129
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
1310
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
1411
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
12+
13+
"github.com/grafana/terraform-provider-grafana/v4/internal/common"
14+
"github.com/grafana/terraform-provider-grafana/v4/internal/testutils"
1515
)
1616

1717
func TestDataSourceAccessPolicy_Basic(t *testing.T) {
@@ -30,7 +30,7 @@ func TestDataSourceAccessPolicy_Basic(t *testing.T) {
3030
"datadog:validate",
3131
}
3232

33-
accessPolicyConfig := testAccCloudAccessPolicyTokenConfigBasic(randomName, randomName+"display", "prod-us-east-0", scopes, expiresAt)
33+
accessPolicyConfig := testAccCloudAccessPolicyTokenConfigBasic(randomName, randomName+"display", "prod-us-east-0", scopes, expiresAt, false)
3434
setItemMatcher := func(s *terraform.State) error {
3535
return resource.TestCheckTypeSetElemNestedAttrs("data.grafana_cloud_access_policies.test", "access_policies.*", map[string]string{
3636
"id": *policy.Id,

0 commit comments

Comments
 (0)