Skip to content

Commit 48e4304

Browse files
abheda-crestabd-goog
authored andcommitted
Add support for regional secret version datasource google_secret_manager_regional_secret_version (GoogleCloudPlatform#11730)
1 parent c460675 commit 48e4304

6 files changed

+653
-190
lines changed

mmv1/products/secretmanagerregional/RegionalSecret.yaml

+10-11
Original file line numberDiff line numberDiff line change
@@ -137,19 +137,18 @@ properties:
137137
138138
An object containing a list of "key": value pairs. Example:
139139
{ "name": "wrench", "mass": "1.3kg", "count": "3" }.
140-
# TODO : Add versionAliases field support once google_secret_manager_regional_secret_version is added
141-
# - !ruby/object:Api::Type::KeyValuePairs
142-
# name: versionAliases
143-
# description: |
144-
# Mapping from version alias to version name.
140+
- !ruby/object:Api::Type::KeyValuePairs
141+
name: versionAliases
142+
description: |
143+
Mapping from version alias to version name.
145144
146-
# A version alias is a string with a maximum length of 63 characters and can contain
147-
# uppercase and lowercase letters, numerals, and the hyphen (-) and underscore ('_')
148-
# characters. An alias string must start with a letter and cannot be the string
149-
# 'latest' or 'NEW'. No more than 50 aliases can be assigned to a given secret.
145+
A version alias is a string with a maximum length of 63 characters and can contain
146+
uppercase and lowercase letters, numerals, and the hyphen (-) and underscore ('_')
147+
characters. An alias string must start with a letter and cannot be the string
148+
'latest' or 'NEW'. No more than 50 aliases can be assigned to a given secret.
150149
151-
# An object containing a list of "key": value pairs. Example:
152-
# { "name": "wrench", "mass": "1.3kg", "count": "3" }.
150+
An object containing a list of "key": value pairs. Example:
151+
{ "name": "wrench", "mass": "1.3kg", "count": "3" }.
153152
- !ruby/object:Api::Type::NestedObject
154153
name: customerManagedEncryption
155154
description: |

mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb

+1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ var handwrittenDatasources = map[string]*schema.Resource{
180180
"google_runtimeconfig_config": runtimeconfig.DataSourceGoogleRuntimeconfigConfig(),
181181
"google_runtimeconfig_variable": runtimeconfig.DataSourceGoogleRuntimeconfigVariable(),
182182
<% end -%>
183+
"google_secret_manager_regional_secret_version": secretmanagerregional.DataSourceSecretManagerRegionalRegionalSecretVersion(),
183184
"google_secret_manager_regional_secret": secretmanagerregional.DataSourceSecretManagerRegionalRegionalSecret(),
184185
"google_secret_manager_secret": secretmanager.DataSourceSecretManagerSecret(),
185186
"google_secret_manager_secrets": secretmanager.DataSourceSecretManagerSecrets(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
package secretmanagerregional
2+
3+
import (
4+
"encoding/base64"
5+
"fmt"
6+
"log"
7+
"regexp"
8+
9+
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
10+
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
11+
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
13+
)
14+
15+
func DataSourceSecretManagerRegionalRegionalSecretVersion() *schema.Resource {
16+
return &schema.Resource{
17+
Read: dataSourceSecretManagerRegionalRegionalSecretVersionRead,
18+
Schema: map[string]*schema.Schema{
19+
"project": {
20+
Type: schema.TypeString,
21+
Optional: true,
22+
Computed: true,
23+
},
24+
"location": {
25+
Type: schema.TypeString,
26+
Optional: true,
27+
Computed: true,
28+
},
29+
"secret": {
30+
Type: schema.TypeString,
31+
Required: true,
32+
DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName,
33+
},
34+
"version": {
35+
Type: schema.TypeString,
36+
Optional: true,
37+
Computed: true,
38+
},
39+
"create_time": {
40+
Type: schema.TypeString,
41+
Computed: true,
42+
},
43+
"destroy_time": {
44+
Type: schema.TypeString,
45+
Computed: true,
46+
},
47+
"name": {
48+
Type: schema.TypeString,
49+
Computed: true,
50+
},
51+
"enabled": {
52+
Type: schema.TypeBool,
53+
Computed: true,
54+
},
55+
"secret_data": {
56+
Type: schema.TypeString,
57+
Computed: true,
58+
Sensitive: true,
59+
},
60+
"customer_managed_encryption": {
61+
Type: schema.TypeList,
62+
Computed: true,
63+
Elem: &schema.Resource{
64+
Schema: map[string]*schema.Schema{
65+
"kms_key_version_name": {
66+
Type: schema.TypeString,
67+
Computed: true,
68+
},
69+
},
70+
},
71+
},
72+
},
73+
}
74+
}
75+
76+
func dataSourceSecretManagerRegionalRegionalSecretVersionRead(d *schema.ResourceData, meta interface{}) error {
77+
config := meta.(*transport_tpg.Config)
78+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
79+
if err != nil {
80+
return err
81+
}
82+
83+
secretRegex := regexp.MustCompile("projects/(.+)/locations/(.+)/secrets/(.+)$")
84+
parts := secretRegex.FindStringSubmatch(d.Get("secret").(string))
85+
86+
var project string
87+
88+
// if reference of the secret is provided in the secret field
89+
if len(parts) == 4 {
90+
// Store values of project to set in state
91+
project = parts[1]
92+
if d.Get("project").(string) != "" && d.Get("project").(string) != parts[1] {
93+
return fmt.Errorf("The project set on this secret version (%s) is not equal to the project where this secret exists (%s).", d.Get("project").(string), parts[1])
94+
}
95+
if d.Get("location").(string) != "" && d.Get("location").(string) != parts[2] {
96+
return fmt.Errorf("The location set on this secret version (%s) is not equal to the location where this secret exists (%s).", d.Get("location").(string), parts[2])
97+
}
98+
if err := d.Set("location", parts[2]); err != nil {
99+
return fmt.Errorf("Error setting location: %s", err)
100+
}
101+
if err := d.Set("secret", parts[3]); err != nil {
102+
return fmt.Errorf("Error setting secret: %s", err)
103+
}
104+
} else { // if secret name is provided in the secret field
105+
// Store values of project to set in state
106+
project, err = tpgresource.GetProject(d, config)
107+
if err != nil {
108+
return fmt.Errorf("Error fetching project for Secret: %s", err)
109+
}
110+
if d.Get("location").(string) == "" {
111+
return fmt.Errorf("Location must be set when providing only secret name")
112+
}
113+
}
114+
if err := d.Set("project", project); err != nil {
115+
return fmt.Errorf("Error setting project: %s", err)
116+
}
117+
118+
var url string
119+
versionNum := d.Get("version")
120+
121+
// set version if provided, else set version to latest
122+
if versionNum != "" {
123+
url, err = tpgresource.ReplaceVars(d, config, "{{SecretManagerRegionalBasePath}}projects/{{project}}/locations/{{location}}/secrets/{{secret}}/versions/{{version}}")
124+
if err != nil {
125+
return err
126+
}
127+
} else {
128+
url, err = tpgresource.ReplaceVars(d, config, "{{SecretManagerRegionalBasePath}}projects/{{project}}/locations/{{location}}/secrets/{{secret}}/versions/latest")
129+
if err != nil {
130+
return err
131+
}
132+
}
133+
134+
var secretVersion map[string]interface{}
135+
secretVersion, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
136+
Config: config,
137+
Method: "GET",
138+
Project: project,
139+
RawURL: url,
140+
UserAgent: userAgent,
141+
})
142+
143+
if err != nil {
144+
return fmt.Errorf("Error retrieving available secret manager regional secret versions: %s", err.Error())
145+
}
146+
147+
secretVersionRegex := regexp.MustCompile("projects/(.+)/locations/(.+)/secrets/(.+)/versions/(.+)$")
148+
parts = secretVersionRegex.FindStringSubmatch(secretVersion["name"].(string))
149+
150+
if len(parts) != 5 {
151+
return fmt.Errorf("secret name, %s, does not match format, projects/{{project}}/locations/{{location}}/secrets/{{secret}}/versions/{{version}}", secretVersion["name"].(string))
152+
}
153+
154+
log.Printf("[DEBUG] Received Google Secret Manager Regional Secret Version: %q", secretVersion)
155+
156+
if err := d.Set("version", parts[4]); err != nil {
157+
return fmt.Errorf("Error setting version: %s", err)
158+
}
159+
160+
url = fmt.Sprintf("%s:access", url)
161+
resp, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
162+
Config: config,
163+
Method: "GET",
164+
Project: project,
165+
RawURL: url,
166+
UserAgent: userAgent,
167+
})
168+
169+
if err != nil {
170+
return fmt.Errorf("Error retrieving available secret manager regional secret version access: %s", err.Error())
171+
}
172+
173+
if err := d.Set("customer_managed_encryption", flattenSecretManagerRegionalRegionalSecretVersionCustomerManagedEncryption(secretVersion["customerManagedEncryption"], d, config)); err != nil {
174+
return fmt.Errorf("Error setting customer_managed_encryption: %s", err)
175+
}
176+
177+
if err := d.Set("create_time", secretVersion["createTime"].(string)); err != nil {
178+
return fmt.Errorf("Error setting create_time: %s", err)
179+
}
180+
181+
if secretVersion["destroyTime"] != nil {
182+
if err := d.Set("destroy_time", secretVersion["destroyTime"].(string)); err != nil {
183+
return fmt.Errorf("Error setting destroy_time: %s", err)
184+
}
185+
}
186+
187+
if err := d.Set("name", secretVersion["name"].(string)); err != nil {
188+
return fmt.Errorf("Error setting name: %s", err)
189+
}
190+
191+
if err := d.Set("enabled", true); err != nil {
192+
return fmt.Errorf("Error setting enabled: %s", err)
193+
}
194+
195+
data := resp["payload"].(map[string]interface{})
196+
secretData, err := base64.StdEncoding.DecodeString(data["data"].(string))
197+
if err != nil {
198+
return fmt.Errorf("Error decoding secret manager regional secret version data: %s", err.Error())
199+
}
200+
201+
if err := d.Set("secret_data", string(secretData)); err != nil {
202+
return fmt.Errorf("Error setting secret_data: %s", err)
203+
}
204+
205+
d.SetId(secretVersion["name"].(string))
206+
return nil
207+
}

0 commit comments

Comments
 (0)