From e9c640c994b3dd9c8101fbeaf29c080f13d5f38e Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Thu, 30 Oct 2025 10:26:03 -0400 Subject: [PATCH 1/5] [minor_change] Add resource and data source for MACsec Policy under Fabric Policy Template. --- .../fabric_policies_macsec_policy/main.tf | 43 ++ ...ource_mso_fabric_policies_macsec_policy.go | 101 +++++ ..._mso_fabric_policies_macsec_policy_test.go | 50 ++ mso/provider.go | 2 + ...ource_mso_fabric_policies_macsec_policy.go | 426 ++++++++++++++++++ ..._mso_fabric_policies_macsec_policy_test.go | 224 +++++++++ ...abric_policies_macsec_policy.html.markdown | 49 ++ ...abric_policies_macsec_policy.html.markdown | 73 +++ 8 files changed, 968 insertions(+) create mode 100644 examples/fabric_policies_macsec_policy/main.tf create mode 100644 mso/datasource_mso_fabric_policies_macsec_policy.go create mode 100644 mso/datasource_mso_fabric_policies_macsec_policy_test.go create mode 100644 mso/resource_mso_fabric_policies_macsec_policy.go create mode 100644 mso/resource_mso_fabric_policies_macsec_policy_test.go create mode 100644 website/docs/d/fabric_policies_macsec_policy.html.markdown create mode 100644 website/docs/r/fabric_policies_macsec_policy.html.markdown diff --git a/examples/fabric_policies_macsec_policy/main.tf b/examples/fabric_policies_macsec_policy/main.tf new file mode 100644 index 00000000..292f08bf --- /dev/null +++ b/examples/fabric_policies_macsec_policy/main.tf @@ -0,0 +1,43 @@ +terraform { + required_providers { + mso = { + source = "CiscoDevNet/mso" + } + } +} + +provider "mso" { + username = "" # + password = "" # + url = "" # + insecure = true +} + +# fabric policy template example + +resource "mso_template" "fabric_policy_template" { + template_name = "fabric_policy_template" + template_type = "fabric_policy" +} + +# fabric policies macsec policy example + +resource "mso_fabric_policies_macsec_policy" "macsec_policy" { + template_id = mso_template.fabric_policy_template.id + name = "macsec_policy" + description = "Example description" + admin_state = "enabled" + interface_type = "access" + cipher_suite = "256GcmAes" + window_size = 128 + security_policy = "shouldSecure" + sak_expire_time = 60 + confidentiality_offset = "offset30" + key_server_priority = 8 + macsec_key { + key_name = "abc123" + psk = "AA111111111111111111111111111111111111111111111111111111111111aa" + start_time = "now" + end_time = "2027-09-23 00:00:00" + } +} diff --git a/mso/datasource_mso_fabric_policies_macsec_policy.go b/mso/datasource_mso_fabric_policies_macsec_policy.go new file mode 100644 index 00000000..b1bbdba1 --- /dev/null +++ b/mso/datasource_mso_fabric_policies_macsec_policy.go @@ -0,0 +1,101 @@ +package mso + +import ( + "log" + + "github.com/ciscoecosystem/mso-go-client/client" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func datasourceMacsecPolicy() *schema.Resource { + return &schema.Resource{ + Read: dataSourceMacsecPolicyRead, + + Schema: map[string]*schema.Schema{ + "template_id": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "uuid": { + Type: schema.TypeString, + Computed: true, + }, + "admin_state": { + Type: schema.TypeString, + Computed: true, + }, + "interface_type": { + Type: schema.TypeString, + Computed: true, + }, + "cipher_suite": { + Type: schema.TypeString, + Computed: true, + }, + "window_size": { + Type: schema.TypeInt, + Computed: true, + }, + "security_policy": { + Type: schema.TypeString, + Computed: true, + }, + "sak_expire_time": { + Type: schema.TypeInt, + Computed: true, + }, + "confidentiality_offset": { + Type: schema.TypeString, + Computed: true, + }, + "key_server_priority": { + Type: schema.TypeInt, + Computed: true, + }, + "macsec_key": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key_name": { + Type: schema.TypeString, + Computed: true, + }, + "psk": { + Type: schema.TypeString, + Computed: true, + }, + "start_time": { + Type: schema.TypeString, + Computed: true, + }, + "end_time": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceMacsecPolicyRead(d *schema.ResourceData, m interface{}) error { + log.Printf("[DEBUG] MSO MACsec Policy Data Source - Beginning Read") + msoClient := m.(*client.Client) + + templateId := d.Get("template_id").(string) + policyName := d.Get("name").(string) + + setMacsecPolicyData(d, msoClient, templateId, policyName) + log.Printf("[DEBUG] MSO MACsec Policy Data Source - Read Complete : %v", d.Id()) + return nil +} diff --git a/mso/datasource_mso_fabric_policies_macsec_policy_test.go b/mso/datasource_mso_fabric_policies_macsec_policy_test.go new file mode 100644 index 00000000..769ce150 --- /dev/null +++ b/mso/datasource_mso_fabric_policies_macsec_policy_test.go @@ -0,0 +1,50 @@ +package mso + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccMSOMacsecPolicyDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: MACsec Policy Data Source") }, + Config: testAccMSOMacsecPolicyDataSource(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "name", "tf_test_macsec_policy"), + resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "description", "Terraform test MACsec Policy"), + resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "admin_state", "enabled"), + resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "interface_type", "access"), + resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "cipher_suite", "256GcmAes"), + resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "window_size", "128"), + resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "security_policy", "shouldSecure"), + resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "sak_expire_time", "60"), + resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "confidentiality_offset", "offset30"), + resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "key_server_priority", "8"), + resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key.#", "1"), + customTestCheckResourceTypeSetAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key", + map[string]string{ + "key_name": "abc123", + "psk": "AA111111111111111111111111111111111111111111111111111111111111aa", + "start_time": "2027-09-23 00:00:00", + "end_time": "2030-09-23 00:00:00", + }, + ), + ), + }, + }, + }) +} + +func testAccMSOMacsecPolicyDataSource() string { + return fmt.Sprintf(`%s + data "mso_fabric_policies_macsec_policy" "macsec_policy" { + template_id = mso_fabric_policies_macsec_policy.macsec_policy.template_id + name = "tf_test_macsec_policy" + }`, testAccMSOMacsecPolicyConfigCreate()) +} diff --git a/mso/provider.go b/mso/provider.go index 40af5c26..0d403a38 100644 --- a/mso/provider.go +++ b/mso/provider.go @@ -131,6 +131,7 @@ func Provider() terraform.ResourceProvider { "mso_fabric_policies_physical_domain": resourceMSOPhysicalDomain(), "mso_service_device_cluster": resourceMSOServiceDeviceCluster(), "mso_fabric_policies_synce_interface_policy": resourceMSOSyncEInterfacePolicy(), + "mso_fabric_policies_macsec_policy": resourceMSOMacsecPolicy(), }, DataSourcesMap: map[string]*schema.Resource{ @@ -195,6 +196,7 @@ func Provider() terraform.ResourceProvider { "mso_fabric_policies_physical_domain": datasourceMSOPhysicalDomain(), "mso_service_device_cluster": datasourceMSOServiceDeviceCluster(), "mso_fabric_policies_synce_interface_policy": datasourceMSOSyncEInterfacePolicy(), + "mso_fabric_policies_macsec_policy": datasourceMacsecPolicy(), }, ConfigureFunc: configureClient, diff --git a/mso/resource_mso_fabric_policies_macsec_policy.go b/mso/resource_mso_fabric_policies_macsec_policy.go new file mode 100644 index 00000000..d32da6c0 --- /dev/null +++ b/mso/resource_mso_fabric_policies_macsec_policy.go @@ -0,0 +1,426 @@ +package mso + +import ( + "fmt" + "log" + + "github.com/ciscoecosystem/mso-go-client/client" + "github.com/ciscoecosystem/mso-go-client/container" + "github.com/ciscoecosystem/mso-go-client/models" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" +) + +func resourceMSOMacsecPolicy() *schema.Resource { + return &schema.Resource{ + Create: resourceMSOMacsecPolicyCreate, + Read: resourceMSOMacsecPolicyRead, + Update: resourceMSOMacsecPolicyUpdate, + Delete: resourceMSOMacsecPolicyDelete, + Importer: &schema.ResourceImporter{ + State: resourceMSOMacsecPolicyImport, + }, + + SchemaVersion: 1, + Schema: map[string]*schema.Schema{ + "template_id": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + "name": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 64), + }, + "description": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "uuid": { + Type: schema.TypeString, + Computed: true, + }, + "admin_state": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{ + "enabled", "disabled", + }, false), + }, + "interface_type": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{ + "fabric", "access", + }, false), + }, + "cipher_suite": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{ + "128GcmAes", "128GcmAesXpn", "256GcmAes", "256GcmAesXpn", + }, false), + }, + "window_size": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + "security_policy": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{ + "shouldSecure", "mustSecure", + }, false), + }, + "sak_expire_time": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + "confidentiality_offset": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{ + "offset0", "offset30", "offset50", + }, false), + }, + "key_server_priority": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + "macsec_key": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key_name": { + Type: schema.TypeString, + Required: true, + }, + "psk": { + Type: schema.TypeString, + Required: true, + }, + "start_time": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "end_time": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func setMacsecKeys(macsecKeyEntries *schema.Set) []map[string]any { + macsecKeyList := macsecKeyEntries.List() + macsecKeys := make([]map[string]any, 0, 1) + + for _, val := range macsecKeyList { + macsecKeyEntry := val.(map[string]any) + macsecKey := map[string]any{ + "keyname": macsecKeyEntry["key_name"].(string), + "psk": macsecKeyEntry["psk"].(string), + "start": macsecKeyEntry["start_time"].(string), + "end": macsecKeyEntry["end_time"].(string), + } + macsecKeys = append(macsecKeys, macsecKey) + } + + return macsecKeys +} + +func setMacsecPolicyData(d *schema.ResourceData, msoClient *client.Client, templateId, policyName string) error { + + response, err := msoClient.GetViaURL(fmt.Sprintf("api/v1/templates/%s", templateId)) + if err != nil { + return err + } + + policy, err := GetPolicyByName(response, policyName, "fabricPolicyTemplate", "template", "macsecPolicies") + if err != nil { + return err + } + + d.SetId(fmt.Sprintf("templateId/%s/macsecPolicy/%s", templateId, models.StripQuotes(policy.S("name").String()))) + d.Set("template_id", templateId) + d.Set("name", models.StripQuotes(policy.S("name").String())) + d.Set("description", models.StripQuotes(policy.S("description").String())) + d.Set("uuid", models.StripQuotes(policy.S("uuid").String())) + d.Set("admin_state", models.StripQuotes(policy.S("adminState").String())) + d.Set("interface_type", models.StripQuotes(policy.S("type").String())) + d.Set("cipher_suite", models.StripQuotes(policy.S("macsecParams", "cipherSuite").String())) + d.Set("window_size", policy.S("macsecParams", "windowSize").Data().(float64)) + d.Set("security_policy", models.StripQuotes(policy.S("macsecParams", "securityPol").String())) + d.Set("sak_expire_time", policy.S("macsecParams", "sakExpiryTime").Data().(float64)) + d.Set("confidentiality_offset", models.StripQuotes(policy.S("macsecParams", "confOffSet").String())) + d.Set("key_server_priority", policy.S("macsecParams", "keyServerPrio").Data().(float64)) + + count, err := policy.ArrayCount("macsecKeys") + if err != nil { + return fmt.Errorf("unable to count the number of macsec keys: %s", err) + } + macsecKeys := make([]any, 0) + for i := range count { + macsecKeysCont, err := policy.ArrayElement(i, "macsecKeys") + if err != nil { + return fmt.Errorf("unable to parse element %d from the list of macsec keys: %s", i, err) + } + macsecKeyEntry := make(map[string]any) + macsecKeyEntry["key_name"] = models.StripQuotes(macsecKeysCont.S("keyname").String()) + macsecKeyEntry["psk"] = models.StripQuotes(macsecKeysCont.S("psk").String()) + macsecKeyEntry["start_time"] = models.StripQuotes(macsecKeysCont.S("start").String()) + macsecKeyEntry["end_time"] = models.StripQuotes(macsecKeysCont.S("end").String()) + macsecKeys = append(macsecKeys, macsecKeyEntry) + } + d.Set("macsec_key", macsecKeys) + + return nil + +} + +func resourceMSOMacsecPolicyImport(d *schema.ResourceData, m any) ([]*schema.ResourceData, error) { + log.Printf("[DEBUG] MSO MACSec Policy Resource - Beginning Import: %v", d.Id()) + msoClient := m.(*client.Client) + + templateId, err := GetTemplateIdFromResourceId(d.Id()) + if err != nil { + return nil, err + } + + policyName, err := GetPolicyNameFromResourceId(d.Id(), "macsecPolicy") + if err != nil { + return nil, err + } + + setMacsecPolicyData(d, msoClient, templateId, policyName) + log.Printf("[DEBUG] MSO MACSec Policy Resource - Import Complete: %v", d.Id()) + return []*schema.ResourceData{d}, nil +} + +func resourceMSOMacsecPolicyCreate(d *schema.ResourceData, m any) error { + log.Printf("[DEBUG] MSO MACSec Policy Resource - Beginning Create: %v", d.Id()) + msoClient := m.(*client.Client) + + payload := map[string]any{} + + payload["name"] = d.Get("name").(string) + + if description, ok := d.GetOk("description"); ok { + payload["description"] = description.(string) + } + + if adminState, ok := d.GetOk("admin_state"); ok { + payload["adminState"] = adminState.(string) + } + + if interfaceType, ok := d.GetOk("interface_type"); ok { + payload["type"] = interfaceType.(string) + } + + macsecParams := make(map[string]any) + + if cipherSuite, ok := d.GetOk("cipher_suite"); ok { + macsecParams["cipherSuite"] = cipherSuite.(string) + } + + if windowSize, ok := d.GetOk("window_size"); ok { + macsecParams["windowSize"] = windowSize.(int) + } + + if securityPol, ok := d.GetOk("security_policy"); ok { + macsecParams["securityPol"] = securityPol.(string) + } + if sakExpiryTime, ok := d.GetOk("sak_expire_time"); ok { + macsecParams["sakExpiryTime"] = sakExpiryTime.(int) + } + + if confOffSet, ok := d.GetOk("confidentiality_offset"); ok { + macsecParams["confOffSet"] = confOffSet.(string) + } + + if keyServerPrio, ok := d.GetOk("key_server_priority"); ok { + macsecParams["keyServerPrio"] = keyServerPrio.(int) + } + + if len(macsecParams) > 0 { + payload["macsecParams"] = macsecParams + } + + if macsecKeyEntries, ok := d.GetOk("macsec_key"); ok { + payload["macsecKeys"] = setMacsecKeys(macsecKeyEntries.(*schema.Set)) + } + + payloadModel := models.GetPatchPayload("add", "/fabricPolicyTemplate/template/macsecPolicies/-", payload) + templateId := d.Get("template_id").(string) + + _, err := msoClient.PatchbyID(fmt.Sprintf("api/v1/templates/%s", templateId), payloadModel) + if err != nil { + return err + } + + d.SetId(fmt.Sprintf("templateId/%s/macsecPolicy/%s", templateId, d.Get("name").(string))) + log.Printf("[DEBUG] MSO MACSec Policy Resource - Create Complete: %v", d.Id()) + return resourceMSOMacsecPolicyRead(d, m) +} + +func resourceMSOMacsecPolicyRead(d *schema.ResourceData, m any) error { + log.Printf("[DEBUG] MSO MACSec Policy Resource - Beginning Read: %v", d.Id()) + msoClient := m.(*client.Client) + + templateId := d.Get("template_id").(string) + policyName := d.Get("name").(string) + + setMacsecPolicyData(d, msoClient, templateId, policyName) + log.Printf("[DEBUG] MSO MACSec Policy Resource - Read Complete : %v", d.Id()) + return nil +} + +func resourceMSOMacsecPolicyUpdate(d *schema.ResourceData, m any) error { + log.Printf("[DEBUG] MSO MACSec Policy Resource - Beginning Update: %v", d.Id()) + msoClient := m.(*client.Client) + templateId := d.Get("template_id").(string) + + templateCont, err := msoClient.GetViaURL(fmt.Sprintf("api/v1/templates/%s", templateId)) + if err != nil { + return err + } + + policyIndex, err := GetPolicyIndexByKeyAndValue(templateCont, "uuid", d.Get("uuid").(string), "fabricPolicyTemplate", "template", "macsecPolicies") + if err != nil { + return err + } + + updatePath := fmt.Sprintf("/fabricPolicyTemplate/template/macsecPolicies/%d", policyIndex) + + payloadCont := container.New() + payloadCont.Array() + if d.HasChange("name") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/name", updatePath), d.Get("name").(string)) + if err != nil { + return err + } + } + + if d.HasChange("description") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/description", updatePath), d.Get("description").(string)) + if err != nil { + return err + } + } + + if d.HasChange("admin_state") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/adminState", updatePath), d.Get("admin_state").(string)) + if err != nil { + return err + } + } + + if d.HasChange("interface_type") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/type", updatePath), d.Get("interface_type").(string)) + if err != nil { + return err + } + } + + if d.HasChange("cipher_suite") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/macsecParams/cipherSuite", updatePath), d.Get("cipher_suite").(string)) + if err != nil { + return err + } + } + + if d.HasChange("window_size") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/macsecParams/windowSize", updatePath), d.Get("window_size").(int)) + if err != nil { + return err + } + } + + if d.HasChange("security_policy") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/macsecParams/securityPol", updatePath), d.Get("security_policy").(string)) + if err != nil { + return err + } + } + + if d.HasChange("sak_expire_time") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/macsecParams/sakExpiryTime", updatePath), d.Get("sak_expire_time").(int)) + if err != nil { + return err + } + } + + if d.HasChange("confidentiality_offset") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/macsecParams/confOffSet", updatePath), d.Get("confidentiality_offset").(string)) + if err != nil { + return err + } + } + + if d.HasChange("key_server_priority") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/macsecParams/keyServerPrio", updatePath), d.Get("key_server_priority").(int)) + if err != nil { + return err + } + } + + if d.HasChange("macsec_key") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/macsecKeys", updatePath), setMacsecKeys(d.Get("vlan_range").(*schema.Set))) + if err != nil { + return err + } + } + + err = doPatchRequest(msoClient, fmt.Sprintf("api/v1/templates/%s", templateId), payloadCont) + if err != nil { + return err + } + + d.SetId(fmt.Sprintf("templateId/%s/macsecPolicy/%s", templateId, d.Get("name").(string))) + log.Printf("[DEBUG] MSO MACSec Policy Resource - Update Complete: %v", d.Id()) + return resourceMSOMacsecPolicyRead(d, m) +} + +func resourceMSOMacsecPolicyDelete(d *schema.ResourceData, m any) error { + log.Printf("[DEBUG] MSO MACSec Policy Resource - Beginning Delete: %v", d.Id()) + msoClient := m.(*client.Client) + + templateCont, err := msoClient.GetViaURL(fmt.Sprintf("api/v1/templates/%s", d.Get("template_id").(string))) + if err != nil { + return err + } + + policyIndex, err := GetPolicyIndexByKeyAndValue(templateCont, "uuid", d.Get("uuid").(string), "fabricPolicyTemplate", "template", "macsecPolicies") + if err != nil { + return err + } + + payloadModel := models.GetRemovePatchPayload(fmt.Sprintf("/fabricPolicyTemplate/template/macsecPolicies/%d", policyIndex)) + + _, err = msoClient.PatchbyID(fmt.Sprintf("api/v1/templates/%s", d.Get("template_id").(string)), payloadModel) + if err != nil { + return err + } + + d.SetId("") + log.Printf("[DEBUG] MSO MACSec Policy Resource - Delete Complete: %v", d.Id()) + return nil +} diff --git a/mso/resource_mso_fabric_policies_macsec_policy_test.go b/mso/resource_mso_fabric_policies_macsec_policy_test.go new file mode 100644 index 00000000..3a3d02d2 --- /dev/null +++ b/mso/resource_mso_fabric_policies_macsec_policy_test.go @@ -0,0 +1,224 @@ +package mso + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccMSOMacsecPolicyResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: Create MACsec Policy") }, + Config: testAccMSOMacsecPolicyConfigCreate(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "name", "tf_test_macsec_policy"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "description", "Terraform test MACsec Policy"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "admin_state", "enabled"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "interface_type", "access"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "cipher_suite", "256GcmAes"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "window_size", "128"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "security_policy", "shouldSecure"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "sak_expire_time", "60"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "confidentiality_offset", "offset30"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "key_server_priority", "8"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key.#", "1"), + customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key", + map[string]string{ + "key_name": "abc123", + "psk": "AA111111111111111111111111111111111111111111111111111111111111aa", + "start_time": "2027-09-23 00:00:00", + "end_time": "2030-09-23 00:00:00", + }, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update MACsec Policy adding extra MACsec Key") }, + Config: testAccMSOMacsecPolicyConfigUpdateAddingExtraMacSecKey(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "name", "tf_test_macsec_policy"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "description", "Terraform test MACsec Policy adding extra MACsec Key"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "admin_state", "enabled"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "interface_type", "access"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "cipher_suite", "256GcmAes"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "window_size", "128"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "security_policy", "shouldSecure"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "sak_expire_time", "60"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "confidentiality_offset", "offset30"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "key_server_priority", "8"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key.#", "2"), + customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key", + map[string]string{ + "key_name": "abc123", + "psk": "AA111111111111111111111111111111111111111111111111111111111111aa", + "start_time": "2027-09-23 00:00:00", + "end_time": "2030-09-23 00:00:00", + }, + ), + customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key", + map[string]string{ + "key_name": "def456", + "psk": "AA11111111111111111111111111111111111111111111111111111111111aaa", + "start_time": "2029-12-11 11:12:13", + "end_time": "2030-12-11 11:12:13", + }, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update MACsec Policy removing extra MACsec Key") }, + Config: testAccMSOMacsecPolicyConfigUpdateRemovingExtraMacSecKey(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "admin_state", "enabled"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "interface_type", "access"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "cipher_suite", "256GcmAes"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "window_size", "128"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "security_policy", "shouldSecure"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "sak_expire_time", "60"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "confidentiality_offset", "offset30"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "key_server_priority", "8"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key.#", "1"), + customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key", + map[string]string{ + "key_name": "abc123", + "psk": "AA111111111111111111111111111111111111111111111111111111111111aa", + "start_time": "2027-09-23 00:00:00", + "end_time": "2030-09-23 00:00:00", + }, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update MACsec Policy changing the interface type") }, + Config: testAccMSOMacsecPolicyConfigUpdateChangingType(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "admin_state", "enabled"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "interface_type", "fabric"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "cipher_suite", "256GcmAesXpn"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "window_size", "256"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "security_policy", "mustSecure"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "sak_expire_time", "120"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "confidentiality_offset", "offset30"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "key_server_priority", "8"), + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key.#", "1"), + customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key", + map[string]string{ + "key_name": "abc123", + "psk": "AA111111111111111111111111111111111111111111111111111111111111ab", + "start_time": "2028-12-12 12:12:12", + "end_time": "infinite", + }, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Import MACsec Policy") }, + ResourceName: "mso_fabric_policies_macsec_policy.macsec_policy", + ImportState: true, + ImportStateVerify: true, + }, + }, + CheckDestroy: testCheckResourceDestroyPolicyWithPathAttributesAndArguments("mso_fabric_policies_macsec_policy", "fabricPolicyTemplate", "template", "macsecPolicies"), + }) +} + +func testAccMSOMacsecPolicyConfigCreate() string { + return fmt.Sprintf(`%s + resource "mso_fabric_policies_macsec_policy" "macsec_policy" { + template_id = mso_template.template_fabric_policy.id + name = "tf_test_macsec_policy" + description = "Terraform test MACsec Policy" + admin_state = "enabled" + interface_type = "access" + cipher_suite = "256GcmAes" + window_size = 128 + security_policy = "shouldSecure" + sak_expire_time = 60 + confidentiality_offset = "offset30" + key_server_priority = 8 + macsec_key { + key_name = "abc123" + psk = "AA111111111111111111111111111111111111111111111111111111111111aa" + start_time = "2027-09-23 00:00:00" + end_time = "2030-09-23 00:00:00" + } + }`, testAccMSOTemplateResourceFabricPolicyConfig()) +} + +func testAccMSOMacsecPolicyConfigUpdateAddingExtraMacSecKey() string { + return fmt.Sprintf(`%s + resource "mso_fabric_policies_macsec_policy" "macsec_policy" { + template_id = mso_template.template_fabric_policy.id + name = "tf_test_macsec_policy" + description = "Terraform test MACsec Policy adding extra MACsec Key" + admin_state = "enabled" + interface_type = "access" + cipher_suite = "256GcmAes" + window_size = 128 + security_policy = "shouldSecure" + sak_expire_time = 60 + confidentiality_offset = "offset30" + key_server_priority = 8 + macsec_key { + key_name = "abc123" + psk = "AA111111111111111111111111111111111111111111111111111111111111aa" + start_time = "2027-09-23 00:00:00" + end_time = "2030-09-23 00:00:00" + } + macsec_key { + key_name = "def456" + psk = "AA11111111111111111111111111111111111111111111111111111111111aaa" + start_time = "2029-12-11 11:12:13" + end_time = "2030-12-11 11:12:13" + } + }`, testAccMSOTemplateResourceFabricPolicyConfig()) +} + +func testAccMSOMacsecPolicyConfigUpdateRemovingExtraMacSecKey() string { + return fmt.Sprintf(`%s + resource "mso_fabric_policies_macsec_policy" "macsec_policy" { + template_id = mso_template.template_fabric_policy.id + name = "tf_test_macsec_policy" + description = "Terraform test MACsec Policy removing extra MACsec Key" + admin_state = "enabled" + interface_type = "access" + cipher_suite = "256GcmAes" + window_size = 128 + security_policy = "shouldSecure" + sak_expire_time = 60 + confidentiality_offset = "offset30" + key_server_priority = 8 + macsec_key { + key_name = "abc123" + psk = "AA111111111111111111111111111111111111111111111111111111111111aa" + start_time = "2027-09-23 00:00:00" + end_time = "2030-09-23 00:00:00" + } + }`, testAccMSOTemplateResourceFabricPolicyConfig()) +} + +func testAccMSOMacsecPolicyConfigUpdateChangingType() string { + return fmt.Sprintf(`%s + resource "mso_fabric_policies_macsec_policy" "macsec_policy" { + template_id = mso_template.template_fabric_policy.id + name = "tf_test_macsec_policy" + description = "Terraform test MACsec Policy changing interface type" + admin_state = "disabled" + interface_type = "fabric" + cipher_suite = "256GcmAesXpn" + window_size = 256 + security_policy = "mustSecure" + sak_expire_time = 120 + macsec_key { + key_name = "abc123" + psk = "AA111111111111111111111111111111111111111111111111111111111111ab" + start_time = "2028-12-12 12:12:12" + end_time = "infinite" + } + }`, testAccMSOTemplateResourceFabricPolicyConfig()) +} diff --git a/website/docs/d/fabric_policies_macsec_policy.html.markdown b/website/docs/d/fabric_policies_macsec_policy.html.markdown new file mode 100644 index 00000000..02f66254 --- /dev/null +++ b/website/docs/d/fabric_policies_macsec_policy.html.markdown @@ -0,0 +1,49 @@ +--- +layout: "mso" +page_title: "MSO: mso_fabric_policies_macsec_policy" +sidebar_current: "docs-mso-data-source-fabric_policies_macsec_policy" +description: |- + Data source for MACsec Policies on Cisco Nexus Dashboard Orchestrator (NDO) +--- + + + +# mso_fabric_policies_macsec_policy # + +Data source for MACsec Policies on Cisco Nexus Dashboard Orchestrator (NDO). This data source is supported in NDO v4.3(1) or higher. + +## GUI Information ## + +* `Location` - Manage -> Fabric Template -> Fabric Policies -> MACsec + +## Example Usage ## + +```hcl +data "mso_fabric_policies_macsec_policy" "macsec_policy" { + template_id = mso_template.fabric_policy_template.id + name = "macsec_policy" +} +``` + +## Argument Reference ## + +* `template_id` - (Required) The unique ID of the Fabric Policy template. +* `name` - (Required) The name of the MACsec Policy. + +## Attribute Reference ## + +* `uuid` - (Read-Only) The NDO UUID of the MACsec Policy. +* `id` - (Read-Only) The unique Terraform identifier of the MACsec Policy. +* `description` - (Read-Only) The description of the MACsec Policy. +* `admin_state` - (Read-Only) The administrative state of the MACsec Policy. +* `interface_type` - (Read-Only) The type of the interfaces the MACsec Policy will be applied to. +* `cipher_suite` - (Read-Only) The cipher suite of the MACsec Policy to be used for encryption. +* `window_size` - (Read-Only) The window size of the MACsec Policy. It defines the maximum number of frames that can be received out of order before a replay attack is detected. +* `security_policy` - (Read-Only) The security policy to allow traffic on the link for the MACsec Policy. +* `sak_expire_time` - (Read-Only) The expiry time for the Security Association Key (SAK) for the MACsec Policy. +* `confidentiality_offset` - (Read-Only) The confidentiality offset for the MACsec Policy. +* `key_server_priority` - (Read-Only) The key server priority for the MACsec Policy. + * `macsec_key.key_name` - (Read-Only) The name of the MACsec Key. + * `macsec_key.psk` - (Read-Only) The Pre-Shared Key (PSK) for the MACsec Key. + * `macsec_key.start_time` - (Read-Only) The start time for the MACsec Key. + * `macsec_key.end_time` - (Read-Only) TThe end time for the MACsec Key. diff --git a/website/docs/r/fabric_policies_macsec_policy.html.markdown b/website/docs/r/fabric_policies_macsec_policy.html.markdown new file mode 100644 index 00000000..345ccdc9 --- /dev/null +++ b/website/docs/r/fabric_policies_macsec_policy.html.markdown @@ -0,0 +1,73 @@ +--- +layout: "mso" +page_title: "MSO: mso_fabric_policies_macsec_policy" +sidebar_current: "docs-mso-resource-fabric_policies_macsec_policy" +description: |- + Manages MACsec Policies on Cisco Nexus Dashboard Orchestrator (NDO) +--- + + + +# mso_fabric_policies_macsec_policy # + +Manages MACsec Policies on Cisco Nexus Dashboard Orchestrator (NDO). This resource is supported in NDO v4.3(1) or higher. + +## GUI Information ## + +* `Location` - Manage -> Fabric Template -> Fabric Policies -> MACsec + +## Example Usage ## + +```hcl +resource "mso_fabric_policies_macsec_policy" "macsec_policy" { + template_id = mso_template.fabric_policy_template.id + name = "macsec_policy" + description = "Example description" + admin_state = "enabled" + interface_type = "access" + cipher_suite = "256GcmAes" + window_size = 128 + security_policy = "shouldSecure" + sak_expire_time = 60 + confidentiality_offset = "offset30" + key_server_priority = 8 + macsec_key { + key_name = "abc123" + psk = "AA111111111111111111111111111111111111111111111111111111111111aa" + start_time = "now" + end_time = "2027-09-23 00:00:00" + } +} +``` + +## Argument Reference ## + +* `template_id` - (Required) The unique ID of the Fabric Policy template. +* `name` - (Required) The name of the MACsec Policy. +* `description` - (Optional) The description of the MACsec Policy. +* `admin_state` - (Optional) The administrative state of the MACsec Policy. Allowed values are `enabled` or `disabled`. Defaults to `enabled` when unset during creation. +* `interface_type` - (Optional) The type of the interfaces the MACsec Policy will be applied to. Allowed values are `fabric` or `access`. +* `cipher_suite` - (Optional) The cipher suite of the MACsec Policy to be used for encryption. Allowed values are `128GcmAes`, `128GcmAesXpn`, `256GcmAes` or `256GcmAesXpn`. Defaults to `enabled` when unset during creation. +* `window_size` - (Optional) The window size of the MACsec Policy. It defines the maximum number of frames that can be received out of order before a replay attack is detected. Valid range: 0-4294967295. Defaults to 0 for `fabric` type or to 64 for `access` type when unset during creation. +* `security_policy` - (Optional) The security policy to allow traffic on the link for the MACsec Policy. Allowed values are `shouldSecure` or `mustSecure`. Defaults to `shouldSecure` when unset during creation. +* `sak_expire_time` - (Optional) The expiry time for the Security Association Key (SAK) for the MACsec Policy. Allowed value is 0 or valid range: 60-2592000. Defaults to 0 when unset during creation. +* `confidentiality_offset` - (Optional) The confidentiality offset for the MACsec Policy. This paramater is only configurable for `access` type. Allowed values are `offset0`, `offset30` or `offset50`. Defaults to `offset0` when unset during creation. +* `key_server_priority` - (Optional) The key server priority for the MACsec Policy. This paramater is only configurable for `access` type. Valid range: 0-255. Defaults to 16 when unset during creation. +* `macsec_key` - (Optional) The list of MACsec Keys. + * `macsec_key.key_name` - (Required) The name of the MACsec Key. Key Name has to be hexadecimal characters [0-9a-fA-F]. + * `macsec_key.psk` - (Required) The Pre-Shared Key (PSK) for the MACsec Key. PSK has to be hexadecimal characters [0-9a-fA-F]. PSK has to be 64 characters long if cipher suite is `256GcmAes` or `256GcmAesXpn`. PSK has to be 32 characters long if cipher suite is `128GcmAes` or `128GcmAesXpn`. + * `macsec_key.start_time` - (Optional) The start time for the MACsec Key. Allowed values are of the following format `YYYY-MM-DD HH:MM:SS` or `now`. The start time for each Key should be unique. + * `macsec_key.end_time` - (Optional) TThe end time for the MACsec Key. Allowed values are of the following format `YYYY-MM-DD HH:MM:SS` or `infinite`. + +## Attribute Reference ## + +* `uuid` - (Read-Only) The NDO UUID of the MACsec Policy. +* `id` - (Read-Only) The unique Terraform identifier of the MACsec Policy. + +## Importing ## + +An existing MSO MACsec Policy can be [imported][docs-import] into this resource via its ID/path, via the following command: [docs-import]: + +```bash +terraform import mso_fabric_policies_macsec_policy.macsec_policy templateId/{template_id}/VlanPool/{name} +``` From eb3c5b84815d0c75e448452810c2d4fbe1ed858e Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Fri, 31 Oct 2025 10:36:01 -0400 Subject: [PATCH 2/5] [ignore] Change macsec_key attribute to macsec_keys. Fix Documentation issue for resource and data source. --- .../fabric_policies_macsec_policy/main.tf | 2 +- ...ource_mso_fabric_policies_macsec_policy.go | 2 +- ..._mso_fabric_policies_macsec_policy_test.go | 4 +-- ...ource_mso_fabric_policies_macsec_policy.go | 8 +++--- ..._mso_fabric_policies_macsec_policy_test.go | 28 +++++++++---------- ...abric_policies_macsec_policy.html.markdown | 1 + ...abric_policies_macsec_policy.html.markdown | 14 +++++----- 7 files changed, 30 insertions(+), 29 deletions(-) diff --git a/examples/fabric_policies_macsec_policy/main.tf b/examples/fabric_policies_macsec_policy/main.tf index 292f08bf..1d8aecc0 100644 --- a/examples/fabric_policies_macsec_policy/main.tf +++ b/examples/fabric_policies_macsec_policy/main.tf @@ -34,7 +34,7 @@ resource "mso_fabric_policies_macsec_policy" "macsec_policy" { sak_expire_time = 60 confidentiality_offset = "offset30" key_server_priority = 8 - macsec_key { + macsec_keys { key_name = "abc123" psk = "AA111111111111111111111111111111111111111111111111111111111111aa" start_time = "now" diff --git a/mso/datasource_mso_fabric_policies_macsec_policy.go b/mso/datasource_mso_fabric_policies_macsec_policy.go index b1bbdba1..e0518116 100644 --- a/mso/datasource_mso_fabric_policies_macsec_policy.go +++ b/mso/datasource_mso_fabric_policies_macsec_policy.go @@ -60,7 +60,7 @@ func datasourceMacsecPolicy() *schema.Resource { Type: schema.TypeInt, Computed: true, }, - "macsec_key": { + "macsec_keys": { Type: schema.TypeSet, Computed: true, Elem: &schema.Resource{ diff --git a/mso/datasource_mso_fabric_policies_macsec_policy_test.go b/mso/datasource_mso_fabric_policies_macsec_policy_test.go index 769ce150..6d782727 100644 --- a/mso/datasource_mso_fabric_policies_macsec_policy_test.go +++ b/mso/datasource_mso_fabric_policies_macsec_policy_test.go @@ -26,8 +26,8 @@ func TestAccMSOMacsecPolicyDataSource(t *testing.T) { resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "sak_expire_time", "60"), resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "confidentiality_offset", "offset30"), resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "key_server_priority", "8"), - resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key.#", "1"), - customTestCheckResourceTypeSetAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key", + resource.TestCheckResourceAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "macsec_keys.#", "1"), + customTestCheckResourceTypeSetAttr("data.mso_fabric_policies_macsec_policy.macsec_policy", "macsec_keys", map[string]string{ "key_name": "abc123", "psk": "AA111111111111111111111111111111111111111111111111111111111111aa", diff --git a/mso/resource_mso_fabric_policies_macsec_policy.go b/mso/resource_mso_fabric_policies_macsec_policy.go index d32da6c0..32daca68 100644 --- a/mso/resource_mso_fabric_policies_macsec_policy.go +++ b/mso/resource_mso_fabric_policies_macsec_policy.go @@ -98,7 +98,7 @@ func resourceMSOMacsecPolicy() *schema.Resource { Optional: true, Computed: true, }, - "macsec_key": { + "macsec_keys": { Type: schema.TypeSet, Optional: true, Computed: true, @@ -190,7 +190,7 @@ func setMacsecPolicyData(d *schema.ResourceData, msoClient *client.Client, templ macsecKeyEntry["end_time"] = models.StripQuotes(macsecKeysCont.S("end").String()) macsecKeys = append(macsecKeys, macsecKeyEntry) } - d.Set("macsec_key", macsecKeys) + d.Set("macsec_keys", macsecKeys) return nil @@ -264,7 +264,7 @@ func resourceMSOMacsecPolicyCreate(d *schema.ResourceData, m any) error { payload["macsecParams"] = macsecParams } - if macsecKeyEntries, ok := d.GetOk("macsec_key"); ok { + if macsecKeyEntries, ok := d.GetOk("macsec_keys"); ok { payload["macsecKeys"] = setMacsecKeys(macsecKeyEntries.(*schema.Set)) } @@ -382,7 +382,7 @@ func resourceMSOMacsecPolicyUpdate(d *schema.ResourceData, m any) error { } } - if d.HasChange("macsec_key") { + if d.HasChange("macsec_keys") { err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/macsecKeys", updatePath), setMacsecKeys(d.Get("vlan_range").(*schema.Set))) if err != nil { return err diff --git a/mso/resource_mso_fabric_policies_macsec_policy_test.go b/mso/resource_mso_fabric_policies_macsec_policy_test.go index 3a3d02d2..9ccdea67 100644 --- a/mso/resource_mso_fabric_policies_macsec_policy_test.go +++ b/mso/resource_mso_fabric_policies_macsec_policy_test.go @@ -26,8 +26,8 @@ func TestAccMSOMacsecPolicyResource(t *testing.T) { resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "sak_expire_time", "60"), resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "confidentiality_offset", "offset30"), resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "key_server_priority", "8"), - resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key.#", "1"), - customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key", + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_keys.#", "1"), + customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_keys", map[string]string{ "key_name": "abc123", "psk": "AA111111111111111111111111111111111111111111111111111111111111aa", @@ -51,8 +51,8 @@ func TestAccMSOMacsecPolicyResource(t *testing.T) { resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "sak_expire_time", "60"), resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "confidentiality_offset", "offset30"), resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "key_server_priority", "8"), - resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key.#", "2"), - customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key", + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_keys.#", "2"), + customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_keys", map[string]string{ "key_name": "abc123", "psk": "AA111111111111111111111111111111111111111111111111111111111111aa", @@ -60,7 +60,7 @@ func TestAccMSOMacsecPolicyResource(t *testing.T) { "end_time": "2030-09-23 00:00:00", }, ), - customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key", + customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_keys", map[string]string{ "key_name": "def456", "psk": "AA11111111111111111111111111111111111111111111111111111111111aaa", @@ -82,8 +82,8 @@ func TestAccMSOMacsecPolicyResource(t *testing.T) { resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "sak_expire_time", "60"), resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "confidentiality_offset", "offset30"), resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "key_server_priority", "8"), - resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key.#", "1"), - customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key", + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_keys.#", "1"), + customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_keys", map[string]string{ "key_name": "abc123", "psk": "AA111111111111111111111111111111111111111111111111111111111111aa", @@ -105,8 +105,8 @@ func TestAccMSOMacsecPolicyResource(t *testing.T) { resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "sak_expire_time", "120"), resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "confidentiality_offset", "offset30"), resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "key_server_priority", "8"), - resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key.#", "1"), - customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_key", + resource.TestCheckResourceAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_keys.#", "1"), + customTestCheckResourceTypeSetAttr("mso_fabric_policies_macsec_policy.macsec_policy", "macsec_keys", map[string]string{ "key_name": "abc123", "psk": "AA111111111111111111111111111111111111111111111111111111111111ab", @@ -141,7 +141,7 @@ func testAccMSOMacsecPolicyConfigCreate() string { sak_expire_time = 60 confidentiality_offset = "offset30" key_server_priority = 8 - macsec_key { + macsec_keys { key_name = "abc123" psk = "AA111111111111111111111111111111111111111111111111111111111111aa" start_time = "2027-09-23 00:00:00" @@ -164,13 +164,13 @@ func testAccMSOMacsecPolicyConfigUpdateAddingExtraMacSecKey() string { sak_expire_time = 60 confidentiality_offset = "offset30" key_server_priority = 8 - macsec_key { + macsec_keys { key_name = "abc123" psk = "AA111111111111111111111111111111111111111111111111111111111111aa" start_time = "2027-09-23 00:00:00" end_time = "2030-09-23 00:00:00" } - macsec_key { + macsec_keys { key_name = "def456" psk = "AA11111111111111111111111111111111111111111111111111111111111aaa" start_time = "2029-12-11 11:12:13" @@ -193,7 +193,7 @@ func testAccMSOMacsecPolicyConfigUpdateRemovingExtraMacSecKey() string { sak_expire_time = 60 confidentiality_offset = "offset30" key_server_priority = 8 - macsec_key { + macsec_keys { key_name = "abc123" psk = "AA111111111111111111111111111111111111111111111111111111111111aa" start_time = "2027-09-23 00:00:00" @@ -214,7 +214,7 @@ func testAccMSOMacsecPolicyConfigUpdateChangingType() string { window_size = 256 security_policy = "mustSecure" sak_expire_time = 120 - macsec_key { + macsec_keys { key_name = "abc123" psk = "AA111111111111111111111111111111111111111111111111111111111111ab" start_time = "2028-12-12 12:12:12" diff --git a/website/docs/d/fabric_policies_macsec_policy.html.markdown b/website/docs/d/fabric_policies_macsec_policy.html.markdown index 02f66254..38fcec56 100644 --- a/website/docs/d/fabric_policies_macsec_policy.html.markdown +++ b/website/docs/d/fabric_policies_macsec_policy.html.markdown @@ -43,6 +43,7 @@ data "mso_fabric_policies_macsec_policy" "macsec_policy" { * `sak_expire_time` - (Read-Only) The expiry time for the Security Association Key (SAK) for the MACsec Policy. * `confidentiality_offset` - (Read-Only) The confidentiality offset for the MACsec Policy. * `key_server_priority` - (Read-Only) The key server priority for the MACsec Policy. +* `macsec_keys` - (Read-Only) The list of MACsec Keys. * `macsec_key.key_name` - (Read-Only) The name of the MACsec Key. * `macsec_key.psk` - (Read-Only) The Pre-Shared Key (PSK) for the MACsec Key. * `macsec_key.start_time` - (Read-Only) The start time for the MACsec Key. diff --git a/website/docs/r/fabric_policies_macsec_policy.html.markdown b/website/docs/r/fabric_policies_macsec_policy.html.markdown index 345ccdc9..3e565814 100644 --- a/website/docs/r/fabric_policies_macsec_policy.html.markdown +++ b/website/docs/r/fabric_policies_macsec_policy.html.markdown @@ -31,7 +31,7 @@ resource "mso_fabric_policies_macsec_policy" "macsec_policy" { sak_expire_time = 60 confidentiality_offset = "offset30" key_server_priority = 8 - macsec_key { + macsec_keys { key_name = "abc123" psk = "AA111111111111111111111111111111111111111111111111111111111111aa" start_time = "now" @@ -53,11 +53,11 @@ resource "mso_fabric_policies_macsec_policy" "macsec_policy" { * `sak_expire_time` - (Optional) The expiry time for the Security Association Key (SAK) for the MACsec Policy. Allowed value is 0 or valid range: 60-2592000. Defaults to 0 when unset during creation. * `confidentiality_offset` - (Optional) The confidentiality offset for the MACsec Policy. This paramater is only configurable for `access` type. Allowed values are `offset0`, `offset30` or `offset50`. Defaults to `offset0` when unset during creation. * `key_server_priority` - (Optional) The key server priority for the MACsec Policy. This paramater is only configurable for `access` type. Valid range: 0-255. Defaults to 16 when unset during creation. -* `macsec_key` - (Optional) The list of MACsec Keys. - * `macsec_key.key_name` - (Required) The name of the MACsec Key. Key Name has to be hexadecimal characters [0-9a-fA-F]. - * `macsec_key.psk` - (Required) The Pre-Shared Key (PSK) for the MACsec Key. PSK has to be hexadecimal characters [0-9a-fA-F]. PSK has to be 64 characters long if cipher suite is `256GcmAes` or `256GcmAesXpn`. PSK has to be 32 characters long if cipher suite is `128GcmAes` or `128GcmAesXpn`. - * `macsec_key.start_time` - (Optional) The start time for the MACsec Key. Allowed values are of the following format `YYYY-MM-DD HH:MM:SS` or `now`. The start time for each Key should be unique. - * `macsec_key.end_time` - (Optional) TThe end time for the MACsec Key. Allowed values are of the following format `YYYY-MM-DD HH:MM:SS` or `infinite`. +* `macsec_keys` - (Optional) The list of MACsec Keys. + * `macsec_keys.key_name` - (Required) The name of the MACsec Key. Key Name has to be hexadecimal characters [0-9a-fA-F]. + * `macsec_keys.psk` - (Required) The Pre-Shared Key (PSK) for the MACsec Key. PSK has to be hexadecimal characters [0-9a-fA-F]. PSK has to be 64 characters long if cipher suite is `256GcmAes` or `256GcmAesXpn`. PSK has to be 32 characters long if cipher suite is `128GcmAes` or `128GcmAesXpn`. + * `macsec_keys.start_time` - (Optional) The start time for the MACsec Key. Allowed values are of the following format `YYYY-MM-DD HH:MM:SS` or `now`. The start time for each Key should be unique. + * `macsec_keys.end_time` - (Optional) TThe end time for the MACsec Key. Allowed values are of the following format `YYYY-MM-DD HH:MM:SS` or `infinite`. ## Attribute Reference ## @@ -69,5 +69,5 @@ resource "mso_fabric_policies_macsec_policy" "macsec_policy" { An existing MSO MACsec Policy can be [imported][docs-import] into this resource via its ID/path, via the following command: [docs-import]: ```bash -terraform import mso_fabric_policies_macsec_policy.macsec_policy templateId/{template_id}/VlanPool/{name} +terraform import mso_fabric_policies_macsec_policy.macsec_policy templateId/{template_id}/macsecPolicy/{name} ``` From 44f0f61f43f90baaa3193e1c355935636748e1b4 Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Mon, 3 Nov 2025 11:29:32 -0500 Subject: [PATCH 3/5] [ignore] Fix identation issues. --- examples/fabric_policies_macsec_policy/main.tf | 2 +- website/docs/r/fabric_policies_macsec_policy.html.markdown | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/fabric_policies_macsec_policy/main.tf b/examples/fabric_policies_macsec_policy/main.tf index 1d8aecc0..f2637813 100644 --- a/examples/fabric_policies_macsec_policy/main.tf +++ b/examples/fabric_policies_macsec_policy/main.tf @@ -39,5 +39,5 @@ resource "mso_fabric_policies_macsec_policy" "macsec_policy" { psk = "AA111111111111111111111111111111111111111111111111111111111111aa" start_time = "now" end_time = "2027-09-23 00:00:00" - } + } } diff --git a/website/docs/r/fabric_policies_macsec_policy.html.markdown b/website/docs/r/fabric_policies_macsec_policy.html.markdown index 3e565814..dcec90b5 100644 --- a/website/docs/r/fabric_policies_macsec_policy.html.markdown +++ b/website/docs/r/fabric_policies_macsec_policy.html.markdown @@ -36,7 +36,7 @@ resource "mso_fabric_policies_macsec_policy" "macsec_policy" { psk = "AA111111111111111111111111111111111111111111111111111111111111aa" start_time = "now" end_time = "2027-09-23 00:00:00" - } + } } ``` From 098edc44f7c85f270a5b94e8c3ae2cba3c750d3e Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Tue, 4 Nov 2025 13:51:20 -0500 Subject: [PATCH 4/5] [ignore] Modify small typo mistake in MACsec resource documentation. --- website/docs/r/fabric_policies_macsec_policy.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/r/fabric_policies_macsec_policy.html.markdown b/website/docs/r/fabric_policies_macsec_policy.html.markdown index dcec90b5..b16df514 100644 --- a/website/docs/r/fabric_policies_macsec_policy.html.markdown +++ b/website/docs/r/fabric_policies_macsec_policy.html.markdown @@ -51,8 +51,8 @@ resource "mso_fabric_policies_macsec_policy" "macsec_policy" { * `window_size` - (Optional) The window size of the MACsec Policy. It defines the maximum number of frames that can be received out of order before a replay attack is detected. Valid range: 0-4294967295. Defaults to 0 for `fabric` type or to 64 for `access` type when unset during creation. * `security_policy` - (Optional) The security policy to allow traffic on the link for the MACsec Policy. Allowed values are `shouldSecure` or `mustSecure`. Defaults to `shouldSecure` when unset during creation. * `sak_expire_time` - (Optional) The expiry time for the Security Association Key (SAK) for the MACsec Policy. Allowed value is 0 or valid range: 60-2592000. Defaults to 0 when unset during creation. -* `confidentiality_offset` - (Optional) The confidentiality offset for the MACsec Policy. This paramater is only configurable for `access` type. Allowed values are `offset0`, `offset30` or `offset50`. Defaults to `offset0` when unset during creation. -* `key_server_priority` - (Optional) The key server priority for the MACsec Policy. This paramater is only configurable for `access` type. Valid range: 0-255. Defaults to 16 when unset during creation. +* `confidentiality_offset` - (Optional) The confidentiality offset for the MACsec Policy. This parameter is only configurable for `access` type. Allowed values are `offset0`, `offset30` or `offset50`. Defaults to `offset0` when unset during creation. +* `key_server_priority` - (Optional) The key server priority for the MACsec Policy. This parameter is only configurable for `access` type. Valid range: 0-255. Defaults to 16 when unset during creation. * `macsec_keys` - (Optional) The list of MACsec Keys. * `macsec_keys.key_name` - (Required) The name of the MACsec Key. Key Name has to be hexadecimal characters [0-9a-fA-F]. * `macsec_keys.psk` - (Required) The Pre-Shared Key (PSK) for the MACsec Key. PSK has to be hexadecimal characters [0-9a-fA-F]. PSK has to be 64 characters long if cipher suite is `256GcmAes` or `256GcmAesXpn`. PSK has to be 32 characters long if cipher suite is `128GcmAes` or `128GcmAesXpn`. From d5d8c60b32710b919a12ab8066d93b7297137dab Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Wed, 5 Nov 2025 13:49:41 -0500 Subject: [PATCH 5/5] [ignore] Fix attributes description in MACsec resource and data source Documentation. --- .../docs/d/fabric_policies_macsec_policy.html.markdown | 2 +- .../docs/r/fabric_policies_macsec_policy.html.markdown | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/website/docs/d/fabric_policies_macsec_policy.html.markdown b/website/docs/d/fabric_policies_macsec_policy.html.markdown index 38fcec56..ba651163 100644 --- a/website/docs/d/fabric_policies_macsec_policy.html.markdown +++ b/website/docs/d/fabric_policies_macsec_policy.html.markdown @@ -47,4 +47,4 @@ data "mso_fabric_policies_macsec_policy" "macsec_policy" { * `macsec_key.key_name` - (Read-Only) The name of the MACsec Key. * `macsec_key.psk` - (Read-Only) The Pre-Shared Key (PSK) for the MACsec Key. * `macsec_key.start_time` - (Read-Only) The start time for the MACsec Key. - * `macsec_key.end_time` - (Read-Only) TThe end time for the MACsec Key. + * `macsec_key.end_time` - (Read-Only) The end time for the MACsec Key. diff --git a/website/docs/r/fabric_policies_macsec_policy.html.markdown b/website/docs/r/fabric_policies_macsec_policy.html.markdown index b16df514..1d5483ad 100644 --- a/website/docs/r/fabric_policies_macsec_policy.html.markdown +++ b/website/docs/r/fabric_policies_macsec_policy.html.markdown @@ -47,17 +47,17 @@ resource "mso_fabric_policies_macsec_policy" "macsec_policy" { * `description` - (Optional) The description of the MACsec Policy. * `admin_state` - (Optional) The administrative state of the MACsec Policy. Allowed values are `enabled` or `disabled`. Defaults to `enabled` when unset during creation. * `interface_type` - (Optional) The type of the interfaces the MACsec Policy will be applied to. Allowed values are `fabric` or `access`. -* `cipher_suite` - (Optional) The cipher suite of the MACsec Policy to be used for encryption. Allowed values are `128GcmAes`, `128GcmAesXpn`, `256GcmAes` or `256GcmAesXpn`. Defaults to `enabled` when unset during creation. +* `cipher_suite` - (Optional) The cipher suite of the MACsec Policy to be used for encryption. Allowed values are `128GcmAes`, `128GcmAesXpn`, `256GcmAes` or `256GcmAesXpn`. Defaults to `256GcmAesXpn` when unset during creation. * `window_size` - (Optional) The window size of the MACsec Policy. It defines the maximum number of frames that can be received out of order before a replay attack is detected. Valid range: 0-4294967295. Defaults to 0 for `fabric` type or to 64 for `access` type when unset during creation. * `security_policy` - (Optional) The security policy to allow traffic on the link for the MACsec Policy. Allowed values are `shouldSecure` or `mustSecure`. Defaults to `shouldSecure` when unset during creation. * `sak_expire_time` - (Optional) The expiry time for the Security Association Key (SAK) for the MACsec Policy. Allowed value is 0 or valid range: 60-2592000. Defaults to 0 when unset during creation. * `confidentiality_offset` - (Optional) The confidentiality offset for the MACsec Policy. This parameter is only configurable for `access` type. Allowed values are `offset0`, `offset30` or `offset50`. Defaults to `offset0` when unset during creation. * `key_server_priority` - (Optional) The key server priority for the MACsec Policy. This parameter is only configurable for `access` type. Valid range: 0-255. Defaults to 16 when unset during creation. * `macsec_keys` - (Optional) The list of MACsec Keys. - * `macsec_keys.key_name` - (Required) The name of the MACsec Key. Key Name has to be hexadecimal characters [0-9a-fA-F]. - * `macsec_keys.psk` - (Required) The Pre-Shared Key (PSK) for the MACsec Key. PSK has to be hexadecimal characters [0-9a-fA-F]. PSK has to be 64 characters long if cipher suite is `256GcmAes` or `256GcmAesXpn`. PSK has to be 32 characters long if cipher suite is `128GcmAes` or `128GcmAesXpn`. + * `macsec_keys.key_name` - (Required) The name of the MACsec Key. Key Name should contain hexadecimal characters [0-9a-fA-F]. + * `macsec_keys.psk` - (Required) The Pre-Shared Key (PSK) for the MACsec Key. PSK should contain hexadecimal characters [0-9a-fA-F]. PSK should be 64 characters long if cipher suite is `256GcmAes` or `256GcmAesXpn`. PSK should be 32 characters long if cipher suite is `128GcmAes` or `128GcmAesXpn`. * `macsec_keys.start_time` - (Optional) The start time for the MACsec Key. Allowed values are of the following format `YYYY-MM-DD HH:MM:SS` or `now`. The start time for each Key should be unique. - * `macsec_keys.end_time` - (Optional) TThe end time for the MACsec Key. Allowed values are of the following format `YYYY-MM-DD HH:MM:SS` or `infinite`. + * `macsec_keys.end_time` - (Optional) The end time for the MACsec Key. Allowed values are of the following format `YYYY-MM-DD HH:MM:SS` or `infinite`. ## Attribute Reference ##