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 saml field to google_iam_workload_identity_pool_provider resource #6718

Merged
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
3 changes: 3 additions & 0 deletions .changelog/9061.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
workloadidentity: added `saml` block to `google_iam_workload_identity_pool_provider` resource
```
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ For OIDC providers, the following rules apply:
"aws": {
Type: schema.TypeList,
Optional: true,
Description: `An Amazon Web Services identity provider. Not compatible with the property oidc.`,
Description: `An Amazon Web Services identity provider. Not compatible with the property oidc or saml.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
Expand All @@ -201,7 +201,7 @@ For OIDC providers, the following rules apply:
},
},
},
ExactlyOneOf: []string{"aws", "oidc"},
ExactlyOneOf: []string{"aws", "oidc", "saml"},
},
"description": {
Type: schema.TypeString,
Expand All @@ -222,7 +222,7 @@ However, existing tokens still grant access.`,
"oidc": {
Type: schema.TypeList,
Optional: true,
Description: `An OpenId Connect 1.0 identity provider. Not compatible with the property aws.`,
Description: `An OpenId Connect 1.0 identity provider. Not compatible with the property aws or saml.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -279,7 +279,23 @@ the following fields:
},
},
},
ExactlyOneOf: []string{"aws", "oidc"},
ExactlyOneOf: []string{"aws", "oidc", "saml"},
},
"saml": {
Type: schema.TypeList,
Optional: true,
Description: `An SAML 2.0 identity provider. Not compatible with the property oidc or aws.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"idp_metadata_xml": {
Type: schema.TypeString,
Required: true,
Description: `SAML Identity provider configuration metadata xml doc.`,
},
},
},
ExactlyOneOf: []string{"aws", "oidc", "saml"},
},
"name": {
Type: schema.TypeString,
Expand Down Expand Up @@ -359,6 +375,12 @@ func resourceIAMBetaWorkloadIdentityPoolProviderCreate(d *schema.ResourceData, m
} else if v, ok := d.GetOkExists("oidc"); !tpgresource.IsEmptyValue(reflect.ValueOf(oidcProp)) && (ok || !reflect.DeepEqual(v, oidcProp)) {
obj["oidc"] = oidcProp
}
samlProp, err := expandIAMBetaWorkloadIdentityPoolProviderSaml(d.Get("saml"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("saml"); !tpgresource.IsEmptyValue(reflect.ValueOf(samlProp)) && (ok || !reflect.DeepEqual(v, samlProp)) {
obj["saml"] = samlProp
}

url, err := tpgresource.ReplaceVars(d, config, "{{IAMBetaBasePath}}projects/{{project}}/locations/global/workloadIdentityPools/{{workload_identity_pool_id}}/providers?workloadIdentityPoolProviderId={{workload_identity_pool_provider_id}}")
if err != nil {
Expand Down Expand Up @@ -493,6 +515,9 @@ func resourceIAMBetaWorkloadIdentityPoolProviderRead(d *schema.ResourceData, met
if err := d.Set("oidc", flattenIAMBetaWorkloadIdentityPoolProviderOidc(res["oidc"], d, config)); err != nil {
return fmt.Errorf("Error reading WorkloadIdentityPoolProvider: %s", err)
}
if err := d.Set("saml", flattenIAMBetaWorkloadIdentityPoolProviderSaml(res["saml"], d, config)); err != nil {
return fmt.Errorf("Error reading WorkloadIdentityPoolProvider: %s", err)
}

return nil
}
Expand Down Expand Up @@ -555,6 +580,12 @@ func resourceIAMBetaWorkloadIdentityPoolProviderUpdate(d *schema.ResourceData, m
} else if v, ok := d.GetOkExists("oidc"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, oidcProp)) {
obj["oidc"] = oidcProp
}
samlProp, err := expandIAMBetaWorkloadIdentityPoolProviderSaml(d.Get("saml"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("saml"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, samlProp)) {
obj["saml"] = samlProp
}

url, err := tpgresource.ReplaceVars(d, config, "{{IAMBetaBasePath}}projects/{{project}}/locations/global/workloadIdentityPools/{{workload_identity_pool_id}}/providers/{{workload_identity_pool_provider_id}}")
if err != nil {
Expand Down Expand Up @@ -593,6 +624,10 @@ func resourceIAMBetaWorkloadIdentityPoolProviderUpdate(d *schema.ResourceData, m
"oidc.issuer_uri",
"oidc.jwks_json")
}

if d.HasChange("saml") {
updateMask = append(updateMask, "saml")
}
// updateMask is a URL parameter but not present in the schema, so ReplaceVars
// won't set it
url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")})
Expand Down Expand Up @@ -782,6 +817,23 @@ func flattenIAMBetaWorkloadIdentityPoolProviderOidcJwksJson(v interface{}, d *sc
return v
}

func flattenIAMBetaWorkloadIdentityPoolProviderSaml(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["idp_metadata_xml"] =
flattenIAMBetaWorkloadIdentityPoolProviderSamlIdpMetadataXml(original["idpMetadataXml"], d, config)
return []interface{}{transformed}
}
func flattenIAMBetaWorkloadIdentityPoolProviderSamlIdpMetadataXml(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func expandIAMBetaWorkloadIdentityPoolProviderDisplayName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
Expand Down Expand Up @@ -877,6 +929,29 @@ func expandIAMBetaWorkloadIdentityPoolProviderOidcJwksJson(v interface{}, d tpgr
return v, nil
}

func expandIAMBetaWorkloadIdentityPoolProviderSaml(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedIdpMetadataXml, err := expandIAMBetaWorkloadIdentityPoolProviderSamlIdpMetadataXml(original["idp_metadata_xml"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedIdpMetadataXml); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["idpMetadataXml"] = transformedIdpMetadataXml
}

return transformed, nil
}

func expandIAMBetaWorkloadIdentityPoolProviderSamlIdpMetadataXml(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func resourceIAMBetaWorkloadIdentityPoolProviderDecoder(d *schema.ResourceData, meta interface{}, res map[string]interface{}) (map[string]interface{}, error) {
if v := res["state"]; v == "DELETED" {
return nil, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,101 @@ EOT
`, context)
}

