[macsec]: Add config/show commands for MACsec fallback key & MKA - #29102
liamkearney-msft wants to merge 4 commits into
Conversation
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
Adds CLI support in the MACsec config plugin to configure a fallback CAK/CKN when creating MACsec profiles, and to rotate (update) a profile’s primary or fallback key at runtime to support hitless CAK rotation workflows.
Changes:
- Add
--fallback_cak/--fallback_cknoptions toconfig macsec profile add, including validation and persistence inMACSEC_PROFILE. - Introduce
config macsec profile updateto rotate either the primary or fallback key selected by--old_ckn. - Extend CLI plugin tests to cover fallback configuration and key-rotation behaviors (including invalid input cases).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| dockers/docker-macsec/cli/config/plugins/macsec.py | Adds fallback CAK/CKN support, shared key validation helpers, and a new profile update command for key rotation. |
| dockers/docker-macsec/cli-plugin-tests/test_config_macsec.py | Adds test coverage for fallback key configuration and runtime key rotation, including negative test cases. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
🟢 Approval recommended
The feature implementation is coherent and has substantial test coverage; remaining feedback is limited to improving the specificity of newly-generic CLI error messages.
Review details
Suppressed comments (2)
dockers/docker-macsec/cli/config/plugins/macsec.py:128
- validate_cak() now emits generic failure messages ("Expect the CAK is valid hex string" / "Expect the length of CAK...") without indicating which CLI argument was invalid (primary_cak vs fallback_cak vs new_cak), which makes troubleshooting harder—especially now that multiple CAKs can be provided/rotated. Consider including the failing field name in the error (or passing it into validate_cak) so the CLI points to the exact option that needs fixing.
def validate_cak(ctx, cipher_suite, cak):
length = expected_cak_length(cipher_suite)
if length is not None and len(cak) != length:
ctx.fail("Expect the length of CAK is {}, but got {}".format(length, len(cak)))
if not is_hexstring(cak):
ctx.fail("Expect the CAK is valid hex string")
dockers/docker-macsec/cli/config/plugins/macsec.py:134
- validate_ckn() now reports a generic "Expect the CKN is valid hex string" error, which doesn’t identify whether the invalid value came from --primary_ckn, --fallback_ckn, --old_ckn, or --new_ckn. Since the new 'update' flow introduces multiple CKN inputs, it would be clearer to include the specific argument name in the failure message (or pass a label into validate_ckn).
def validate_ckn(ctx, ckn):
if not is_hexstring(ckn):
ctx.fail("Expect the CKN is valid hex string")
- Files reviewed: 2/2 changed files
- Comments generated: 0 new
- Review effort level: Lite
|
cc @senthil-nexthop for review |
855bf98 to
f1516b0
Compare
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved runtime failure and validation and multi-ASIC display issues remain.
Get a fresh assessment by requesting another Copilot review.
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 4
- Review effort level: Lite
f1516b0 to
8fce93c
Compare
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
🔵 Needs a closer look
Add fallback-path rotation tests and correct missing-value duration formatting.
Review details
Suppressed comments (2)
dockers/docker-macsec/cli/config/plugins/macsec.py:438
- The attached-port tests cover only the
selected_role == "primary"path. This fallback branch has different safety semantics (the configured primary must be the live alternate), so add an attached-profile test that rotatesold_cknfrom the fallback and verifies both the successful case and a failed-primary-alternate preflight leave CONFIG_DB unchanged.
elif normalized_old == normalized_fallback:
selected_role = "fallback"
other_ckn = normalized_primary
dockers/docker-macsec/cli/show/plugins/show_macsec.py:675
_safe_uintreturns-for a missing or malformed field, but this formatting appendsmsunconditionally, so an incomplete session is rendered as- msinstead of the required missing-value marker-. Format the unit only when the sanitized value is valid.
("MKA hello time", "{} ms".format(
_safe_uint(session.get("mka_hello_time_ms"))
)),
- Files reviewed: 4/4 changed files
- Comments generated: 0 new
- Review effort level: Lite
Implement fallback profile validation, safe replacement-by-CKN updates, and namespace-aware MKA operational state display. Signed-off-by: Liam Kearney <liamkearney@microsoft.com>
8fce93c to
73868eb
Compare
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
🔵 Needs a closer look
Unresolved review findings remain in MKA rendering and attached-profile fallback-rotation coverage.
Review details
Suppressed comments (4)
dockers/docker-macsec/cli/config/plugins/macsec.py:437
- The attached-profile tests cover only the
selected_role == "primary"path. The fallback-rotation branch here uses the opposite role predicate and must prove that the configured primary is active, hasis_primary=true, and has a live peer before CONFIG_DB is changed; add an attached-profile test that rotates the fallback and asserts both the success case and rejection when that primary alternate is unsafe.
elif normalized_old == normalized_fallback:
selected_role = "fallback"
dockers/docker-macsec/cli/show/plugins/show_macsec.py:127
int(value, 16)is not a strict hexadecimal check: it accepts signs and surrounding whitespace, so malformed values such as a fixed-width+...SCI/CKN are rendered instead of being mapped to-. Use an ASCII hex-character check here, asis_hexstring()does in the config plugin, before lowercasing the value.
try:
int(value, 16)
return value.lower()
except ValueError:
return "-"
dockers/docker-macsec/cli/show/plugins/show_macsec.py:80
- When
last_updatedparses butquery_statusis missing or an unexpected value, this path falls through and reports a plain age such as2s; onlyokor the explicitly retainederrorstate should produce a freshness age. That makes malformed state look fresh even though the query column renders-; return a conservativenever/unknown freshness for unrecognized statuses.
def _freshness(last_updated, query_status, now=None):
parsed = _parse_utc_timestamp(last_updated)
if parsed is None:
return "never", "never"
dockers/docker-macsec/cli/show/plugins/show_macsec.py:675
- A missing or invalid
mka_hello_time_msis rendered as- msbecause the unit is appended unconditionally. The MKA detail contract uses-for missing fields, so this output incorrectly suggests a value with a unit; appendmsonly when_safe_uintreturns a real counter.
("MKA hello time", "{} ms".format(
_safe_uint(session.get("mka_hello_time_ms"))
)),
- Files reviewed: 4/4 changed files
- Comments generated: 0 new
- Review effort level: Lite
Align freshness with the 20-second state sweep, make compact health explicit, and cover fallback rotation and strict rendering paths. Signed-off-by: Liam Kearney <liamkearney@microsoft.com>
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
🟡 Changes recommended
Align freshness thresholds with the HLD and preserve documented MKA status distinctions.
Get a fresh assessment by requesting another Copilot review.
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 3
- Review effort level: Lite
Accept the IEEE protected controlled-port state and label the raw authenticated-only state accurately in detailed output. Signed-off-by: Liam Kearney <liamkearney@microsoft.com>
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
🟡 Changes recommended
The MKA display has one moderate correctness issue and one labeling issue to address.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
dockers/docker-macsec/cli/show/plugins/show_macsec.py:174
key_server_sci=0000000000000000is a valid normalized value before key-server election, but this helper converts it to-. That makesshow macsec --mkalose the distinction between a legitimate pre-election state and an invalid/missing SCI; the allowlisted 16-hex value should be displayed as-is.
if sci == "0000000000000000":
return "-"
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Lite
Replace raw detailed controlled-port booleans with a conservative operator-facing mode while preserving compact protection status. Signed-off-by: Liam Kearney <liamkearney@microsoft.com>
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical secret-redaction and moderate freshness-preflight issues remain.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
dockers/docker-macsec/cli/config/plugins/macsec.py:281
nowis captured once before iterating all attached ports, so a port checked late in a large/slow preflight can cross the 60-second freshness limit while still being accepted, and the subsequent CONFIG_DB write proceeds with stale safety data. Compute the reference time per port (as close as possible to that port's validation) rather than reusing the timestamp from the start of the whole sweep.
now = datetime.datetime.now(datetime.timezone.utc)
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Lite
| r"(?i)(?<![0-9a-f])(?:[0-9a-f]{130}|[0-9a-f]{66})(?![0-9a-f])", | ||
| "[redacted]", | ||
| result, | ||
| ) |
Add docker-macsec configuration and show commands for MKA operational state and safe primary/fallback CAK rotation.
Companion design and implementation:
Dependency order: sonic-net/sonic-swss-common#1251 → sonic-net/sonic-swss#4827 → this PR. The WPA PR supplies the frozen control/status interface consumed by
macsecmgrd.Work item tracking
How I did it
00..52.config macsec profile updatereplacement selected by old CKN.authenticated=false, secured=true;authenticated=truedenotes authenticated-only, unprotected controlled-port state.last_updated,query_status,config_status, and optional redactedconfig_error; freshness is derived rather than stored.show macsec --mka [interface]with multi-ASIC aggregation, natural interface ordering, namespace disambiguation, and strict secret-safe field allowlisting.StatusandAge: age comes only from the last successful snapshot, while status preserves independent query, staleness, and configuration health.Controlled port mode(secured,authenticated-only,failed,inactive,inconsistent, or unknown) from the raw WPA state while retaining separate query/config/error and last-updated diagnostics.How to verify it
python3 -m py_compilepassed on all four changed Python files.git diff --checkpassed.Coverage includes fallback validation, canonical CKN/CAK and salt-index rejection, duplicate CKN rejection, unattached and attached primary/fallback profile updates, the complete controlled-port preflight state matrix, atomic preflight failures, the 60-second config/show freshness boundary, independent query/config/stale status combinations, never-success age, strict malformed-state rendering, the detailed controlled-port mode state matrix and valid pre-election zero SCI rendering, compact/detail display, natural interface ordering, duplicate interface names across namespaces, namespace aggregation, and secret redaction.
Which release branch to backport (provide reason below if selected)
Tracking issue/work item for backport/cherry-pick request (GitHub issue or Microsoft ADO):
Failure type:
Tested branch
Test result
master: focused docker-macsec CLI tests, 27 passed; Python compilation and diff checks passed. Physical image validation is tracked separately.
Description for the changelog
Add safe MACsec primary/fallback CAK rotation commands and namespace-aware MKA operational-state display.
Link to config_db schema for YANG module changes
N/A — this PR consumes the existing MACsec profile schema and adds CLI behavior.
A picture of a cute animal (not mandatory but encouraged)