Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new resource IAM OAuth Client Credential for Workforce Identity Federation #13231

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion mmv1/products/iamworkforcepool/OauthClient.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ timeouts:
update_minutes: 20
delete_minutes: 20
custom_code:
constants: "templates/terraform/constants/iam_oauth_client.go.tmpl"
decoder: "templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl"
test_check_destroy: "templates/terraform/custom_check_destroy/iam_oauth_client.go.tmpl"
post_create: "templates/terraform/post_create/sleep.go.tmpl"
Expand Down
107 changes: 107 additions & 0 deletions mmv1/products/iamworkforcepool/OauthClientCredential.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Copyright 2024 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

---
name: OauthClientCredential
description: |
Represents an OAuth Client Credential. Used to authenticate an OAuth Client
while accessing Google Cloud resources on behalf of a Workforce Identity Federation user
by using OAuth 2.0 Protocol.
references:
guides:
"Managing OAuth clients": "https://cloud.google.com/iam/docs/workforce-manage-oauth-app#manage-clients"
api: "https://cloud.google.com/iam/docs/reference/rest/v1/projects.locations.oauthClients.credentials"
base_url: projects/{{project}}/locations/{{location}}/oauthClients/{{oauthclient}}/credentials
update_mask: true
self_link: projects/{{project}}/locations/{{location}}/oauthClients/{{oauthclient}}/credentials/{{oauth_client_credential_id}}
create_url: projects/{{project}}/locations/{{location}}/oauthClients/{{oauthclient}}/credentials?oauthClientCredentialId={{oauth_client_credential_id}}
update_verb: PATCH
id_format: projects/{{project}}/locations/{{location}}/oauthClients/{{oauthclient}}/credentials/{{oauth_client_credential_id}}
import_format:
- projects/{{project}}/locations/{{location}}/oauthClients/{{oauthclient}}/credentials/{{oauth_client_credential_id}}
timeouts:
insert_minutes: 20
update_minutes: 20
delete_minutes: 20
custom_code:
decoder: "templates/terraform/decoders/treat_deleted_state_as_gone.go.tmpl"
test_check_destroy: "templates/terraform/custom_check_destroy/iam_oauth_client_credential.go.tmpl"
post_create: "templates/terraform/post_create/sleep.go.tmpl"
post_update: "templates/terraform/post_create/sleep.go.tmpl"
post_delete: "templates/terraform/post_create/sleep.go.tmpl"
exclude_sweeper: true
examples:
- name: "iam_oauth_client_credential_basic"
primary_resource_id: "example"
vars:
oauth_client_id: "example-client-id"
oauth_client_credential_id: "cred-id"
- name: "iam_oauth_client_credential_full"
primary_resource_id: "example"
vars:
oauth_client_id: "example-client-id"
oauth_client_credential_id: "cred-id"
parameters:
- name: location
type: String
description: Resource ID segment making up resource `name`. It identifies the resource within its parent collection as described in https://google.aip.dev/122.
immutable: true
url_param_only: true
required: true
- name: oauthclient
type: String
description: Resource ID segment making up resource `name`. It identifies the resource within its parent collection as described in https://google.aip.dev/122.
immutable: true
url_param_only: true
required: true
- name: oauthClientCredentialId
type: String
description: |-
Required. The ID to use for the OauthClientCredential, which becomes the
final component of the resource name. This value should be 4-32 characters,
and may contain the characters [a-z0-9-]. The prefix `gcp-` is
reserved for use by Google, and may not be specified.
immutable: true
url_param_only: true
required: true
properties:
- name: disabled
type: Boolean
description: |-
Optional. Whether the OauthClientCredential is disabled. You cannot use a
disabled OauthClientCredential.
- name: clientSecret
type: String
description: |-
Output only. The system-generated OAuth client secret.

