Repository: mrparkers/terraform-provider-keycloak
Pull request #261 (2020-03-25 09:44:37)

SAML client: add force_name_id_format attribute
This pull request introduces the `force_name_id_format` attribute to the `saml_client` resource.
Static binary for this PR can be found [here](https://github.com/Xide/terraform-provider-keycloak/releases/download/1.0/terraform-provider-keycloak.zip)



Patch:
diff --git a/docs/resources/keycloak_saml_client.md b/docs/resources/keycloak_saml_client.md
index 3eec0de..63eb7b0 100644
--- a/docs/resources/keycloak_saml_client.md
+++ b/docs/resources/keycloak_saml_client.md
@@ -44,6 +44,7 @@ The following arguments are supported:
 - `force_post_binding` - (Optional) When `true`, Keycloak will always respond to an authentication request via the SAML POST Binding.
 - `front_channel_logout` - (Optional) When `true`, this client will require a browser redirect in order to perform a logout.
 - `name_id_format` - (Optional) Sets the Name ID format for the subject.
+- `force_name_id_format` - (Optional) Ignore requested NameID subject format and use the one defined in `name_id_format` instead.
 - `root_url` - (Optional) When specified, this value is prepended to all relative URLs.
 - `valid_redirect_uris` - (Optional) When specified, Keycloak will use this list to validate given Assertion Consumer URLs specified in the authentication request.
 - `base_url` - (Optional) When specified, this URL will be used whenever Keycloak needs to link to this client.
diff --git a/keycloak/saml_client.go b/keycloak/saml_client.go
index b713dfe..4445a38 100644
--- a/keycloak/saml_client.go
+++ b/keycloak/saml_client.go
@@ -10,6 +10,7 @@ type SamlClientAttributes struct {
 	SignAssertions          *string `json:"saml.assertion.signature"`
 	ClientSignatureRequired *string `json:"saml.client.signature"`
 	ForcePostBinding        *string `json:"saml.force.post.binding"`
+	ForceNameIdFormat       *string `json:"saml_force_name_id_format"`
 	// attributes above are actually booleans, but the Keycloak API expects strings
 	NameIdFormat                    string  `json:"saml_name_id_format"`
 	SigningCertificate              *string `json:"saml.signing.certificate,omitempty"`
diff --git a/provider/resource_keycloak_saml_client.go b/provider/resource_keycloak_saml_client.go
index 5106172..6d49ac6 100644
--- a/provider/resource_keycloak_saml_client.go
+++ b/provider/resource_keycloak_saml_client.go
@@ -77,6 +77,11 @@ func resourceKeycloakSamlClient() *schema.Resource {
 				Optional: true,
 				Computed: true,
 			},
+			"force_name_id_format": {
+				Type:     schema.TypeBool,
+				Optional: true,
+				Computed: true,
+			},
 			"name_id_format": {
 				Type:         schema.TypeString,
 				Optional:     true,
@@ -202,6 +207,11 @@ func mapToSamlClientFromData(data *schema.ResourceData) *keycloak.SamlClient {
 		samlAttributes.IncludeAuthnStatement = &includeAuthnStatementString
 	}
 
+	if forceNameIdFormat, ok := data.GetOkExists("force_name_id_format"); ok {
+		forceNameIdFormatString := strconv.FormatBool(forceNameIdFormat.(bool))
+		samlAttributes.ForceNameIdFormat = &forceNameIdFormatString
+	}
+
 	if signDocuments, ok := data.GetOkExists("sign_documents"); ok {
 		signDocumentsString := strconv.FormatBool(signDocuments.(bool))
 		samlAttributes.SignDocuments = &signDocumentsString
@@ -252,6 +262,14 @@ func mapToDataFromSamlClient(data *schema.ResourceData, client *keycloak.SamlCli
 
 		data.Set("include_authn_statement", includeAuthnStatement)
 	}
+	if client.Attributes.ForceNameIdFormat != nil {
+		forceNameIdFormat, err := strconv.ParseBool(*client.Attributes.ForceNameIdFormat)
+		if err != nil {
+			return err
+		}
+
+		data.Set("force_name_id_format", forceNameIdFormat)
+	}
 
 	if client.Attributes.SignDocuments != nil {
 		signDocuments, err := strconv.ParseBool(*client.Attributes.SignDocuments)


Test patch:
diff --git a/provider/resource_keycloak_saml_client_test.go b/provider/resource_keycloak_saml_client_test.go
index fe548f8..f86d850 100644
--- a/provider/resource_keycloak_saml_client_test.go
+++ b/provider/resource_keycloak_saml_client_test.go
@@ -158,6 +158,7 @@ func TestAccKeycloakSamlClient_updateInPlace(t *testing.T) {
 			SignAssertions:                  randomBoolAsStringPointer(),
 			ClientSignatureRequired:         &clientSignatureRequired,
 			ForcePostBinding:                randomBoolAsStringPointer(),
+			ForceNameIdFormat:               randomBoolAsStringPointer(),
 			NameIdFormat:                    randomStringInSlice(keycloakSamlClientNameIdFormats),
 			SigningCertificate:              &signingCertificateBefore,
 			SigningPrivateKey:               &signingPrivateKeyBefore,
@@ -193,6 +194,7 @@ func TestAccKeycloakSamlClient_updateInPlace(t *testing.T) {
 			SignAssertions:                  randomBoolAsStringPointer(),
 			ClientSignatureRequired:         &clientSignatureRequired,
 			ForcePostBinding:                randomBoolAsStringPointer(),
+			ForceNameIdFormat:               randomBoolAsStringPointer(),
 			NameIdFormat:                    randomStringInSlice(keycloakSamlClientNameIdFormats),
 			SigningCertificate:              &signingCertificateAfter,
 			SigningPrivateKey:               &signingPrivateKeyAfter,
@@ -399,7 +401,12 @@ func testAccCheckKeycloakSamlClientHasDefaultBooleanAttributes(resourceName stri
 			return err
 		}
 
-		if !includeAuthnStatement && !signDocuments && !signAssertions && !clientSignatureRequired && !forcePostBinding {
+		forceNameIdFormat, err := parseBoolAndTreatEmptyStringAsFalse(rs.Primary.Attributes["force_name_id_format"])
+		if err != nil {
+			return err
+		}
+
+		if !includeAuthnStatement && !signDocuments && !signAssertions && !clientSignatureRequired && !forcePostBinding && !forceNameIdFormat {
 			return fmt.Errorf("expected saml client with id %s to have some defaults set by Keycloak", rs.Primary.ID)
 		}
 
@@ -487,6 +494,7 @@ resource "keycloak_saml_client" "saml_client" {
 	sign_assertions            = %s
 	client_signature_required  = %s
 	force_post_binding         = %s
+	force_name_id_format       = %s
 
 	front_channel_logout       = %t
 	name_id_format             = "%s"
@@ -516,6 +524,7 @@ resource "keycloak_saml_client" "saml_client" {
 		*client.Attributes.SignAssertions,
 		*client.Attributes.ClientSignatureRequired,
 		*client.Attributes.ForcePostBinding,
+		*client.Attributes.ForceNameIdFormat,
 		client.FrontChannelLogout,
 		client.Attributes.NameIdFormat,
 		client.RootUrl,