func TestAccIAMBetaWorkloadIdentityPoolProvider_iamWorkloadIdentityPoolProviderSamlBasicExample(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: testAccCheckIAMBetaWorkloadIdentityPoolProviderDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccIAMBetaWorkloadIdentityPoolProvider_iamWorkloadIdentityPoolProviderSamlBasicExample(context),
},
{
ResourceName: "google_iam_workload_identity_pool_provider.example",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"workload_identity_pool_id", "workload_identity_pool_provider_id"},
},
},
})
}

func testAccIAMBetaWorkloadIdentityPoolProvider_iamWorkloadIdentityPoolProviderSamlBasicExample(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_iam_workload_identity_pool" "pool" {
workload_identity_pool_id = "tf-test-example-pool%{random_suffix}"
}

resource "google_iam_workload_identity_pool_provider" "example" {
workload_identity_pool_id = google_iam_workload_identity_pool.pool.workload_identity_pool_id
workload_identity_pool_provider_id = "tf-test-example-prvdr%{random_suffix}"
attribute_mapping = {
"google.subject" = "assertion.arn"
"attribute.aws_account" = "assertion.account"
"attribute.environment" = "assertion.arn.contains(\":instance-profile/Production\") ? \"prod\" : \"test\""
}
saml {
idp_metadata_xml = file("test-fixtures/metadata.xml")
}
}
`, context)
}

func TestAccIAMBetaWorkloadIdentityPoolProvider_iamWorkloadIdentityPoolProviderSamlFullExample(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: testAccCheckIAMBetaWorkloadIdentityPoolProviderDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccIAMBetaWorkloadIdentityPoolProvider_iamWorkloadIdentityPoolProviderSamlFullExample(context),
},
{
ResourceName: "google_iam_workload_identity_pool_provider.example",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"workload_identity_pool_id", "workload_identity_pool_provider_id"},
},
},
})
}

func testAccIAMBetaWorkloadIdentityPoolProvider_iamWorkloadIdentityPoolProviderSamlFullExample(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_iam_workload_identity_pool" "pool" {
workload_identity_pool_id = "tf-test-example-pool%{random_suffix}"
}

resource "google_iam_workload_identity_pool_provider" "example" {
workload_identity_pool_id = google_iam_workload_identity_pool.pool.workload_identity_pool_id
workload_identity_pool_provider_id = "tf-test-example-prvdr%{random_suffix}"
display_name = "Name of provider"
description = "SAML 2.0 identity pool provider for automated test"
disabled = true
attribute_mapping = {
"google.subject" = "assertion.arn"
"attribute.aws_account" = "assertion.account"
"attribute.environment" = "assertion.arn.contains(\":instance-profile/Production\") ? \"prod\" : \"test\""
}
saml {
idp_metadata_xml = file("test-fixtures/metadata.xml")
}
}
`, context)
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func testSweepIAMBetaWorkloadIdentityPoolProvider(region string) error {
},
}

listTemplate := strings.Split("https://iam.googleapis.com/v1beta/projects/{{project}}/locations/global/workloadIdentityPools/{{workload_identity_pool_id}}/providers", "?")[0]
listTemplate := strings.Split("https://iam.googleapis.com/v1/projects/{{project}}/locations/global/workloadIdentityPools/{{workload_identity_pool_id}}/providers", "?")[0]
listUrl, err := tpgresource.ReplaceVars(d, config, listTemplate)
if err != nil {
log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err)
Expand Down Expand Up @@ -112,7 +112,7 @@ func testSweepIAMBetaWorkloadIdentityPoolProvider(region string) error {
continue
}