The client secret must be stored securely. If the client secret is
leaked, you must delete and re-create the client credential. To learn
more, see [OAuth client and credential security risks and
mitigations](https://cloud.google.com/iam/docs/workforce-oauth-app#security)
output: true
- name: displayName
type: String
description: |-
Optional. A user-specified display name of the OauthClientCredential.

Cannot exceed 32 characters.
- name: name
type: String
description: |-
Immutable. Identifier. The resource name of the OauthClientCredential.

Format:
`projects/{project}/locations/{location}/oauthClients/{oauth_client}/credentials/{credential}`
output: true
immutable: true
20 changes: 0 additions & 20 deletions mmv1/templates/terraform/constants/iam_oauth_client.go.tmpl

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
config := acctest.GoogleProviderConfig(t)

url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{"{{"}}IAMWorkforcePoolBasePath{{"}}"}}projects/{{"{{"}}project{{"}}"}}/locations/global/oauthClients/{{"{{"}}oauth_client_id{{"}}"}}")
url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{"{{"}}IAMWorkforcePoolBasePath{{"}}"}}projects/{{"{{"}}project{{"}}"}}/locations/{{"{{"}}location{{"}}"}}/oauthClients/{{"{{"}}oauth_client_id{{"}}"}}")
if err != nil {
return err
}
Expand All @@ -19,4 +19,4 @@ if v := res["state"]; v == "DELETED" {
return nil
}

return fmt.Errorf("IAMOAuthCLient still exists at %s", url)
return fmt.Errorf("IAMOAuthClient still exists at %s", url)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
config := acctest.GoogleProviderConfig(t)

url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{"{{"}}IAMWorkforcePoolBasePath{{"}}"}}projects/{{"{{"}}project{{"}}"}}/locations/{{"{{"}}location{{"}}"}}/oauthClients/{{"{{"}}oauthclient{{"}}"}}/credentials/{{"{{"}}oauth_client_credential_id{{"}}"}}")
if err != nil {
return err
}

_, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "GET",
RawURL: url,
UserAgent: config.UserAgent,
})
if err != nil {
e := err.(*googleapi.Error)
// credential or parent client is expected to be deleted.
if (e.Code == 404) {
return nil
}

// Return err in all other cases
return err
}

return fmt.Errorf("IAMOAuthClientCredential still exists at %s", url)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
resource "google_iam_oauth_client" "oauth_client" {
oauth_client_id = "{{index $.Vars "oauth_client_id"}}"
location = "global"
allowed_grant_types = ["AUTHORIZATION_CODE_GRANT"]
allowed_redirect_uris = ["https://www.example.com"]
allowed_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
client_type = "CONFIDENTIAL_CLIENT"
}

resource "google_iam_oauth_client_credential" "{{$.PrimaryResourceId}}" {
oauthclient = google_iam_oauth_client.oauth_client.oauth_client_id
location = google_iam_oauth_client.oauth_client.location
oauth_client_credential_id = "{{index $.Vars "oauth_client_credential_id"}}"
disabled = true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
resource "google_iam_oauth_client" "oauth_client" {
oauth_client_id = "{{index $.Vars "oauth_client_id"}}"
location = "global"
allowed_grant_types = ["AUTHORIZATION_CODE_GRANT"]
allowed_redirect_uris = ["https://www.example.com"]
allowed_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
client_type = "CONFIDENTIAL_CLIENT"
}

resource "google_iam_oauth_client_credential" "{{$.PrimaryResourceId}}" {
oauthclient = google_iam_oauth_client.oauth_client.oauth_client_id
location = google_iam_oauth_client.oauth_client.location
oauth_client_credential_id = "{{index $.Vars "oauth_client_credential_id"}}"
disabled = true
display_name = "Display Name of credential"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package iamworkforcepool_test

import (
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"

"github.com/hashicorp/terraform-provider-google/google/acctest"
)

func TestAccIAMWorkforcePoolOauthClientCredential_basic(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckIAMWorkforcePoolOauthClientCredentialDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccIAMWorkforcePoolOauthClientCredential_basic(context),
},
{
ResourceName: "google_iam_oauth_client_credential.example",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"location", "oauth_client_credential_id", "oauthclient"},
},
{
Config: testAccIAMWorkforcePoolOauthClientCredential_basic_update(context),
},
{
ResourceName: "google_iam_oauth_client_credential.example",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"location", "oauth_client_credential_id", "oauthclient"},
},
},
})
}

