From 37dcb74954577c9342cdbd4bf2e3e2b063187d4c Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 14 Mar 2024 16:45:27 +0530 Subject: [PATCH] CRUD for idp --- .../v2/iam/data_source_nutanix_saml_idp_v2.go | 64 ++- .../iam/data_source_nutanix_saml_idps_v2.go | 9 +- .../v2/iam/resource_nutanix_saml_idp_v2.go | 382 ++++++++++++++++++ 3 files changed, 453 insertions(+), 2 deletions(-) create mode 100644 nutanix/services/v2/iam/resource_nutanix_saml_idp_v2.go diff --git a/nutanix/services/v2/iam/data_source_nutanix_saml_idp_v2.go b/nutanix/services/v2/iam/data_source_nutanix_saml_idp_v2.go index c37de9b2d..f2502e85d 100644 --- a/nutanix/services/v2/iam/data_source_nutanix_saml_idp_v2.go +++ b/nutanix/services/v2/iam/data_source_nutanix_saml_idp_v2.go @@ -28,6 +28,10 @@ func DatasourceNutanixSamlIDPv4() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "idp_metadata_xml": { + Type: schema.TypeString, + Computed: true, + }, "name": { Type: schema.TypeString, Computed: true, @@ -105,7 +109,10 @@ func DatasourceNutanixSamlIDPv4Read(ctx context.Context, d *schema.ResourceData, if err := d.Set("idp_metadata_url", getResp.IdpMetadataUrl); err != nil { return diag.FromErr(err) } - if err := d.Set("idp_metadata", getResp.IdpMetadata); err != nil { + if err := d.Set("idp_metadata", flattenIdpMetadata(getResp.IdpMetadata)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("idp_metadata_xml", getResp.IdpMetadataXml); err != nil { return diag.FromErr(err) } if err := d.Set("username_attr", getResp.UsernameAttribute); err != nil { @@ -148,3 +155,58 @@ func DatasourceNutanixSamlIDPv4Read(ctx context.Context, d *schema.ResourceData, d.SetId(*getResp.ExtId) return nil } + +func flattenIdpMetadata(pr *import1.IdpMetadata) []map[string]interface{} { + if pr != nil { + idps := make([]map[string]interface{}, 0) + idp := make(map[string]interface{}) + + idp["entity_id"] = pr.EntityId + idp["login_url"] = pr.LoginUrl + idp["logout_url"] = pr.LogoutUrl + idp["error_url"] = pr.ErrorUrl + idp["certificate"] = pr.Certificate + if pr.NameIdPolicyFormat != nil { + idp["name_id_policy_format"] = flattenNameIdPolicyFormat(pr.NameIdPolicyFormat) + } + + idps = append(idps, idp) + return idps + } + return nil +} + +func flattenNameIdPolicyFormat(pr *import1.NameIdPolicyFormat) string { + if pr != nil { + const two, three, four, five, six, seven, eight, nine, ten = 2, 3, 4, 5, 6, 7, 8, 9, 10 + + if *pr == import1.NameIdPolicyFormat(two) { + return "emailAddress" + } + if *pr == import1.NameIdPolicyFormat(three) { + return "unspecified" + } + if *pr == import1.NameIdPolicyFormat(four) { + return "X509SubjectName" + } + if *pr == import1.NameIdPolicyFormat(five) { + return "WindowsDomainQualifiedName" + } + if *pr == import1.NameIdPolicyFormat(six) { + return "encrypted" + } + if *pr == import1.NameIdPolicyFormat(seven) { + return "entity" + } + if *pr == import1.NameIdPolicyFormat(eight) { + return "kerberos" + } + if *pr == import1.NameIdPolicyFormat(nine) { + return "persistent" + } + if *pr == import1.NameIdPolicyFormat(ten) { + return "transient" + } + } + return "UNKNOWN" +} diff --git a/nutanix/services/v2/iam/data_source_nutanix_saml_idps_v2.go b/nutanix/services/v2/iam/data_source_nutanix_saml_idps_v2.go index ed23ceaf7..801c7d957 100644 --- a/nutanix/services/v2/iam/data_source_nutanix_saml_idps_v2.go +++ b/nutanix/services/v2/iam/data_source_nutanix_saml_idps_v2.go @@ -54,6 +54,10 @@ func DatasourceNutanixSamlIDPsV4() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "idp_metadata_xml": { + Type: schema.TypeString, + Computed: true, + }, "name": { Type: schema.TypeString, Computed: true, @@ -177,11 +181,14 @@ func flattenIdentityProvidersEntities(pr []import1.SamlIdentityProvider) []inter idp["name"] = v.Name } if v.IdpMetadata != nil { - idp["idp_metadata_url"] = v.IdpMetadata + idp["idp_metadata_url"] = flattenIdpMetadata(v.IdpMetadata) } if v.IdpMetadataUrl != nil { idp["idp_metadata"] = v.IdpMetadataUrl } + if v.IdpMetadataXml != nil { + idp["idp_metadata_xml"] = v.IdpMetadataXml + } if v.UsernameAttribute != nil { idp["username_attr"] = v.UsernameAttribute } diff --git a/nutanix/services/v2/iam/resource_nutanix_saml_idp_v2.go b/nutanix/services/v2/iam/resource_nutanix_saml_idp_v2.go new file mode 100644 index 000000000..6ce07f490 --- /dev/null +++ b/nutanix/services/v2/iam/resource_nutanix_saml_idp_v2.go @@ -0,0 +1,382 @@ +package iam + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + errResp "github.com/nutanix-core/ntnx-api-golang-sdk-internal/iam-go-client/v16/models/iam/v4/error" + + import1 "github.com/nutanix-core/ntnx-api-golang-sdk-internal/iam-go-client/v16/models/iam/v4/authn" + conns "github.com/terraform-providers/terraform-provider-nutanix/nutanix" + "github.com/terraform-providers/terraform-provider-nutanix/utils" +) + +func ResourceNutanixSamlIdpV4() *schema.Resource { + return &schema.Resource{ + CreateContext: ResourceNutanixSamlIdpV4Create, + ReadContext: ResourceNutanixSamlIdpV4Read, + UpdateContext: ResourceNutanixSamlIdpV4Update, + DeleteContext: ResourceNutanixSamlIdpV4Delete, + Schema: map[string]*schema.Schema{ + "ext_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "idp_metadata_url": { + Type: schema.TypeString, + Optional: true, + }, + "idp_metadata": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "entity_id": { + Type: schema.TypeString, + Required: true, + }, + "login_url": { + Type: schema.TypeString, + Required: true, + }, + "logout_url": { + Type: schema.TypeString, + Optional: true, + }, + "error_url": { + Type: schema.TypeString, + Optional: true, + }, + "certificate": { + Type: schema.TypeString, + Required: true, + }, + "name_id_policy_format": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"emailAddress", "encrypted", "unspecified", "transient", + "WindowsDomainQualifiedName", "X509SubjectName", "kerberos", "persistent", "entity"}, false), + }, + }, + }, + }, + "idp_metadata_xml": { + Type: schema.TypeString, + Optional: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "username_attribute": { + Type: schema.TypeString, + Optional: true, + }, + "email_attribute": { + Type: schema.TypeString, + Optional: true, + }, + "groups_attribute": { + Type: schema.TypeString, + Optional: true, + }, + "groups_delim": { + Type: schema.TypeString, + Optional: true, + }, + "custom_attribute": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "entity_issuer": { + Type: schema.TypeString, + Optional: true, + }, + "is_signed_authn_req_enabled": { + Type: schema.TypeBool, + Optional: true, + }, + "created_time": { + Type: schema.TypeString, + Computed: true, + }, + "last_updated_time": { + Type: schema.TypeString, + Computed: true, + }, + "created_by": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func ResourceNutanixSamlIdpV4Create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).IamAPI + + input := &import1.SamlIdentityProvider{} + if idpMetadataurl, ok := d.GetOk("idp_metadata_url"); ok { + input.IdpMetadataUrl = utils.StringPtr(idpMetadataurl.(string)) + } + if idpMetadata, ok := d.GetOk("idp_metadata"); ok { + input.IdpMetadata = expandIdpMetadata(idpMetadata) + } + if idpMetaXml, ok := d.GetOk("idp_metadata_xml"); ok { + input.IdpMetadataXml = utils.StringPtr(idpMetaXml.(string)) + } + if name, ok := d.GetOk("name"); ok { + input.Name = utils.StringPtr(name.(string)) + } + if uName, ok := d.GetOk("username_attribute"); ok { + input.UsernameAttribute = utils.StringPtr(uName.(string)) + } + if emailAttr, ok := d.GetOk("email_attribute"); ok { + input.EmailAttribute = utils.StringPtr(emailAttr.(string)) + } + if grpAttr, ok := d.GetOk("groups_attribute"); ok { + input.GroupsAttribute = utils.StringPtr(grpAttr.(string)) + } + if grpDelim, ok := d.GetOk("groups_delim"); ok { + input.GroupsDelim = utils.StringPtr(grpDelim.(string)) + } + if cAttr, ok := d.GetOk("custom_attribute"); ok { + input.CustomAttributes = utils.StringValueSlice(cAttr.([]*string)) + } + if entity, ok := d.GetOk("entity_issuer"); ok { + input.EntityIssuer = utils.StringPtr(entity.(string)) + } + if isSigned, ok := d.GetOk("is_signed_authn_req_enabled"); ok { + input.IsSignedAuthnReqEnabled = utils.BoolPtr(isSigned.(bool)) + } + + resp, err := conn.SamlIdentityAPIInstance.CreateSamlIdentityProvider(input) + + if err != nil { + var errordata map[string]interface{} + e := json.Unmarshal([]byte(err.Error()), &errordata) + if e != nil { + return diag.FromErr(e) + } + data := errordata["data"].(map[string]interface{}) + errorList := data["error"].([]interface{}) + errorMessage := errorList[0].(map[string]interface{}) + return diag.Errorf("error while creating saml identity providers: %v", errorMessage["message"]) + } + + getResp := resp.Data.GetValue().(import1.SamlIdentityProvider) + + d.SetId(*getResp.ExtId) + return ResourceNutanixSamlIdpV4Read(ctx, d, meta) +} + +func ResourceNutanixSamlIdpV4Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).IamAPI + + resp, err := conn.SamlIdentityAPIInstance.GetSamlIdentityProviderById(utils.StringPtr(d.Id())) + if err != nil { + var errordata map[string]interface{} + e := json.Unmarshal([]byte(err.Error()), &errordata) + if e != nil { + return diag.FromErr(e) + } + data := errordata["data"].(map[string]interface{}) + errorList := data["error"].([]interface{}) + errorMessage := errorList[0].(map[string]interface{}) + return diag.Errorf("error while fetching saml identity providers: %v", errorMessage["message"]) + } + + getResp := resp.Data.GetValue().(import1.SamlIdentityProvider) + + if err := d.Set("name", getResp.Name); err != nil { + return diag.FromErr(err) + } + if err := d.Set("idp_metadata_url", getResp.IdpMetadataUrl); err != nil { + return diag.FromErr(err) + } + if err := d.Set("idp_metadata", flattenIdpMetadata(getResp.IdpMetadata)); err != nil { + return diag.FromErr(err) + } + if err := d.Set("username_attribute", getResp.UsernameAttribute); err != nil { + return diag.FromErr(err) + } + if err := d.Set("email_attribute", getResp.EmailAttribute); err != nil { + return diag.FromErr(err) + } + if err := d.Set("groups_attribute", getResp.GroupsAttribute); err != nil { + return diag.FromErr(err) + } + if err := d.Set("groups_delim", getResp.GroupsDelim); err != nil { + return diag.FromErr(err) + } + if err := d.Set("custom_attribute", getResp.CustomAttributes); err != nil { + return diag.FromErr(err) + } + if err := d.Set("entity_issuer", getResp.EntityIssuer); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_signed_authn_req_enabled", getResp.IsSignedAuthnReqEnabled); err != nil { + return diag.FromErr(err) + } + if getResp.CreatedTime != nil { + t := getResp.CreatedTime + if err := d.Set("created_time", t.String()); err != nil { + return diag.FromErr(err) + } + } + if getResp.LastUpdatedTime != nil { + t := getResp.LastUpdatedTime + if err := d.Set("last_updated_time", t.String()); err != nil { + return diag.FromErr(err) + } + } + if err := d.Set("created_by", getResp.CreatedBy); err != nil { + return diag.FromErr(err) + } + return nil +} + +func ResourceNutanixSamlIdpV4Update(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).IamAPI + updatedInput := import1.SamlIdentityProvider{} + resp, err := conn.SamlIdentityAPIInstance.GetSamlIdentityProviderById(utils.StringPtr(d.Id())) + if err != nil { + var errordata map[string]interface{} + e := json.Unmarshal([]byte(err.Error()), &errordata) + if e != nil { + return diag.FromErr(e) + } + data := errordata["data"].(map[string]interface{}) + errorList := data["error"].([]interface{}) + errorMessage := errorList[0].(map[string]interface{}) + return diag.Errorf("error while fetching saml identity providers: %v", errorMessage["message"]) + } + + updatedInput = resp.Data.GetValue().(import1.SamlIdentityProvider) + + if d.HasChange("name") { + updatedInput.Name = utils.StringPtr(d.Get("name").(string)) + } + if d.HasChange("idp_metadata_url") { + updatedInput.IdpMetadataUrl = utils.StringPtr(d.Get("idp_metadata_url").(string)) + } + if d.HasChange("idp_metadata") { + updatedInput.IdpMetadata = expandIdpMetadata(d.Get("idp_metadata")) + } + if d.HasChange("username_attribute") { + updatedInput.UsernameAttribute = utils.StringPtr(d.Get("username_attribute").(string)) + } + if d.HasChange("email_attribute") { + updatedInput.EmailAttribute = utils.StringPtr(d.Get("email_attribute").(string)) + } + if d.HasChange("groups_attribute") { + updatedInput.GroupsAttribute = utils.StringPtr(d.Get("groups_attribute").(string)) + } + if d.HasChange("groups_delim") { + updatedInput.GroupsDelim = utils.StringPtr(d.Get("groups_delim").(string)) + } + if d.HasChange("custom_attribute") { + updatedInput.CustomAttributes = utils.StringValueSlice(d.Get("custom_attribute").([]*string)) + } + if d.HasChange("entity_issuer") { + updatedInput.EntityIssuer = utils.StringPtr(d.Get("entity_issuer").(string)) + } + if d.HasChange("is_signed_authn_req_enabled") { + updatedInput.IsSignedAuthnReqEnabled = utils.BoolPtr(d.Get("is_signed_authn_req_enabled").(bool)) + } + + updateResp, err := conn.SamlIdentityAPIInstance.UpdateSamlIdentityProviderById(utils.StringPtr(d.Id()), &updatedInput) + if err != nil { + var errordata map[string]interface{} + e := json.Unmarshal([]byte(err.Error()), &errordata) + if e != nil { + return diag.FromErr(e) + } + data := errordata["data"].(map[string]interface{}) + errorList := data["error"].([]interface{}) + errorMessage := errorList[0].(map[string]interface{}) + return diag.Errorf("error while updating saml identity providers: %v", errorMessage["message"]) + } + + updateTaskResp := updateResp.Data.GetValue().(import1.SamlIdentityProvider) + + if updateTaskResp.ExtId != nil { + fmt.Println("Saml Identity provider updated successfully") + } + return nil +} + +func ResourceNutanixSamlIdpV4Delete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.Client).IamAPI + + resp, err := conn.SamlIdentityAPIInstance.DeleteSamlIdentityProviderById(utils.StringPtr(d.Id())) + if err != nil { + var errordata map[string]interface{} + e := json.Unmarshal([]byte(err.Error()), &errordata) + if e != nil { + return diag.FromErr(e) + } + data := errordata["data"].(map[string]interface{}) + errorList := data["error"].([]interface{}) + errorMessage := errorList[0].(map[string]interface{}) + return diag.Errorf("error while deleting saml idp : %v", errorMessage["message"]) + } + + getResp := resp.Data.GetValue().(errResp.ErrorResponse) + + if getResp.Error != nil { + fmt.Println("Saml IDP deleted successfully.") + } + return nil +} + +func expandIdpMetadata(pr interface{}) *import1.IdpMetadata { + if pr != nil { + prI := pr.([]interface{}) + val := prI[0].(map[string]interface{}) + idp := &import1.IdpMetadata{} + + if entityID, ok := val["entity_id"]; ok { + idp.EntityId = utils.StringPtr(entityID.(string)) + } + if loginUrl, ok := val["login_url"]; ok { + idp.LoginUrl = utils.StringPtr(loginUrl.(string)) + } + if logoutUrl, ok := val["logout_url"]; ok { + idp.LogoutUrl = utils.StringPtr(logoutUrl.(string)) + } + if errorUrl, ok := val["error_url"]; ok { + idp.ErrorUrl = utils.StringPtr(errorUrl.(string)) + } + if certi, ok := val["certificate"]; ok { + idp.Certificate = utils.StringPtr(certi.(string)) + } + if policyFormat, ok := val["name_id_policy_format"]; ok { + subMap := map[string]interface{}{ + "emailAddress": 2, + "unspecified": 3, + "X509SubjectName": 4, + "WindowsDomainQualifiedName": 5, + "encrypted": 6, + "entity": 7, + "kerberos": 8, + "persistent": 9, + "transient": 10, + } + pInt := subMap[policyFormat.(string)] + p := import1.NameIdPolicyFormat(pInt.(int)) + idp.NameIdPolicyFormat = &p + } + + return idp + } + return nil +}