deleteTemplate := "https://iam.googleapis.com/v1beta/projects/{{project}}/locations/global/workloadIdentityPools/{{workload_identity_pool_id}}/providers/{{workload_identity_pool_provider_id}}"
deleteTemplate := "https://iam.googleapis.com/v1/projects/{{project}}/locations/global/workloadIdentityPools/{{workload_identity_pool_id}}/providers/{{workload_identity_pool_provider_id}}"
deleteUrl, err := tpgresource.ReplaceVars(d, config, deleteTemplate)
if err != nil {
log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func testSweepIAMBetaWorkloadIdentityPool(region string) error {
},
}

listTemplate := strings.Split("https://iam.googleapis.com/v1beta/projects/{{project}}/locations/global/workloadIdentityPools", "?")[0]
listTemplate := strings.Split("https://iam.googleapis.com/v1/projects/{{project}}/locations/global/workloadIdentityPools", "?")[0]
listUrl, err := tpgresource.ReplaceVars(d, config, listTemplate)
if err != nil {
log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err)
Expand Down Expand Up @@ -112,7 +112,7 @@ func testSweepIAMBetaWorkloadIdentityPool(region string) error {
continue
}

deleteTemplate := "https://iam.googleapis.com/v1beta/projects/{{project}}/locations/global/workloadIdentityPools/{{workload_identity_pool_id}}"
deleteTemplate := "https://iam.googleapis.com/v1/projects/{{project}}/locations/global/workloadIdentityPools/{{workload_identity_pool_id}}"
deleteUrl, err := tpgresource.ReplaceVars(d, config, deleteTemplate)
if err != nil {
log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err)
Expand Down
14 changes: 14 additions & 0 deletions google-beta/services/iambeta/test-fixtures/metadata.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://example.idp.metadata.com">
<md:IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>
MIIC3jCCAcagAwIBAgIBATANBgkqhkiG9w0BAQsFADAeMRwwGgYDVQQDExNNeSBTZXJ2aWNlIFByb3ZpZGVyMB4XDTIzMTEzMDAwMzc1NVoXDTM4MTEyNjAwMzc1NVowHjEcMBoGA1UEAxMTTXkgU2VydmljZSBQcm92aWRlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM1W92rSmU8MbqNhIL6E0OEg3H0t65wqEMqg8r99yjZq/KW9ps6PoO4MZVIFLAMRtXvoTrVv6oPYCoc1T5u46Wl16qldGGRWk44Lr03L5xRqhKAVPfHMGL3HO0aaSnrVjKuFbGgjoMxJRSHHmU2Q6FU5AaRP2zodnkNhsZZt+x4dwKkow94uvTIQc1avdfCqKB5PeS2+2/oeFoNc78Pbnok+wUKZbhHwzYQdmSZ8NJnsIDpqf1IGcXyMMEqGkHmAa3O3sme4gYkl/0MbHcCSFwyaW+gUFy0uHz/amTiiZNoJ+0TPoNLz0XLXYv7ACxz5mTa/DaMvZ1zRsKi6wOzoSOUCAwEAAaMnMCUwDgYDVR0PAQH/BAQDAgKEMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IBAQBFyfbJBaKuHSNd4Kx73ozSV2no96ctY3ZciUjCmUArLeqg0qQwkwXP6AoOd5bwIpKAmgHJgyv7T6GGHA+w9qNXuQxU86ph3gPRlYCB3+pnaiDq/iUECE09pleQJr//Am5x2Z1Bc8itMUPRuVsU873DASOFho3HZykmgS6x4JwAqCO2dBNoYHi+N9DsbQ9MatNdUOvrYgCTzbwRuwsDwLno/OSFQYTLqZVTW+NuEL/Axtx/yu9wKvuTzcD2MqPHaisy35PkPbJLsCauFJn8CAC4U5xKEkwsaumANeMZzzvAv8J2SIyjagLI+iF06AmCQNeytSvYxptxt7hhTg6uJVxS
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
</md:IDPSSODescriptor>
</md:EntityDescriptor>
2 changes: 1 addition & 1 deletion google-beta/transport/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ var DefaultBasePaths = map[string]string{
GkeonpremBasePathKey: "https://gkeonprem.googleapis.com/v1/",
HealthcareBasePathKey: "https://healthcare.googleapis.com/v1beta1/",
IAM2BasePathKey: "https://iam.googleapis.com/v2beta/",
IAMBetaBasePathKey: "https://iam.googleapis.com/v1beta/",
IAMBetaBasePathKey: "https://iam.googleapis.com/v1/",
IAMWorkforcePoolBasePathKey: "https://iam.googleapis.com/v1/",
IapBasePathKey: "https://iap.googleapis.com/v1/",
IdentityPlatformBasePathKey: "https://identitytoolkit.googleapis.com/v2/",
Expand Down
Loading