func testAccIAMWorkforcePoolOauthClientCredential_basic(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_iam_oauth_client" "oauth_client" {
oauth_client_id = "tf-test-example-client-id%{random_suffix}"
location = "global"
allowed_grant_types = ["AUTHORIZATION_CODE_GRANT"]
allowed_redirect_uris = ["https://www.example.com"]
allowed_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
client_type = "CONFIDENTIAL_CLIENT"
}

resource "google_iam_oauth_client_credential" "example" {
oauthclient = google_iam_oauth_client.oauth_client.oauth_client_id
location = google_iam_oauth_client.oauth_client.location
oauth_client_credential_id = "tf-test-cred-id%{random_suffix}"
disabled = true
}
`, context)
}

func testAccIAMWorkforcePoolOauthClientCredential_basic_update(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_iam_oauth_client" "oauth_client" {
oauth_client_id = "tf-test-example-client-id%{random_suffix}"
location = "global"
allowed_grant_types = ["AUTHORIZATION_CODE_GRANT"]
allowed_redirect_uris = ["https://www.example.com"]
allowed_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
client_type = "CONFIDENTIAL_CLIENT"
}

resource "google_iam_oauth_client_credential" "example" {
oauthclient = google_iam_oauth_client.oauth_client.oauth_client_id
location = google_iam_oauth_client.oauth_client.location
oauth_client_credential_id = "tf-test-cred-id%{random_suffix}"
disabled = true
}
`, context)
}


func TestAccIAMWorkforcePoolOauthClientCredential_full(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckIAMWorkforcePoolOauthClientCredentialDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccIAMWorkforcePoolOauthClientCredential_full(context),
},
{
ResourceName: "google_iam_oauth_client_credential.example",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"location", "oauth_client_credential_id", "oauthclient"},
},
{
Config: testAccIAMWorkforcePoolOauthClientCredential_full_update(context),
},
{
ResourceName: "google_iam_oauth_client_credential.example",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"location", "oauth_client_credential_id", "oauthclient"},
},
},
})
}

func testAccIAMWorkforcePoolOauthClientCredential_full(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_iam_oauth_client" "oauth_client" {
oauth_client_id = "tf-test-example-client-id%{random_suffix}"
location = "global"
allowed_grant_types = ["AUTHORIZATION_CODE_GRANT"]
allowed_redirect_uris = ["https://www.example.com"]
allowed_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
client_type = "CONFIDENTIAL_CLIENT"
}

resource "google_iam_oauth_client_credential" "example" {
oauthclient = google_iam_oauth_client.oauth_client.oauth_client_id
location = google_iam_oauth_client.oauth_client.location
oauth_client_credential_id = "tf-test-cred-id%{random_suffix}"
disabled = true
display_name = "Display Name of credential"
}
`, context)
}

func testAccIAMWorkforcePoolOauthClientCredential_full_update(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_iam_oauth_client" "oauth_client" {
oauth_client_id = "tf-test-example-client-id%{random_suffix}"
location = "global"
allowed_grant_types = ["AUTHORIZATION_CODE_GRANT"]
allowed_redirect_uris = ["https://www.example.com"]
allowed_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
client_type = "CONFIDENTIAL_CLIENT"
}

resource "google_iam_oauth_client_credential" "example" {
oauthclient = google_iam_oauth_client.oauth_client.oauth_client_id
location = google_iam_oauth_client.oauth_client.location
oauth_client_credential_id = "tf-test-cred-id%{random_suffix}"
disabled = true
display_name = "Updated displayName"
}
`, context)
}
Loading