Add OpenConfig user provider - #513
Conversation
1227441 to
aa94822
Compare
Implement UserProvider for the OpenConfig provider, targeting the standard OpenConfig path: openconfig-system:system/aaa/authentication/users/user[username=X]/config Nokia SR Linux limitation: the OpenConfig user model on SRLinux does not expose password or ssh-public-key as writable config leaves — only username and role are settable, and only a single role is accepted. The provider raises UnsupportedFieldError for spec.password, spec.sshPublicKey, and spec.roles when more than one role is given. Since spec.password is mandatory in the CRD, User CRs will always reach Ready=False (terminal) on Nokia SRL via the OpenConfig provider. Also adds a gnmi testdata file documenting the expected device state for a user created with a single role. Co-authored-by: Claude <claude@anthropic.com> Signed-off-by: Robert Gildein <rgildein@users.noreply.github.com>
aa94822 to
f480dcc
Compare
…feat/openconfig-user
Rewrite the user provider to target vanilla OpenConfig rather than Nokia SRLinux-specific behavior: - Support password, ssh-key and role — all standard OpenConfig user config leaves (openconfig-system:system/aaa/authentication/users) - Use gNMI update (Patch) instead of replace (Update) for user creation — Juniper rejects replace for new entries with "statement not found" - Password excluded from UnmarshalJSON to avoid perpetual diffs (device returns hashed value that never matches plaintext) - Remove Nokia-specific UnsupportedFieldError for password/sshPublicKey - Remove CodeIgnoredField from apistatus — not needed for vanilla OpenConfig; revert related changes to conditions.go and user_controller.go - Only retain single-role constraint (OpenConfig role leaf is a single value, not a leaf-list — confirmed on both Juniper and Nokia) - Replace user.txt testdata with proper user.txtar including secrets and full expected gNMI state with ssh-key Tested against Juniper vJunos-Evolved 26.2R1.7 via containerlab. Co-authored-by: Claude <claude@anthropic.com> Signed-off-by: Robert Gildein <rgildein@users.noreply.github.com>
Merging this branch will decrease overall coverage
Coverage by fileChanged files (no unit tests)
Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code. |
|
|
||
| // UserConfig holds the user config container leaves. | ||
| // Password is write-only — the device returns a hashed value that would never match | ||
| // the plaintext, so we exclude it from unmarshal to avoid perpetual diffs. |
There was a problem hiding this comment.
Please have a look into what we are doing on the nxos provider in https://github.com/ironcore-dev/network-operator/blob/main/internal/provider/cisco/nxos/provider.go#L2620-L2641
We take the plaintext password as we retrieve it from the kubernetes secret and compute the hash ourselves (which we can do if the hash includes the algorithm and salt value). If the hash we compute from the plaintext value matches, what is stored in hashed form on the device. We can retain that value.
Otherwise, we would end up with a gnmi write on every reconcilation, which we definitely want to avoid.
| // User targets an OpenConfig user entry. | ||
| type User struct { | ||
| Username string `json:"-"` | ||
| Config *UserConfig `json:"config,omitempty"` |
There was a problem hiding this comment.
| Config *UserConfig `json:"config,omitempty"` | |
| Config *UserConfig `json:"config"` |
This field is always present and should therefore not have an omitempty tag. See
Lines 156 to 161 in e21328d
| SSHKey: req.SSHKey, | ||
| }, | ||
| } | ||
| return p.client.Patch(ctx, u) |
There was a problem hiding this comment.
Any particular reason we use a patch over an update here?
Add OpenConfig provider implementation for the
Userresource targetingthe standard OpenConfig path:
openconfig-system:system/aaa/authentication/users/user[username=X]/configWhat changed
Initial implementation (
Add OpenConfig user provider):EnsureUser/DeleteUserfor the OpenConfig providerusername,password,role, andssh-key— all standardOpenConfig user config leaves
Patch) instead of replace for user creation —Juniper rejects gNMI replace for new list entries with
statement not found; update works for both create and updatepasswordexcluded fromUnmarshalJSONto avoid perpetual diffs —the device returns the hashed value which never matches the plaintext
spec.roleswith more than one entry returnsUnsupportedFieldError—the OpenConfig
roleleaf is a single value (not a leaf-list),confirmed on both Juniper and Nokia
Vanilla OpenConfig cleanup (
Update OpenConfig user provider to vanilla OpenConfig):UnsupportedFieldErrorforspec.passwordandspec.sshPublicKey— vanilla OpenConfig supportsboth fields
CodeIgnoredFieldfromapistatusand related changes toconditions.goanduser_controller.go— not needed once passwordis fully supported
user.txtartestdata including secrets and full expected gNMIstate with
ssh-keyTesting
Tested against real devices via containerlab and live gNMI probing.
Juniper vJunos-Evolved
Device: Juniper vJunos-Evolved 26.2R1.7 (
vrnetlab/juniper_vjunosevolved:26.2R1.7-EVO) via containerlab, gNMI at10.47.43.114:50051What was tested:
username,password,role, andssh-key— all acceptedpasswordis writable and returned hashed (\$9\$...) on read — write-only in practicessh-keyis readable and writable — drift detection works correctlyroleaccepts only a single string (Juniper native class name e.g.superuser,operator)openconfig-aaa-types:SYSTEM_ROLE_ADMINis accepted (treated as plain string by Juniper)openconfig-aaa-types:SYSTEM_ROLE_OPERATORis rejected (Must be a string of alphanumericals, dashes or underscores) — Juniper uses native class names, not OpenConfig identitiesInvalidArgument)statement not found) — gNMI update used insteadVerify user config:
Example output:
{ "config": { "password": "\$9\$Dqjm5n6A01hCtvWXxdV.Pf5n/CAp", "role": "superuser", "ssh-key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQDSGgsAKZn/hxPMKyfwKboiOEeuL9bTqW79QfEQ8h0kpGhkFJJEWR1e3BvXpdT9KYQOaKQnNw32atULweSQQNGh6 IronCore Test", "username": "testplan" }, "username": "testplan" }Nokia SR Linux
Device: Nokia SR Linux 26.7.1 (
ghcr.io/nokia/srlinux:26.7.1) via containerlab, gNMI at172.20.20.2:57400What was tested:
configcontainer foruseronly exposes[username, role]—passwordandssh-keyare not writable leaves on Nokia SRL via OpenConfigopenconfig-aaa-types:SYSTEM_ROLE_ADMIN) — native Nokia role names rejected withFailedPreconditionInvalidArgument