Skip to content

Commit 82062e5

Browse files
committed
VAULT-37308: Update resource_iam_policy to use resource_name, instead of resource_uri.
1 parent 9a3318a commit 82062e5

7 files changed

Lines changed: 61 additions & 142 deletions

File tree

.github/workflows/_testacc_vaultradar.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ jobs:
7878
# RADAR_GITHUB_ENTERPRISE_DOMAIN: ${{ secrets.RADAR_GITHUB_ENTERPRISE_DOMAIN }}
7979
# RADAR_GITHUB_ENTERPRISE_TOKEN: ${{ secrets.RADAR_GITHUB_ENTERPRISE_TOKEN }}
8080
# RADAR_GITHUB_ENTERPRISE_TOKEN_2: ${{ secrets.RADAR_GITHUB_ENTERPRISE_TOKEN_2 }}
81-
# RADAR_RESOURCE_URI ${{ secrets.RADAR_RESOURCE_URI }}
81+
# RADAR_HCP_RESOURCE_NAME ${{ secrets.RADAR_HCP_RESOURCE_NAME }}
8282
run: |
8383
go test \
8484
./internal/provider/vaultradar \

docs/resources/vault_radar_resource_iam_binding.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ data "hcp_group" "group" {
3131
# Note: `roles/vault-radar.resource-viewer` and `roles/vault-radar.resource-contributor` are the only roles
3232
# that can be applied to a policy and/or binding for Vault Radar resources.
3333
resource "hcp_vault_radar_resource_iam_binding" "binding" {
34-
resource_uri = "git://github.com/foo/bar.git"
35-
principal_id = data.hcp_group.group.resource_id
36-
role = "roles/vault-radar.resource-viewer"
34+
resource_name = "vault-radar/project/<project_id>/scan-target/<scan_target_id>"
35+
principal_id = data.hcp_group.group.resource_id
36+
role = "roles/vault-radar.resource-viewer"
3737
}
3838
```
3939

@@ -44,5 +44,5 @@ resource "hcp_vault_radar_resource_iam_binding" "binding" {
4444
### Required
4545

4646
- `principal_id` (String) The principal to bind to the given role.
47-
- `resource_uri` (String) The project's Radar resource URI.
47+
- `resource_name` (String) The HCP resource name associated with the Radar resource. This is the name of the resource in the format `vault-radar/project/<project_id>/scan-target/<scan_target_id>`.
4848
- `role` (String) The role name to bind to the given principal.

docs/resources/vault_radar_resource_iam_policy.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ data "hcp_iam_policy" "policy" {
3838
}
3939
4040
resource "hcp_vault_radar_resource_iam_policy" "policy" {
41-
resource_uri = "git://github.com/foo/bar.git"
42-
policy_data = data.hcp_iam_policy.policy.policy_data
41+
resource_name = "vault-radar/project/<project_id>/scan-target/<scan_target_id>"
42+
policy_data = data.hcp_iam_policy.policy.policy_data
4343
}
4444
```
4545

@@ -50,7 +50,7 @@ resource "hcp_vault_radar_resource_iam_policy" "policy" {
5050
### Required
5151

5252
- `policy_data` (String) The policy to apply.
53-
- `resource_uri` (String) The project's Radar resource URI.
53+
- `resource_name` (String) The HCP resource name associated with the Radar resource. This is the name of the resource in the format `vault-radar/project/<project_id>/scan-target/<scan_target_id>`.
5454

5555
### Read-Only
5656

examples/resources/hcp_vault_radar_resource_iam_binding/resource.tf

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ data "hcp_group" "group" {
99
# Note: `roles/vault-radar.resource-viewer` and `roles/vault-radar.resource-contributor` are the only roles
1010
# that can be applied to a policy and/or binding for Vault Radar resources.
1111
resource "hcp_vault_radar_resource_iam_binding" "binding" {
12-
resource_uri = "git://github.com/foo/bar.git"
13-
principal_id = data.hcp_group.group.resource_id
14-
role = "roles/vault-radar.resource-viewer"
12+
resource_name = "vault-radar/project/<project_id>/scan-target/<scan_target_id>"
13+
principal_id = data.hcp_group.group.resource_id
14+
role = "roles/vault-radar.resource-viewer"
1515
}

examples/resources/hcp_vault_radar_resource_iam_policy/resource.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ data "hcp_iam_policy" "policy" {
1616
}
1717

1818
resource "hcp_vault_radar_resource_iam_policy" "policy" {
19-
resource_uri = "git://github.com/foo/bar.git"
20-
policy_data = data.hcp_iam_policy.policy.policy_data
19+
resource_name = "vault-radar/project/<project_id>/scan-target/<scan_target_id>"
20+
policy_data = data.hcp_iam_policy.policy.policy_data
2121
}

internal/provider/vaultradar/resource_radar_resource_iam_policy.go

Lines changed: 26 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ package vaultradar
55

66
import (
77
"context"
8-
"errors"
98
"fmt"
9+
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
10+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
1011
"maps"
1112
"net/http"
13+
"regexp"
1214
"slices"
1315
"strings"
1416

1517
"github.com/hashicorp/hcp-sdk-go/clients/cloud-resource-manager/stable/2019-12-10/client/resource_service"
1618
"github.com/hashicorp/hcp-sdk-go/clients/cloud-resource-manager/stable/2019-12-10/models"
17-
rrs "github.com/hashicorp/hcp-sdk-go/clients/cloud-vault-radar/preview/2023-05-01/client/resource_service"
18-
rrm "github.com/hashicorp/hcp-sdk-go/clients/cloud-vault-radar/preview/2023-05-01/models"
1919
"github.com/hashicorp/terraform-plugin-framework/diag"
2020
"github.com/hashicorp/terraform-plugin-framework/path"
2121
"github.com/hashicorp/terraform-plugin-framework/resource"
@@ -36,15 +36,25 @@ func radarResourceIAMSchema(binding bool) schema.Schema {
3636
d = "Updates the Vault Radar Resource IAM policy to bind a role to a new principal. Existing bindings are preserved."
3737
}
3838

39+
// Defined in: https://github.com/CyberAP/nanoid-dictionary#nolookalikessafe
40+
nanoidNolookalikesSafeAlphabet := "6789BCDFGHJKLMNPQRTWbcdfghjkmnpqrtwz"
41+
nanoidLength := 20
42+
resourceNameRegex := fmt.Sprintf(`^vault-radar/project/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/scan-target/[%s]{%d}$`, nanoidNolookalikesSafeAlphabet, nanoidLength)
43+
3944
return schema.Schema{
4045
MarkdownDescription: d,
4146
Attributes: map[string]schema.Attribute{
42-
"resource_uri": schema.StringAttribute{
47+
"resource_name": schema.StringAttribute{
4348
Required: true,
44-
Description: "The project's Radar resource URI.",
49+
Description: "The HCP resource name associated with the Radar resource. This is the name of the resource in the format `vault-radar/project/<project_id>/scan-target/<scan_target_id>`.",
4550
PlanModifiers: []planmodifier.String{
4651
stringplanmodifier.RequiresReplace(),
4752
},
53+
Validators: []validator.String{
54+
stringvalidator.RegexMatches(regexp.MustCompile(resourceNameRegex),
55+
"must match the format: "+resourceNameRegex,
56+
),
57+
},
4858
},
4959
},
5060
}
@@ -59,40 +69,35 @@ func NewRadarResourceIAMBindingResource() resource.Resource {
5969
}
6070

6171
type radarResourceIAMPolicyUpdater struct {
62-
resourceURI string
63-
client *clients.Client
64-
d iampolicy.TerraformResourceData
72+
resourceName string
73+
client *clients.Client
74+
d iampolicy.TerraformResourceData
6575
}
6676

6777
func newRadarResourceIAMPolicyUpdater(
6878
ctx context.Context,
6979
d iampolicy.TerraformResourceData,
7080
clients *clients.Client) (iampolicy.ResourceIamUpdater, diag.Diagnostics) {
7181

72-
var resourceURI types.String
73-
diags := d.GetAttribute(ctx, path.Root("resource_uri"), &resourceURI)
82+
var resourceName types.String
83+
diags := d.GetAttribute(ctx, path.Root("resource_name"), &resourceName)
7484

7585
return &radarResourceIAMPolicyUpdater{
76-
resourceURI: resourceURI.ValueString(),
77-
client: clients,
78-
d: d,
86+
resourceName: resourceName.ValueString(),
87+
client: clients,
88+
d: d,
7989
}, diags
8090
}
8191

8292
func (u *radarResourceIAMPolicyUpdater) GetMutexKey() string {
83-
return u.resourceURI
93+
return u.resourceName
8494
}
8595

8696
// GetResourceIamPolicy Fetch the existing IAM policy attached to a resource.
8797
func (u *radarResourceIAMPolicyUpdater) GetResourceIamPolicy(ctx context.Context) (*models.HashicorpCloudResourcemanagerPolicy, diag.Diagnostics) {
88-
rr, lookupDiags := lookupRadarResourceByURI(ctx, u.client, u.resourceURI)
89-
if lookupDiags.HasError() {
90-
return nil, lookupDiags
91-
}
92-
9398
var diags diag.Diagnostics
9499
params := resource_service.NewResourceServiceGetIamPolicyParams()
95-
params.ResourceName = &rr.HcpResourceName
100+
params.ResourceName = &u.resourceName
96101

97102
res, err := u.client.ResourceService.ResourceServiceGetIamPolicy(params, nil)
98103
if err != nil {
@@ -131,16 +136,11 @@ func (u *radarResourceIAMPolicyUpdater) SetResourceIamPolicy(ctx context.Context
131136
return nil, diags
132137
}
133138

134-
rr, diags := lookupRadarResourceByURI(ctx, u.client, u.resourceURI)
135-
if diags.HasError() {
136-
return nil, diags
137-
}
138-
139139
params := resource_service.NewResourceServiceSetIamPolicyParams()
140140

141141
params.Body = &models.HashicorpCloudResourcemanagerResourceSetIamPolicyRequest{
142142
Policy: policy,
143-
ResourceName: rr.HcpResourceName,
143+
ResourceName: u.resourceName,
144144
}
145145

146146
res, err := u.client.ResourceService.ResourceServiceSetIamPolicy(params, nil)
@@ -161,84 +161,3 @@ var (
161161
_ iampolicy.NewResourceIamUpdaterFunc = newRadarResourceIAMPolicyUpdater
162162
_ iampolicy.ResourceIamUpdater = &radarResourceIAMPolicyUpdater{}
163163
)
164-
165-
func lookupRadarResourceByURI(ctx context.Context, client *clients.Client, resourceURI string) (*rrm.VaultRadar20230501Resource, diag.Diagnostics) {
166-
projectID := client.Config.ProjectID
167-
168-
// Filter to find the exact radar resources by URI.
169-
filters := []*rrm.VaultRadar20230501Filter{
170-
{
171-
ID: "uri",
172-
Op: rrm.NewFilterFilterOperation(rrm.FilterFilterOperationEQ),
173-
Value: []*rrm.VaultRadar20230501FilterValue{{StringValue: resourceURI}},
174-
ExactMatch: true,
175-
},
176-
{
177-
ID: "state",
178-
Op: rrm.NewFilterFilterOperation(rrm.FilterFilterOperationNEQNULLAWARE),
179-
Value: []*rrm.VaultRadar20230501FilterValue{{StringValue: "deleted"}},
180-
ExactMatch: true,
181-
},
182-
}
183-
184-
body := rrs.ListResourcesBody{
185-
Location: &rrs.ListResourcesParamsBodyLocation{
186-
OrganizationID: client.Config.OrganizationID,
187-
},
188-
Search: &rrm.VaultRadar20230501SearchSchema{
189-
Limit: 1, // we expect either 0 or 1
190-
Page: 1,
191-
Filters: filters,
192-
},
193-
}
194-
195-
var diags diag.Diagnostics
196-
resp, err := clients.ListRadarResources(ctx, client, projectID, body)
197-
if err != nil {
198-
var srvErr *rrs.ListResourcesDefault
199-
ok := errors.As(err, &srvErr)
200-
if !ok {
201-
diags.AddError("unexpected error while reading response from service.", err.Error())
202-
return nil, diags
203-
}
204-
205-
diags.Append(customdiags.NewErrorHTTPStatusCode("failed to retrieve radar resource", err.Error(), srvErr.Code()))
206-
return nil, diags
207-
}
208-
209-
resources := resp.GetPayload().Resources
210-
if len(resources) == 0 {
211-
diags.AddError("unable to find radar resource", "no radar resource could be found with the uri: "+resourceURI)
212-
return nil, diags
213-
}
214-
215-
resource := resources[0]
216-
diags.Append(validateResource(resource, projectID)...)
217-
218-
return resources[0], diags
219-
}
220-
221-
func validateResource(resource *rrm.VaultRadar20230501Resource, projectID string) diag.Diagnostics {
222-
var diags diag.Diagnostics
223-
224-
if projectID == "" {
225-
diags.AddError("hcp project_id unknown", "the project_id where Vault Radar is located must be specified in the hcp provider config.")
226-
return diags
227-
}
228-
229-
if resource.HcpResourceStatus != "registered" {
230-
diags.AddError("invalid radar resource status", "policy cannot be applied to a resource with status: "+resource.HcpResourceStatus)
231-
}
232-
233-
if resource.State != "created" {
234-
diags.AddError("invalid radar resource state", "policy cannot be applied to a resource with state: "+resource.State)
235-
}
236-
237-
// This should never happen, but we check it just in case.
238-
prefix := "vault-radar/project/" + projectID + "/scan-target/"
239-
if !strings.HasPrefix(resource.HcpResourceName, prefix) {
240-
diags.AddError("invalid radar resource name", "got resource name: "+resource.HcpResourceName+", expected it to start with: "+prefix)
241-
}
242-
243-
return diags
244-
}

0 commit comments

Comments
 (0)