Skip to content

Commit 837d613

Browse files
authored
refactor: migrate Casbin to in-memory enforcer with database-stored token policies (#2529)
Signed-off-by: Miguel Martinez <miguel@chainloop.dev>
1 parent ff6b05f commit 837d613

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1996
-2320
lines changed

CLAUDE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,12 @@ The project heavily uses code generation:
217217
- **Wire**: Dependency injection
218218
- **Ent**: ORM models and queries
219219
- **Buf**: Protobuf tooling and validation
220+
- **Mockery v3**: Test mocks - add interface to `.mockery.yml`, run `mockery` from that directory
220221

221222
Always run `make generate` after modifying .proto files or Ent schemas.
222223

224+
**API Token Policies**: If modifying `DefaultAuthzPolicies` in `pkg/biz/apitoken.go`, create a migration to update existing tokens' `policies` field - they're stored in DB, not loaded dynamically.
225+
223226
## Contract-Based Development
224227

225228
Workflow Contracts define the structure and requirements for CI/CD attestations. They specify what materials must be collected and policies that must be evaluated.

app/artifact-cas/api/buf.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ deps:
77
- buf.build/bufbuild/protovalidate:b983156c5e994cc9892e0ce3e64e17e0
88
lint:
99
use:
10-
- DEFAULT
10+
- STANDARD

app/artifact-cas/internal/conf/buf.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ deps:
77
- buf.build/bufbuild/protovalidate:b983156c5e994cc9892e0ce3e64e17e0
88
lint:
99
use:
10-
- DEFAULT
10+
- STANDARD
1111
ignore_only:
1212
PACKAGE_DEFINED:
1313
- ./conf.proto

app/controlplane/api/buf.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ deps:
99
- buf.build/grpc-ecosystem/grpc-gateway:v2.26.3
1010
lint:
1111
use:
12-
- DEFAULT
12+
- STANDARD
1313
ignore_only:
1414
ENUM_ZERO_VALUE_SUFFIX:
1515
- controlplane/v1/pagination.proto

app/controlplane/cmd/main.go

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func init() {
6464
}
6565

6666
func newApp(logger log.Logger, gs *grpc.Server, hs *http.Server, ms *server.HTTPMetricsServer, profilerSvc *server.HTTPProfilerServer,
67-
expirer *biz.WorkflowRunExpirerUseCase, plugins sdk.AvailablePlugins, tokenSync *biz.APITokenSyncerUseCase,
67+
expirer *biz.WorkflowRunExpirerUseCase, plugins sdk.AvailablePlugins,
6868
userAccessSyncer *biz.UserAccessSyncerUseCase, casBackendChecker *biz.CASBackendChecker, cfg *conf.Bootstrap) *app {
6969
servers := []transport.Server{gs, hs, ms}
7070
if cfg.EnableProfiler {
@@ -79,7 +79,7 @@ func newApp(logger log.Logger, gs *grpc.Server, hs *http.Server, ms *server.HTTP
7979
kratos.Metadata(map[string]string{}),
8080
kratos.Logger(logger),
8181
kratos.Server(servers...),
82-
), expirer, plugins, tokenSync, userAccessSyncer, casBackendChecker}
82+
), expirer, plugins, userAccessSyncer, casBackendChecker}
8383
}
8484

