Skip to content

refactor: adopt cinc-api v0.15.0 for groups, ACLs, TLS trust, users and keys - #262

Merged
tas50 merged 10 commits into
mainfrom
refactor/adopt-cinc-api-identity
Sep 24, 2026
Merged

tas50 merged 10 commits into
mainfrom
refactor/adopt-cinc-api-identity

Conversation

@tas50

@tas50 tas50 commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator

Moves the CLI to cinc-api v0.15.0 and deletes the server-protocol logic the library now owns. This is the first of four adoption PRs and carries the minimum v0.15.0 compatibility changes: PushRevision returns a PushResult, and Cookbooks.List returns only the latest version of each cookbook, so explore asks for ListVersions(ctx, "all").

Groups

  • group member add/remove use Groups.AddMembers/RemoveMembers and ParseMemberKind. The hand-rolled read-modify-write and read-back are gone. A remove is now verified too.
  • group edit --file in the server's own {"groupname","actors":{...}} shape used to PUT an empty group. The library now decodes that shape, and a new test covers it.

ACLs

  • Scopes are built on cinc.ACLTarget, with a typed object-type constant at every newACLCmd caller.
  • Grant and revoke use ACLs.Grant/Revoke. When a change fails part way, the error says which permissions were already changed.
  • explainACLError switches on errors.Is.
  • erchef's 403 for removing admins from the grant ACE no longer reads as "you lack grant permission".

TLS and the explorer

  • Trusted certs go through cinc.WithRootCAs. The CLI's own http.Client and its copy of the library's timeout are deleted.
  • The explorer reads the API version from /server_api_version instead of listing every node. pivotal is now cinc.SuperuserName.

Orgs, users and keys

  • Org URLs are built with cinc.FormatServerURL, and org list uses c.ClientName().
  • The library now defaults create_key and the key expiration, so the manual defaulting is gone.
  • user password uses Users.SetPassword, which drops the key fields erchef refuses on a user PUT.
  • There's one emitPrivateKey helper, so every command that prints a key now warns that it won't be shown again.

Test plan

  • go test ./apps/... ./cli/client/ ./cli/explore/ ./cli/config/ ./cli/components/, go vet ./..., gofmt
  • make test-integration (cinc-server-ng): pass
  • cinc-api v0.15.0 itself was validated against a real erchef stack

Replace cinc-api with the local combined branch in both modules so the CLI
can adopt the new identity, group and ACL helpers before they are released.

Two library changes need a touch to keep building and behaving the same:
Policies.PushRevision now returns a PushResult wrapping the revision, and
Cookbooks.List now reports only the latest version of each cookbook, so
the explorer asks for every version with ListVersions.

Signed-off-by: Tim Smith <tsmith84@proton.me>
…embers

The library now reads the group, applies the change, and reads it back to
report what the server kept, so the CLI's own copy of that loop
(applyMemberChange, keptMembers, memberSlice and the memberKind type) goes.
--type is parsed with ParseMemberKind, which also accepts the plural forms.

A remove is now read back too: a member the server still lists afterwards
is an error instead of a claimed removal.

Group.UnmarshalJSON now accepts the PUT shape, members nested under
"actors", so group edit --file with such a file keeps its members instead
of emptying the group. Add a test for it.

Signed-off-by: Tim Smith <tsmith84@proton.me>
…Revoke

The acl subgroups now describe their object as a cinc.ACLTarget (ObjectACL,
OrgACL, UserACL) instead of carrying get/set closures per scope, every
newACLCmd caller passes a cinc.ACL* constant, and grant/revoke hand the
read-modify-write to ACLs.Grant and ACLs.Revoke. explainACLError matches
the library's sentinel errors instead of status codes.

Two user-visible fixes:

- A grant or revoke that fails part way (each permission is its own
  write) now says which permissions were already changed, so the user
  knows the ACL's state.
- Revoking the admins group from grant as anyone but the superuser gets a
  403 from erchef that has nothing to do with the caller's own grant
  permission. We no longer claim they lack grant; we pass on the server's
  message and say only the superuser can do it.

Signed-off-by: Tim Smith <tsmith84@proton.me>
The library now takes a root CA pool and keeps its own HTTP client, 30s
timeout and transport tuning included, so the CLI no longer builds a
replacement client (trustedHTTPClient) or mirrors the library's timeout
(defaultHTTPTimeout) to keep it in step.

Signed-off-by: Tim Smith <tsmith84@proton.me>
…robe

The title bar's API version came from listing every node in the org just
to read the X-Ops-Server-API-Version header. Client.ServerAPIVersion asks
/server_api_version instead, a request that costs the server nothing, and
parses the answer, so parseAPIVersion goes.

The user kind uses cinc.SuperuserName instead of its own "pivotal".

Signed-off-by: Tim Smith <tsmith84@proton.me>
…tter

Users.Create and KeyScope.Create now ask the server to generate a key
whenever no public key is given, and KeyScope.Create sends an expiration
of "infinity" when none is set, so user create and key create stop
setting create_key themselves and --expires no longer carries its own
default.

emitClientCreateResult, emitUserCreateResult and emitOrgCreateResult were
the same function three times; they, writePrivateKey, and the inline
copies in key create, key edit and client reregister become one
emitPrivateKey. Streaming a key to stdout now warns on stderr that it is
the only copy for every command, not just org create.

user password uses Users.SetPassword, which also drops the key fields
erchef refuses on a user PUT. The pivotal checks use cinc.SuperuserName.
org list's fallback and the org confirmation messages read the signing
name and org from the client instead of re-resolving the profile.

Signed-off-by: Tim Smith <tsmith84@proton.me>
config create, node bootstrap and the credentials writer each joined the
server and org by hand. FormatServerURL does the same join, trims the
trailing slash, and escapes the org so it parses back with ParseServerURL.

Signed-off-by: Tim Smith <tsmith84@proton.me>
…lity check

Match cinc.ErrForbidden rather than unpacking the status code, and say
why the check keeps a signed, org-scoped Clients.List rather than the
cheaper ServerAPIVersion probe: /server_api_version sits outside any org,
so it would pass a profile pointed at an org that doesn't exist.

Signed-off-by: Tim Smith <tsmith84@proton.me>
Signed-off-by: Tim Smith <tsmith84@proton.me>
Signed-off-by: Tim Smith <tsmith84@proton.me>
@tas50
tas50 enabled auto-merge (squash) September 24, 2026 05:51
@tas50
tas50 merged commit 4665acd into main Sep 24, 2026
6 checks passed
@tas50
tas50 deleted the refactor/adopt-cinc-api-identity branch September 24, 2026 05:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant