Skip to content

Commit e163d34

Browse files
committed
Create new resource iamoauthclientcredential
1 parent f0f829e commit e163d34

File tree

6 files changed

+339
-0
lines changed

6 files changed

+339
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Copyright 2024 Google Inc.
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
14+
---
15+
name: OauthClientCredential
16+
description: |
17+
Represents an OAuth Client Credential. Used to authenticate an OAuth Client
18+
while accessing Google Cloud resources on behalf of a Workforce Identity Federation user
19+
by using OAuth 2.0 Protocol.
20+
references:
21+
guides:
22+
"Managing OAuth clients": "https://cloud.google.com/iam/docs/workforce-manage-oauth-app#manage-clients"
23+
api: "https://cloud.google.com/iam/docs/reference/rest/v1/projects.locations.oauthClients.credentials"
24+
base_url: projects/{{project}}/locations/{{location}}/oauthClients/{{oauthclient}}/credentials
25+
update_mask: true
26+
self_link: projects/{{project}}/locations/{{location}}/oauthClients/{{oauthclient}}/credentials/{{oauth_client_credential_id}}
27+
create_url: projects/{{project}}/locations/{{location}}/oauthClients/{{oauthclient}}/credentials?oauthClientCredentialId={{oauth_client_credential_id}}
28+
update_verb: PATCH
29+
id_format: projects/{{project}}/locations/{{location}}/oauthClients/{{oauthclient}}/credentials/{{oauth_client_credential_id}}
30+
import_format:
31+
- projects/{{project}}/locations/{{location}}/oauthClients/{{oauthclient}}/credentials/{{oauth_client_credential_id}}
32+
timeouts:
33+
insert_minutes: 20
34+
update_minutes: 20
35+
delete_minutes: 20
36+
custom_code:
37+
constants: "templates/terraform/constants/iam_oauth_client_credential.go.tmpl"
38+
decoder: "templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl"
39+
test_check_destroy: "templates/terraform/custom_check_destroy/iam_oauth_client_credential.go.tmpl"
40+
post_create: "templates/terraform/post_create/sleep.go.tmpl"
41+
post_update: "templates/terraform/post_create/sleep.go.tmpl"
42+
post_delete: "templates/terraform/post_create/sleep.go.tmpl"
43+
exclude_sweeper: true
44+
examples:
45+
- name: "iam_oauth_client_credential_basic"
46+
primary_resource_id: "example"
47+
vars:
48+
oauth_client_id: "example-client-id"
49+
oauth_client_credential_id: "cred-id"
50+
- name: "iam_oauth_client_credential_full"
51+
primary_resource_id: "example"
52+
vars:
53+
oauth_client_id: "example-client-id"
54+
oauth_client_credential_id: "cred-id"
55+
parameters:
56+
- name: location
57+
type: String
58+
description: Resource ID segment making up resource `name`. It identifies the resource within its parent collection as described in https://google.aip.dev/122.
59+
immutable: true
60+
url_param_only: true
61+
required: true
62+
- name: oauthclient
63+
type: String
64+
description: Resource ID segment making up resource `name`. It identifies the resource within its parent collection as described in https://google.aip.dev/122.
65+
immutable: true
66+
url_param_only: true
67+
required: true
68+
- name: oauthClientCredentialId
69+
type: String
70+
description: |-
71+
Required. The ID to use for the OauthClientCredential, which becomes the
72+
final component of the resource name. This value should be 4-32 characters,
73+
and may contain the characters [a-z0-9-]. The prefix `gcp-` is
74+
reserved for use by Google, and may not be specified.
75+
immutable: true
76+
url_param_only: true
77+
required: true
78+
properties:
79+
- name: disabled
80+
type: Boolean
81+
description: |-
82+
Optional. Whether the OauthClientCredential is disabled. You cannot use a
83+
disabled OauthClientCredential.
84+
- name: clientSecret
85+
type: String
86+
description: |-
87+
Output only. The system-generated OAuth client secret.
88+
89+
The client secret must be stored securely. If the client secret is
90+
leaked, you must delete and re-create the client credential. To learn
91+
more, see [OAuth client and credential security risks and
92+
mitigations](https://cloud.google.com/iam/docs/workforce-oauth-app#security)
93+
output: true
94+
- name: displayName
95+
type: String
96+
description: |-
97+
Optional. A user-specified display name of the OauthClientCredential.
98+
99+
Cannot exceed 32 characters.
100+
- name: name
101+
type: String
102+
description: |-
103+
Immutable. Identifier. The resource name of the OauthClientCredential.
104+
105+
Format:
106+
`projects/{project}/locations/{location}/oauthClients/{oauth_client}/credentials/{credential}`
107+
output: true
108+
immutable: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const oauthClientCredentialIdRegexp = `^[a-z0-9-]{4,32}$`
2+
3+
func ValidateOauthClientCredentialId(v interface{}, k string) (ws []string, errors []error) {
4+
value := v.(string)
5+
6+
if strings.HasPrefix(value, "gcp-") {
7+
errors = append(errors, fmt.Errorf(
8+
"%q (%q) can not start with \"gcp-\". " +
9+
"The prefix `gcp-` is reserved for use by Google, and may not be specified.", k, value))
10+
}
11+
12+
if !regexp.MustCompile(oauthClientCredentialIdRegexp).MatchString(value) {
13+
errors = append(errors, fmt.Errorf(
14+
"%q (%q) must be 4-32 characters, and may contain the characters [a-z0-9-].", k, value))
15+
}
16+
17+
return
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
config := acctest.GoogleProviderConfig(t)
2+
3+
url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{"{{"}}IAMWorkforcePoolBasePath{{"}}"}}projects/{{"{{"}}project{{"}}"}}/locations/global/oauthClients/{{"{{"}}oauth_client_id{{"}}"}}/credentials/{{"{{"}}oauth_client_credential_id{{"}}"}}")
4+
if err != nil {
5+
return err
6+
}
7+
8+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
9+
Config: config,
10+
Method: "GET",
11+
RawURL: url,
12+
UserAgent: config.UserAgent,
13+
})
14+
if err != nil {
15+
return nil
16+
}
17+
18+
if v := res["state"]; v == "DELETED" {
19+
return nil
20+
}
21+
22+
return fmt.Errorf("IAMOAuthClientCredential still exists at %s", url)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
resource "google_iam_oauth_client" "oauth_client" {
2+
oauth_client_id = "{{index $.Vars "oauth_client_id"}}"
3+
location = "global"
4+
allowed_grant_types = ["AUTHORIZATION_CODE_GRANT"]
5+
allowed_redirect_uris = ["https://www.example.com"]
6+
allowed_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
7+
client_type = "CONFIDENTIAL_CLIENT"
8+
}
9+
10+
resource "google_iam_oauth_client_credential" "{{$.PrimaryResourceId}}" {
11+
oauthclient = google_iam_oauth_client.oauth_client.oauth_client_id
12+
location = google_iam_oauth_client.oauth_client.location
13+
oauth_client_credential_id = "{{index $.Vars "oauth_client_credential_id"}}"
14+
disabled = true
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
resource "google_iam_oauth_client" "oauth_client" {
2+
oauth_client_id = "{{index $.Vars "oauth_client_id"}}"
3+
location = "global"
4+
allowed_grant_types = ["AUTHORIZATION_CODE_GRANT"]
5+
allowed_redirect_uris = ["https://www.example.com"]
6+
allowed_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
7+
client_type = "CONFIDENTIAL_CLIENT"
8+
}
9+
10+
resource "google_iam_oauth_client_credential" "{{$.PrimaryResourceId}}" {
11+
oauthclient = google_iam_oauth_client.oauth_client.oauth_client_id
12+
location = google_iam_oauth_client.oauth_client.location
13+
oauth_client_credential_id = "{{index $.Vars "oauth_client_credential_id"}}"
14+
disabled = true
15+
display_name = "Display Name of credential"
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package iamworkforcepool_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
7+
8+
"github.com/hashicorp/terraform-provider-google/google/acctest"
9+
)
10+
11+
func TestAccIAMWorkforcePoolOauthClientCredential_basic(t *testing.T) {
12+
t.Parallel()
13+
14+
context := map[string]interface{}{
15+
"random_suffix": acctest.RandString(t, 10),
16+
}
17+
18+
acctest.VcrTest(t, resource.TestCase{
19+
PreCheck: func() { acctest.AccTestPreCheck(t) },
20+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
21+
CheckDestroy: testAccCheckIAMWorkforcePoolOauthClientCredentialDestroyProducer(t),
22+
Steps: []resource.TestStep{
23+
{
24+
Config: testAccIAMWorkforcePoolOauthClientCredential_basic(context),
25+
},
26+
{
27+
ResourceName: "google_iam_oauth_client_credential.example",
28+
ImportState: true,
29+
ImportStateVerify: true,
30+
ImportStateVerifyIgnore: []string{"location", "oauth_client_credential_id", "oauthclient"},
31+
},
32+
{
33+
Config: testAccIAMWorkforcePoolOauthClientCredential_basic_update(context),
34+
},
35+
{
36+
ResourceName: "google_iam_oauth_client_credential.example",
37+
ImportState: true,
38+
ImportStateVerify: true,
39+
ImportStateVerifyIgnore: []string{"location", "oauth_client_credential_id", "oauthclient"},
40+
},
41+
},
42+
})
43+
}
44+
45+
func testAccIAMWorkforcePoolOauthClientCredential_basic(context map[string]interface{}) string {
46+
return acctest.Nprintf(`
47+
resource "google_iam_oauth_client" "oauth_client" {
48+
oauth_client_id = "tf-test-example-client-id%{random_suffix}"
49+
location = "global"
50+
allowed_grant_types = ["AUTHORIZATION_CODE_GRANT"]
51+
allowed_redirect_uris = ["https://www.example.com"]
52+
allowed_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
53+
client_type = "CONFIDENTIAL_CLIENT"
54+
}
55+
56+
resource "google_iam_oauth_client_credential" "example" {
57+
oauthclient = google_iam_oauth_client.oauth_client.oauth_client_id
58+
location = google_iam_oauth_client.oauth_client.location
59+
oauth_client_credential_id = "tf-test-cred-id%{random_suffix}"
60+
disabled = true
61+
}
62+
`, context)
63+
}
64+
65+
func testAccIAMWorkforcePoolOauthClientCredential_basic_update(context map[string]interface{}) string {
66+
return acctest.Nprintf(`
67+
resource "google_iam_oauth_client" "oauth_client" {
68+
oauth_client_id = "tf-test-example-client-id%{random_suffix}"
69+
location = "global"
70+
allowed_grant_types = ["AUTHORIZATION_CODE_GRANT"]
71+
allowed_redirect_uris = ["https://www.example.com"]
72+
allowed_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
73+
client_type = "CONFIDENTIAL_CLIENT"
74+
}
75+
76+
resource "google_iam_oauth_client_credential" "example" {
77+
oauthclient = google_iam_oauth_client.oauth_client.oauth_client_id
78+
location = google_iam_oauth_client.oauth_client.location
79+
oauth_client_credential_id = "tf-test-cred-id%{random_suffix}"
80+
disabled = true
81+
}
82+
`, context)
83+
}
84+
85+
86+
func TestAccIAMWorkforcePoolOauthClientCredential_full(t *testing.T) {
87+
t.Parallel()
88+
89+
context := map[string]interface{}{
90+
"random_suffix": acctest.RandString(t, 10),
91+
}
92+
93+
acctest.VcrTest(t, resource.TestCase{
94+
PreCheck: func() { acctest.AccTestPreCheck(t) },
95+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
96+
CheckDestroy: testAccCheckIAMWorkforcePoolOauthClientCredentialDestroyProducer(t),
97+
Steps: []resource.TestStep{
98+
{
99+
Config: testAccIAMWorkforcePoolOauthClientCredential_full(context),
100+
},
101+
{
102+
ResourceName: "google_iam_oauth_client_credential.example",
103+
ImportState: true,
104+
ImportStateVerify: true,
105+
ImportStateVerifyIgnore: []string{"location", "oauth_client_credential_id", "oauthclient"},
106+
},
107+
{
108+
Config: testAccIAMWorkforcePoolOauthClientCredential_full_update(context),
109+
},
110+
{
111+
ResourceName: "google_iam_oauth_client_credential.example",
112+
ImportState: true,
113+
ImportStateVerify: true,
114+
ImportStateVerifyIgnore: []string{"location", "oauth_client_credential_id", "oauthclient"},
115+
},
116+
},
117+
})
118+
}
119+
120+
func testAccIAMWorkforcePoolOauthClientCredential_full(context map[string]interface{}) string {
121+
return acctest.Nprintf(`
122+
resource "google_iam_oauth_client" "oauth_client" {
123+
oauth_client_id = "tf-test-example-client-id%{random_suffix}"
124+
location = "global"
125+
allowed_grant_types = ["AUTHORIZATION_CODE_GRANT"]
126+
allowed_redirect_uris = ["https://www.example.com"]
127+
allowed_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
128+
client_type = "CONFIDENTIAL_CLIENT"
129+
}
130+
131+
resource "google_iam_oauth_client_credential" "example" {
132+
oauthclient = google_iam_oauth_client.oauth_client.oauth_client_id
133+
location = google_iam_oauth_client.oauth_client.location
134+
oauth_client_credential_id = "tf-test-cred-id%{random_suffix}"
135+
disabled = true
136+
display_name = "Display Name of credential"
137+
}
138+
`, context)
139+
}
140+
141+
func testAccIAMWorkforcePoolOauthClientCredential_full_update(context map[string]interface{}) string {
142+
return acctest.Nprintf(`
143+
resource "google_iam_oauth_client" "oauth_client" {
144+
oauth_client_id = "tf-test-example-client-id%{random_suffix}"
145+
location = "global"
146+
allowed_grant_types = ["AUTHORIZATION_CODE_GRANT"]
147+
allowed_redirect_uris = ["https://www.example.com"]
148+
allowed_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
149+
client_type = "CONFIDENTIAL_CLIENT"
150+
}
151+
152+
resource "google_iam_oauth_client_credential" "example" {
153+
oauthclient = google_iam_oauth_client.oauth_client.oauth_client_id
154+
location = google_iam_oauth_client.oauth_client.location
155+
oauth_client_credential_id = "tf-test-cred-id%{random_suffix}"
156+
disabled = true
157+
display_name = "Updated displayName"
158+
}
159+
`, context)
160+
}

0 commit comments

Comments
 (0)