8585
func main() {
@@ -152,15 +152,6 @@ func main() {
152152
// TODO: Make it configurable from the application config
153153
app.runsExpirer.Run(ctx, &biz.WorkflowRunExpirerOpts{CheckInterval: 1 * time.Minute, ExpirationWindow: 1 * time.Hour})
154154

155-
// Since policies management is not enabled yet but instead is based on a hardcoded list of permissions
156-
// We'll perform a reconciliation of the policies with the tokens stored in the database on startup
157-
// This will allow us to add more policies in the future and keep backwards compatibility with existing tokens
158-
go func() {
159-
if err := app.tokenAuthSyncer.SyncPolicies(); err != nil {
160-
_ = logger.Log(log.LevelError, "msg", "syncing policies", "error", err)
161-
}
162-
}()
163-
164155
// Sync user access
165156
go func() {
166157
if err := app.userAccessSyncer.SyncUserAccess(ctx); err != nil {
@@ -207,7 +198,6 @@ type app struct {
207198
// Periodic job that expires unfinished attestation processes older than a given threshold
208199
runsExpirer *biz.WorkflowRunExpirerUseCase
209200
availablePlugins sdk.AvailablePlugins
210-
tokenAuthSyncer *biz.APITokenSyncerUseCase
211201
userAccessSyncer *biz.UserAccessSyncerUseCase
212202
// Background checker for CAS backends
213203
casBackendChecker *biz.CASBackendChecker

app/controlplane/cmd/wire.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func wireApp(*conf.Bootstrap, credentials.ReaderWriter, log.Logger, sdk.Availabl
5353
wire.FieldsOf(new(*conf.Bootstrap), "Server", "Auth", "Data", "CasServer", "ReferrerSharedIndex", "Onboarding", "PrometheusIntegration", "PolicyProviders", "NatsServer", "FederatedAuthentication"),
5454
wire.FieldsOf(new(*conf.Data), "Database"),
5555
dispatcher.New,
56-
authz.NewDatabaseEnforcer,
56+
authz.NewInMemoryEnforcer,
5757
policies.NewRegistry,
5858
newApp,
5959
newProtoValidator,
@@ -71,7 +71,7 @@ func wireApp(*conf.Bootstrap, credentials.ReaderWriter, log.Logger, sdk.Availabl
7171
}
7272

7373
func authzConfig(conf *conf.Bootstrap) *authz.Config {
74-
return &authz.Config{ManagedResources: authz.ManagedResources, RolesMap: authz.RolesMap, RestrictOrgCreation: conf.RestrictOrgCreation}
74+
return &authz.Config{RolesMap: authz.RolesMap, RestrictOrgCreation: conf.RestrictOrgCreation}
7575
}
7676

7777
func newJWTConfig(conf *conf.Auth) *biz.APITokenJWTConfig {

app/controlplane/cmd/wire_gen.go

Lines changed: 3 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/controlplane/internal/conf/buf.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ deps:
88
- buf.build/kratos-go/kratos:e1d52e944e3845c6862a566db322432d
99
lint:
1010
use:
11-
- DEFAULT
11+
- STANDARD
1212
ignore_only:
1313
PACKAGE_DEFINED:
1414
- ./conf.proto

app/controlplane/internal/usercontext/apitoken_middleware.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ func setCurrentOrgAndAPIToken(ctx context.Context, apiTokenUC *biz.APITokenUseCa
202202
Token: token.JWT,
203203
ProjectID: token.ProjectID,
204204
ProjectName: token.ProjectName,
205+
Policies: token.Policies,
205206
})
206207

207208
// Set the authorization subject that will be used to check the policies

app/controlplane/internal/usercontext/apitoken_middleware_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright 2024 The Chainloop Authors.
2+
// Copyright 2024-2025 The Chainloop Authors.
33
//
44
// Licensed under the Apache License, Version 2.0 (the "License");
55
// you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@ import (
2424

2525
"github.com/chainloop-dev/chainloop/app/controlplane/internal/usercontext/entities"
2626
"github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz"
27-
bizMocks "github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz/mocks"
27+
"github.com/chainloop-dev/chainloop/app/controlplane/pkg/biz/mocks"
2828
"github.com/chainloop-dev/chainloop/app/controlplane/pkg/jwt/apitoken"
2929
"github.com/go-kratos/kratos/v2/log"
3030
jwtmiddleware "github.com/go-kratos/kratos/v2/middleware/auth/jwt"
@@ -97,8 +97,8 @@ func TestWithCurrentAPITokenAndOrgMiddleware(t *testing.T) {
9797
wantToken := &biz.APIToken{ID: uuid.New(), OrganizationID: wantOrgID}
9898

9999
t.Run(tc.name, func(t *testing.T) {
100-
apiTokenRepo := bizMocks.NewAPITokenRepo(t)
101-
orgRepo := bizMocks.NewOrganizationRepo(t)
100+
apiTokenRepo := mocks.NewAPITokenRepo(t)
101+
orgRepo := mocks.NewOrganizationRepo(t)
102102
apiTokenUC, err := biz.NewAPITokenUseCase(apiTokenRepo, &biz.APITokenJWTConfig{SymmetricHmacKey: "test"}, nil, nil, nil, nil)
103103
require.NoError(t, err)
104104
orgUC := biz.NewOrganizationUseCase(orgRepo, nil, nil, nil, nil, nil, nil)

0 commit comments

Comments
 (0)