diff --git a/plugins/modules/ndo_mac_sec_policy.py b/plugins/modules/ndo_mac_sec_policy.py index 9a579e19..08594842 100644 --- a/plugins/modules/ndo_mac_sec_policy.py +++ b/plugins/modules/ndo_mac_sec_policy.py @@ -46,9 +46,9 @@ admin_state: description: - The administrative state of the MACSec Policy. (Enables or disables the policy) + - The default value is enabled. type: str choices: [ enabled, disabled ] - default: enabled type: description: - The type of the interfaces this policy will be applied to. @@ -58,38 +58,39 @@ cipher_suite: description: - The cipher suite to be used for encryption. + - The default value is 256_gcm_aes_xpn. type: str choices: [ 128_gcm_aes, 128_gcm_aes_xpn, 256_gcm_aes, 256_gcm_aes_xpn ] - default: 256_gcm_aes_xpn window_size: description: - The window size for the MACSec Policy. + - The value must be between 0 and 4294967295. + - The default value is 0. type: int - default: 64 security_policy: description: - The security policy to allow trafic on the link for the MACSec Policy. + - The default value is should_secure. type: str choices: [ should_secure, must_secure ] - default: should_secure sak_expiry_time: description: - The expiry time for the Security Association Key (SAK) for the MACSec Policy. - - The value must be 0 or between 60 and 2592000 + - The value must be 0 or between 60 and 2592000. + - The default value is 0. type: int - default: 0 confidentiality_offset: description: - The confidentiality offset for the MACSec Policy. type: int choices: [0, 30, 50] - default: offset0 + default: 0 key_server_priority: description: - The key server priority for the MACSec Policy. - - The value must be between 0 and 255 + - The value must be between 0 and 255. + - The default value is 0. type: int - default: 16 mac_sec_key: description: - List of the MACSec Keys. @@ -102,27 +103,25 @@ - Key Name has to be Hex chars [0-9a-fA-F] type: str required: true - psk: + psk: description: - The Pre-Shared Key (PSK) for the MACSec Key. - PSK has to be 64 chars long. - PSK has to be Hex chars [0-9a-fA-F] type: str required: true - start_time: + start_time: description: - The start time for the MACSec Key. - The date time format - YYYY-MM-DD HH:MM:SS or 'now' + - The default value is now. type: str - default: now - end_time: + end_time: description: - The end time for the MACSec Key. - The date time format - YYYY-MM-DD HH:MM:SS or 'infinite' + - The default value is infinite. type: str - default: infinite - - state: description: - Use C(absent) for removing. @@ -191,22 +190,22 @@ def main(): mac_sec_policy=dict(type="str", aliases=["name"]), mac_sec_policy_uuid=dict(type="str", aliases=["uuid"]), description=dict(type="str"), - admin_state=dict(type="str", choices=["enabled", "disabled"], default="enabled"), + admin_state=dict(type="str", choices=["enabled", "disabled"]), type=dict(type="str", choices=["fabric", "access"], default="fabric"), - cipher_suite=dict(type="str", choices=["128_gcm_aes", "128_gcm_aes_xpn", "256_gcm_aes", "256_gcm_aes_xpn"], default="256_gcm_aes_xpn"), - window_size=dict(type="int", default=64), - security_policy=dict(type="str", choices=["should_secure", "must_secure"], default="should_secure"), - sak_expiry_time=dict(type="int", default=0), + cipher_suite=dict(type="str", choices=["128_gcm_aes", "128_gcm_aes_xpn", "256_gcm_aes", "256_gcm_aes_xpn"]), + window_size=dict(type="int"), + security_policy=dict(type="str", choices=["should_secure", "must_secure"]), + sak_expiry_time=dict(type="int"), confidentiality_offset=dict(type="int", choices=[0, 30, 50], default=0), - key_server_priority=dict(type="int", default=16), + key_server_priority=dict(type="int"), mac_sec_key=dict( type="list", elements="dict", options=dict( key_name=dict(type="str", required=True), psk=dict(type="str", required=True), - start_time=dict(type="str", default="now"), - end_time=dict(type="str", default="infinite"), + start_time=dict(type="str"), + end_time=dict(type="str"), ), ), state=dict(type="str", choices=["absent", "query", "present"], default="query"), @@ -265,63 +264,102 @@ def main(): if state == "present": mso.existing = {} + mso.stdout += str("\n match ") + str(match) if match: - mso.stdout += str("\n match ") + str(match) if mac_sec_policy and match.details.get("name") != mac_sec_policy: - mso.fail_json( - msg=f"MACSec Policy '{match.details.get('name')}' already exists with a different name '{mac_sec_policy}'" - ) + ops.append(dict(op="replace", path="{0}/{1}/name".format(path, match.index), value=mac_sec_policy)) + match.details["name"] = mac_sec_policy if description and match.details.get("description") != description: - ops.append(mso_template.update_object_description(match, description)) + ops.append(dict(op="replace", path="{0}/{1}/description".format(path, match.index), value=description)) + match.details["description"] = description if admin_state and match.details.get("adminState") != admin_state: - ops.append(mso_template.update_object_admin_state(match, admin_state)) + ops.append(dict(op="replace", path="{0}/{1}/adminState".format(path, match.index), value=admin_state)) + match.details["adminState"] = admin_state if type and match.details.get("type") != type: - ops.append(mso_template.update_object_type(match, type)) + ops.append(dict(op="replace", path="{0}/{1}/type".format(path, match.index), value=type)) + match.details["type"] = type + if cipher_suite and match.details.get("macsecParams")["cipherSuite"] != cipher_suite: + ops.append(dict(op="replace", path="{0}/{1}/macsecParams/cipherSuite".format(path, match.index), value=NDO_CIPHER_SUITE_MAP.get(cipher_suite))) + match.details["macsecParams"]["cipherSuite"] = NDO_CIPHER_SUITE_MAP.get(cipher_suite) + if window_size and match.details.get("macsecParams")["windowSize"] != window_size: + ops.append(dict(op="replace", path="{0}/{1}/macsecParams/windowSize".format(path, match.index), value=window_size)) + match.details["macsecParams"]["windowSize"] = window_size - if cipher_suite and match.details.get("cipherSuite") != cipher_suite: - ops.append(mso_template.update_object_cipher_suite(match, cipher_suite)) + if security_policy and match.details.get("macsecParams")["securityPol"] != security_policy: + ops.append(dict(op="replace", path="{0}/{1}/macsecParams/securityPol".format(path, match.index), value=NDO_SECURITY_POLICY_MAP.get(security_policy))) + match.details["macsecParams"]["securityPol"] = NDO_SECURITY_POLICY_MAP.get(security_policy) - if window_size and match.details.get("windowSize") != window_size: - ops.append(mso_template.update_object_window_size(match, window_size)) + if sak_expiry_time and match.details.get("macsecParams")["sakExpiryTime"] != sak_expiry_time: + ops.append(dict(op="replace", path="{0}/{1}/macsecParams/sakExpiryTime".format(path, match.index), value=sak_expiry_time)) + match.details["macsecParams"]["sakExpiryTime"] = sak_expiry_time - if security_policy and match.details.get("securityPol") != security_policy: - ops.append(mso_template.update_object_security_policy(match, security_policy)) - - if sak_expiry_time and match.details.get("sakExpiryTime") != sak_expiry_time: - ops.append(mso_template.update_object_sak_expiry_time(match, sak_expiry_time)) - - if confidentiality_offset and match.details.get("confOffSet") != confidentiality_offset: - ops.append(mso_template.update_object_confidentiality_offset(match, confidentiality_offset)) - - if key_server_priority and match.details.get("keyServerPrio") != key_server_priority: - ops.append(mso_template.update_object_key_server_priority(match, key_server_priority)) + if type == "access": + mso.stdout += ("\n IN IF access") + if confidentiality_offset and match.details.get("macsecParams")["confOffSet"] != confidentiality_offset: + ops.append(dict(op="replace", path="{0}/{1}/macsecParams/confOffSet".format(path, match.index), value=confidentiality_offset)) + match.details["macsecParams"]["confOffSet"] = confidentiality_offset + + if key_server_priority and match.details.get("macsecParams")["keyServerPrio"] != key_server_priority: + ops.append(dict(op="replace", path="{0}/{1}/macsecParams/keyServerPrio".format(path, match.index), value=key_server_priority)) + match.details["macsecParams"]["keyServerPrio"] = key_server_priority + + # if mac_sec_keys: + # mac_sec_keys_list = [] + # for mac_sec_key in mac_sec_keys: + # # if mac_sec_key.get("key_name") and match.details.get("macsecParams")["macsecKeys"]: + + # keyname = mac_sec_key.get("key_name") + # psk = mac_sec_key.get("psk") + # start = mac_sec_key.get("start_time") + # end = mac_sec_key.get("end_time") + + # mac_sec_keys_list.append( + # dict( + # keyname=keyname, + # psk=psk, + # start=start, + # end=end, + # ) + # ) + # ops.append(dict(op="replace", path="{0}/{1}/macsecKeys".format(path, match.index), value=mac_sec_keys_list)) + # match.details["macsecParams"]["macsecKeys"] = mac_sec_keys_list + + + mso.sanitize(match.details) else: + mac_sec_param_map ={} payload = {"name": mac_sec_policy, "templateId": mso_template.template.get("templateId"), "schemaId": mso_template.template.get("schemaId")} - if description: - payload["description"] = description payload["adminState"] = admin_state payload["type"] = type - - mac_sec_param_map ={} - mac_sec_param_map["cipherSuite"] = NDO_CIPHER_SUITE_MAP.get(cipher_suite) - mac_sec_param_map["windowSize"] = window_size - mac_sec_param_map["securityPol"] = NDO_SECURITY_POLICY_MAP.get(security_policy) - mac_sec_param_map["sakExpiryTime"] = sak_expiry_time + + if description: + payload["description"] = description + + if cipher_suite: + mac_sec_param_map["cipherSuite"] = NDO_CIPHER_SUITE_MAP.get(cipher_suite) + if window_size: + mac_sec_param_map["windowSize"] = window_size + if security_policy: + mac_sec_param_map["securityPol"] = NDO_SECURITY_POLICY_MAP.get(security_policy) + if sak_expiry_time: + mac_sec_param_map["sakExpiryTime"] = sak_expiry_time if type == "access": - mac_sec_param_map["confOffSet"] = confidentiality_offset - mac_sec_param_map["keyServerPrio"] = key_server_priority + if confidentiality_offset: + mac_sec_param_map["confOffSet"] = confidentiality_offset + if key_server_priority: + mac_sec_param_map["keyServerPrio"] = key_server_priority - payload["mac_sec_param_map"] = mac_sec_param_map + payload["macsecParams"] = mac_sec_param_map mac_sec_keys_list = [] if mac_sec_keys: @@ -355,6 +393,7 @@ def main(): if not module.check_mode and ops: mso.request(mso_template.template_path, method="PATCH", data=ops) + mso.stdout += str("\n\n ops ") + str(ops) + str("\n request ") + str(mso_template.template_path) mso.exit_json() diff --git a/tests/integration/targets/ndo_mac_sec_policy/tasks/main.yml b/tests/integration/targets/ndo_mac_sec_policy/tasks/main.yml index 9a451455..06155174 100644 --- a/tests/integration/targets/ndo_mac_sec_policy/tasks/main.yml +++ b/tests/integration/targets/ndo_mac_sec_policy/tasks/main.yml @@ -19,7 +19,7 @@ validate_certs: '{{ mso_validate_certs | default(false) }}' use_ssl: '{{ mso_use_ssl | default(true) }}' use_proxy: '{{ mso_use_proxy | default(true) }}' - output_level: '{{ mso_output_level | default("info") }}' + output_level: '{{ mso_output_level | default("debug") }}' # QUERY VERSION - name: Query MSO version @@ -47,7 +47,7 @@ state: present # CREATE - - name: Create a MACsec policy (check mode) + - name: Create a MACsec policy of type 'fabric' (check mode) cisco.mso.ndo_mac_sec_policy: &add_mac_sec_policy <<: *mso_info template: ansible_fabric_policy_template @@ -56,34 +56,43 @@ check_mode: true register: cm_add_mac_sec_policy - - name: Create a MACsec policy + - name: Create a MACsec policy of type 'fabric' cisco.mso.ndo_mac_sec_policy: <<: *add_mac_sec_policy register: nm_add_mac_sec_policy - # - name: Create MACsec policy again - # cisco.mso.ndo_mac_sec_policy: - # <<: *add_mac_sec_policy - # register: nm_add_mac_sec_policy_again + - name: Create MACsec policy again + cisco.mso.ndo_mac_sec_policy: + <<: *add_mac_sec_policy + register: nm_add_mac_sec_policy_again - # - name: Assert that the MACsec policy was created - # assert: - # that: - # - cm_add_mac_sec_policy is changed - # - nm_add_mac_sec_policy is changed - # - nm_add_mac_sec_policy_again is not changed + - name: Assert that the MACsec policy was created + assert: + that: + - cm_add_mac_sec_policy is changed + - cm_add_mac_sec_policy.previous == nm_add_mac_sec_policy.previous == {} + - cm_add_mac_sec_policy.current.name == cm_add_mac_sec_policy.proposed.name == 'ansible_mac_sec_policy' + - cm_add_mac_sec_policy.current.type == cm_add_mac_sec_policy.proposed.type == 'fabric' + - cm_add_mac_sec_policy.current.macsecParams == cm_add_mac_sec_policy.proposed.macsecParams == {} + - nm_add_mac_sec_policy is changed + - nm_add_mac_sec_policy.current.name == 'ansible_mac_sec_policy' + - nm_add_mac_sec_policy.current.type == 'fabric' + - nm_add_mac_sec_policy_again is not changed + - nm_add_mac_sec_policy_again.previous.name == nm_add_mac_sec_policy_again.current.name == 'ansible_mac_sec_policy' + - nm_add_mac_sec_policy_again.previous.type == nm_add_mac_sec_policy_again.current.type == 'fabric' - - name: Create another MACsec policy - cisco.mso.ndo_mac_sec_policy: + + - name: Create another MACsec policy of type 'access' + cisco.mso.ndo_mac_sec_policy: &add_mac_sec_policy_2 <<: *mso_info template: ansible_fabric_policy_template mac_sec_policy: ansible_mac_sec_policy_2 type: access - mac_sec_key: - - key_name: abc12 - psk: 1111111111111111111111111111111111111111111111111111111111111111 - start_time: now - end_time: infinite + # mac_sec_key: + # - key_name: abc12 + # psk: 1111111111111111111111111111111111111111111111111111111111111111 + # start_time: now + # end_time: infinite # - key_name: ABC99 # psk: AA111111111111111111111111111111111111111111111111111111111111aa # start_time: now @@ -91,7 +100,164 @@ # start_time: 2024-12-12 12:12:12 # YYYY-MM-DD HH:MM:SS # end_time: 2024-12-31 23:59:59 state: present + register: nm_add_mac_sec_policy_2 + + # UPDATE + - name: Update the MACsec policy of type 'access' (check mode) + cisco.mso.ndo_mac_sec_policy: &update_mac_sec_policy + <<: *add_mac_sec_policy_2 + description: 'Updated description' + admin_state: 'disabled' + cipher_suite: '128_gcm_aes' + window_size: 110 + security_policy: 'must_secure' + sak_expiry_time: 100 + confidentiality_offset: 30 + key_server_priority: 10 + state: present + check_mode: true + register: cm_update_mac_sec_policy + + - name: Update the MACsec policy of type 'access' + cisco.mso.ndo_mac_sec_policy: + <<: *update_mac_sec_policy + register: nm_update_mac_sec_policy + + - name: Update MACsec policy of type 'access' again + cisco.mso.ndo_mac_sec_policy: + <<: *update_mac_sec_policy + register: nm_update_mac_sec_policy_again + + - name: Assert that the MACsec policy was updated + assert: + that: + - cm_update_mac_sec_policy is changed + - cm_update_mac_sec_policy.previous.description == '' + - cm_update_mac_sec_policy.previous.adminState == 'enabled' + - cm_update_mac_sec_policy.previous.macsecParams.cipherSuite == '256GcmAesXpn' + # - cm_update_mac_sec_policy.previous.macsecParams.windowSize == 0 # -> showing 64 + - cm_update_mac_sec_policy.previous.macsecParams.securityPol == 'shouldSecure' + - cm_update_mac_sec_policy.previous.macsecParams.sakExpiryTime == 0 + - cm_update_mac_sec_policy.previous.macsecParams.confOffSet == 'offset0' + # - cm_update_mac_sec_policy.previous.macsecParams.keyServerPrio == 0 # -> showing 16 + - cm_update_mac_sec_policy.current.description == cm_update_mac_sec_policy.proposed.description == 'Updated description' + - cm_update_mac_sec_policy.current.adminState == cm_update_mac_sec_policy.proposed.adminState == 'disabled' + - cm_update_mac_sec_policy.current.macsecParams.cipherSuite == cm_update_mac_sec_policy.proposed.macsecParams.cipherSuite == '128GcmAes' + - cm_update_mac_sec_policy.current.macsecParams.windowSize == cm_update_mac_sec_policy.proposed.macsecParams.windowSize == 110 + - cm_update_mac_sec_policy.current.macsecParams.securityPol == cm_update_mac_sec_policy.proposed.macsecParams.securityPol == 'mustSecure' + - cm_update_mac_sec_policy.current.macsecParams.sakExpiryTime == cm_update_mac_sec_policy.proposed.macsecParams.sakExpiryTime == 100 + - cm_update_mac_sec_policy.current.macsecParams.confOffSet == cm_update_mac_sec_policy.proposed.macsecParams.confOffSet == 'offset30' + - cm_update_mac_sec_policy.current.macsecParams.keyServerPrio == cm_update_mac_sec_policy.proposed.macsecParams.keyServerPrio == 10 + - nm_update_mac_sec_policy is changed + - nm_update_mac_sec_policy.previous.description == '' + - nm_update_mac_sec_policy.previous.adminState == 'enabled' + - nm_update_mac_sec_policy.previous.macsecParams.cipherSuite == '256GcmAesXpn' + # - nm_update_mac_sec_policy.previous.macsecParams.windowSize == 0 # -> showing 64 + - nm_update_mac_sec_policy.previous.macsecParams.securityPol == 'shouldSecure' + - nm_update_mac_sec_policy.previous.macsecParams.sakExpiryTime == 0 + - nm_update_mac_sec_policy.previous.macsecParams.confOffSet == 'offset0' + # - nm_update_mac_sec_policy.previous.macsecParams.keyServerPrio == 0 # -> showing 16 + - nm_update_mac_sec_policy.current.description =='Updated description' + - nm_update_mac_sec_policy.current.adminState == 'disabled' + - nm_update_mac_sec_policy.current.macsecParams.cipherSuite == '128GcmAes' + - nm_update_mac_sec_policy.current.macsecParams.windowSize == 110 + - nm_update_mac_sec_policy.current.macsecParams.securityPol == 'mustSecure' + - nm_update_mac_sec_policy.current.macsecParams.sakExpiryTime == 100 + - nm_update_mac_sec_policy.current.macsecParams.confOffSet == 'offset30' + - nm_update_mac_sec_policy.current.macsecParams.keyServerPrio == 10 + - nm_update_mac_sec_policy_again is not changed + - nm_update_mac_sec_policy_again.previous.name == cm_update_mac_sec_policy.current.name == nm_update_mac_sec_policy.current.name == 'ansible_mac_sec_policy_2' + - nm_update_mac_sec_policy_again.previous.type == cm_update_mac_sec_policy.current.type == nm_update_mac_sec_policy.current.type == 'access' + - nm_update_mac_sec_policy_again.previous.description == cm_update_mac_sec_policy.current.description == nm_update_mac_sec_policy.current.description == 'Updated description' + + - name: Update the MACsec policy name + cisco.mso.ndo_mac_sec_policy: + <<: *mso_info + template: ansible_fabric_policy_template + mac_sec_policy_uuid: '{{ nm_add_mac_sec_policy_again.current.uuid }}' + mac_sec_policy: ansible_mac_sec_policy_changed + state: present + register: nm_update_mac_sec_policy_uuid + + - name: Assert that the MACsec policy name was updated + assert: + that: + - nm_update_mac_sec_policy_uuid is changed + - nm_update_mac_sec_policy_uuid.previous.name == 'ansible_mac_sec_policy' + - nm_update_mac_sec_policy_uuid.current.name == 'ansible_mac_sec_policy_changed' + - nm_update_mac_sec_policy_uuid.current.type == nm_update_mac_sec_policy_uuid.current.type == 'fabric' + + # QUERY + - name: Query a MACsec policy + cisco.mso.ndo_mac_sec_policy: + <<: *mso_info + template: ansible_fabric_policy_template + mac_sec_policy: ansible_mac_sec_policy_changed + state: query + register: query_one + + - name: Query all MACsec policies in a template + cisco.mso.ndo_mac_sec_policy: + <<: *mso_info + template: ansible_fabric_policy_template + state: query + register: query_all + + - name: Assert that the MACsec policy was queried + assert: + that: + - query_one is not changed + - query_one.current.name == 'ansible_mac_sec_policy_changed' + - query_one.current.type == 'fabric' + - query_one.current.description == '' + - query_all is not changed + - query_all.current | length >= 2 + + - name: Query a syncE MACsec policy with mac_sec_policy uuid + cisco.mso.ndo_mac_sec_policy: + <<: *mso_info + template: ansible_fabric_policy_template + mac_sec_policy_uuid: '{{ nm_update_mac_sec_policy_again.current.uuid }}' + state: query + register: query_uuid + + - name: Assert that the MACsec policy was queried with mac_sec_policy uuid + assert: + that: + - query_uuid is not changed + - query_uuid.current.name == 'ansible_mac_sec_policy_changed' + - query_uuid.current.type == 'fabric' + - query_uuid.current.description == '' + + # DELETE + - name: Delete a MACsec policy of type 'fabric' (check mode) + cisco.mso.ndo_mac_sec_policy: &delete_mac_sec_policy + <<: *mso_info + template: ansible_fabric_policy_template + mac_sec_policy: ansible_mac_sec_policy_changed + state: absent + check_mode: true + register: cm_delete_mac_sec_policy + + - name: Delete a MACsec policy of type 'fabric' + cisco.mso.ndo_mac_sec_policy: + <<: *delete_mac_sec_policy + register: nm_delete_mac_sec_policy + + - name: Delete MACsec policy of type 'fabric' again + cisco.mso.ndo_mac_sec_policy: + <<: *delete_mac_sec_policy + register: nm_delete_mac_sec_policy_again + + - name: Assert that the MACsec policy was deleted + assert: + that: + - cm_delete_mac_sec_policy is changed + - nm_delete_mac_sec_policy is changed + - nm_delete_mac_sec_policy_again is not changed + + + - # UPDATE