Commit 023b5d8
authored
feat(groups): add ServiceAccountAccessToken managed resource (#326)
* feat(groups): add ServiceAccountAccessToken managed resource
Adds a group-scoped ServiceAccountAccessToken managed resource that manages
the personal access token of a group service account.
Owner mode (default): the ProviderConfig is a group owner and the token is
managed via the service-account endpoints:
- Create -> Groups.CreateServiceAccountPersonalAccessToken
- Observe -> Groups.ListServiceAccountPersonalAccessTokens (match by token id)
- Rotate -> Groups.RotateServiceAccountPersonalAccessToken
- Revoke -> Groups.RevokeServiceAccountPersonalAccessToken
Self-managed mode: when the referenced ProviderConfig authenticates with the
very token this resource writes to its connection secret (detected when the
PersonalAccessToken credential secretRef matches writeConnectionSecretToRef by
namespace, name and key), the provider acts as the service account itself and
uses the self endpoints instead:
- Observe -> GET /personal_access_tokens/self (self-inform; external name is
auto-adopted from the response)
- Rotate -> RotatePersonalAccessTokenSelf
- Revoke -> RevokePersonalAccessTokenSelf
This enables a self-sustaining loop of short-lived, self-rotating tokens used to
reconcile a group. A dead self-token surfaces as a clear terminal error
(reseed the credentials secret). A SelfManaged status condition reports the
detected mode.
The external name is the token id and the token value is written to the
connection secret on create/rotate. Rotation, expiresAt/renewalPeriodDays and
renewBeforeDays semantics match the group AccessToken controller. groupId,
serviceAccountId, name and scopes are immutable (enforced via CEL); the
rotation-timing fields stay mutable.
Fixes #324
Signed-off-by: Markus Siebert <markus.siebert@deutschebahn.com>
* fix(groups): address ServiceAccountAccessToken review feedback
- self mode: validate the adopted PAT belongs to spec.forProvider.serviceAccountId
(PersonalAccessToken.UserID) and surface a terminal error on mismatch, so a
miswired credentials secret can no longer rotate/revoke the wrong service
account's token while the reconcile still succeeds.
- owner mode: narrow the rotate->create fallback. Only fall through to a fresh
create when the existing token is genuinely gone (404, or the specific
'Token already revoked' 400). Any other error (generic 400, 403, 5xx,
transport) now returns instead of minting a second token.
- cluster scope: fix self-mode detection for cluster-scoped resources. A
cluster resource has no namespace and writes to a full SecretReference, so
isSelfManaged must compare the credential secret namespace against the write
reference's namespace. Implemented as a generator replacement so the cluster
zz_ code is regenerated correctly.
- client: filter the service-account token list with state=active to avoid
paginating through revoked/expired tokens on every Observe poll.
- crd: add the 'saat' shortName for friendlier kubectl usage.
Regenerated cluster-scoped code and CRDs via make generate.
Signed-off-by: Markus Siebert <markus.siebert@deutschebahn.com>
* fix(common): carry CredentialsSecretRef through the legacy ProviderConfig path
Cluster-scoped resources are LegacyManaged and resolve their credentials via
UseLegacyProviderConfig, which built a Config without CredentialsSecretRef. As
a result isSelfManaged() always saw a nil ref and self-managed mode never
activated for cluster-scoped ServiceAccountAccessTokens, even when the
ProviderConfig read from the exact secret the resource writes to (it stayed
SelfManaged=False / OwnerManaged and then 404'd on the owner path).
Populate CredentialsSecretRef from pc.Spec.Credentials.SecretRef in the legacy
path, mirroring the modern namespaced path, so self-mode detection works for
cluster-scoped resources too.
Co-authored fix and test verifying the legacy builder carries the ref.
Signed-off-by: Markus Siebert <markus.siebert@deutschebahn.com>
* style(common): fix gci import grouping in helper_test.go
Move the provider-gitlab-local imports into their own trailing gci group to
satisfy the project's gci section order (standard, default, prefix).
Signed-off-by: Markus Siebert <markus.siebert@deutschebahn.com>
---------
Signed-off-by: Markus Siebert <markus.siebert@deutschebahn.com>1 parent 0e1dbef commit 023b5d8
31 files changed
Lines changed: 5725 additions & 8 deletions
File tree
- apis
- cluster/groups/v1alpha1
- namespaced/groups/v1alpha1
- examples/groups
- hack
- package/crds
- pkg
- cluster
- clients/groups
- fake
- controller/groups
- serviceaccountaccesstokens
- common
- namespaced
- clients/groups
- fake
- controller/groups
- serviceaccountaccesstokens
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
47 | 92 | | |
48 | 93 | | |
49 | 94 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
0 commit comments