feat(api-token): allow org-level tokens to manage project-scoped tokens#2811
feat(api-token): allow org-level tokens to manage project-scoped tokens#2811migmartri merged 5 commits intochainloop-dev:mainfrom
Conversation
Signed-off-by: Sylwester Piskozub <[email protected]>
Signed-off-by: Sylwester Piskozub <[email protected]>
There was a problem hiding this comment.
1 issue found across 5 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="app/controlplane/internal/service/apitoken_test.go">
<violation number="1" location="app/controlplane/internal/service/apitoken_test.go:70">
P2: This test duplicates the service's authorization logic inline rather than calling `svc.List()`. It will pass even if the actual `List` method is broken or its authorization logic changes, providing false confidence. The same issue applies to `TestAPITokenService_Revoke_OrgTokenCannotRevokeOrgTokens` below. Consider using mocks for `APITokenUseCase` (e.g., via an interface or testify mock) so the tests exercise the real service methods end-to-end.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Signed-off-by: Sylwester Piskozub <[email protected]>
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="app/controlplane/pkg/biz/apitoken_integration_test.go">
<violation number="1" location="app/controlplane/pkg/biz/apitoken_integration_test.go:153">
P2: Unsafe `append` may mutate `s.APIToken.DefaultAuthzPolicies`. In Go, `append` reuses the underlying array when capacity permits, which would silently corrupt the shared `DefaultAuthzPolicies` field. The production code already has a safe helper `withOrgLevelPolicies` (apitoken.go:47) — consider using it here, or copy the slice first.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Signed-off-by: Sylwester Piskozub <[email protected]>
| // OrgLevelAPITokenPolicies are additional policies granted only to org-level tokens. | ||
| // They allow managing project-scoped tokens. | ||
| var OrgLevelAPITokenPolicies = []*authz.Policy{ | ||
| authz.PolicyAPITokenCreate, |
There was a problem hiding this comment.
I'd call this PolicyProjectLevelAPITokenCreate since it's only project level tokens
There was a problem hiding this comment.
I was mentioning this above. We can create this specific resource, and then calling the enforcer directly from the service (instead of checking token!=nil && token.ProjectId == nil ...)
There was a problem hiding this comment.
But this one is needed for the middleware to let the request pass.
| } | ||
|
|
||
| // Org-level API tokens can only create project-scoped tokens | ||
| if token := entities.CurrentAPIToken(ctx); token != nil && token.ProjectID == nil { |
There was a problem hiding this comment.
this is something that could be done with Enforce otherwise the policies are worthless no?
Signed-off-by: Sylwester Piskozub <[email protected]>
There was a problem hiding this comment.
1 issue found across 2 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="app/controlplane/pkg/biz/apitoken_integration_test.go">
<violation number="1" location="app/controlplane/pkg/biz/apitoken_integration_test.go:153">
P2: Missing total policy count assertion in the org-level token test. The project-level subtest correctly checks `s.Len(token.Policies, len(s.APIToken.DefaultAuthzPolicies))`, but the org-level subtest only verifies that certain policies are present without asserting the total count. This weakens the test — extra unintended policies on org tokens won't be caught. Consider adding a `Len` check here, consistent with the project-level subtest and the old test.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| // Org-level API tokens can only create project-scoped tokens | ||
| if token := entities.CurrentAPIToken(ctx); token != nil && token.ProjectID == nil { | ||
| if !req.ProjectReference.IsSet() { | ||
| return nil, errors.Forbidden("forbidden", "org-level API tokens must specify a project when creating new tokens") |
There was a problem hiding this comment.
so this special case is needed because we now allow org tokens to pass.
| } | ||
|
|
||
| tokens, err := s.APITokenUseCase.List(ctx, currentOrg.ID, biz.WithAPITokenStatusFilter(mapTokenStatusFilter(req.GetStatusFilter())), biz.WithAPITokenProjectFilter(defaultProjectFilter), biz.WithAPITokenScope(mapTokenScope(req.Scope))) | ||
| // Org-level API tokens can only see project-scoped tokens |
There was a problem hiding this comment.
Perhaps we can simplify all of this with a new resource "ProjectApiToken" and enforcing that specific permission.
| // OrgLevelAPITokenPolicies are additional policies granted only to org-level tokens. | ||
| // They allow managing project-scoped tokens. | ||
| var OrgLevelAPITokenPolicies = []*authz.Policy{ | ||
| authz.PolicyAPITokenCreate, |
There was a problem hiding this comment.
I was mentioning this above. We can create this specific resource, and then calling the enforcer directly from the service (instead of checking token!=nil && token.ProjectId == nil ...)
|
Thanks |
Org-level API tokens can now create, list, and revoke project-scoped API tokens.
🟢 Create project-scoped token with org-scoped token
🔴 Create project-scoped token with project-scoped token
🔴 Create org-scoped token with project-scoped token
🟢 List tokens with org-scoped token
🔴 List tokens with project-scoped token
🔴 Revoke project-scoped token with project-scoped token
🟢 Revoke project-scoped token with org-scoped token
🟢 Create project-scoped token with org-scoped token that was created in the past (List and revoke also works)
Closes #2808