@@ -3,14 +3,12 @@ package token
33import (
44 "context"
55 "errors"
6- "fmt"
76 "log/slog"
87 "slices"
98 "time"
109
1110 apiv2 "github.com/metal-stack/api/go/metalstack/api/v2"
1211 "github.com/metal-stack/api/go/metalstack/api/v2/apiv2connect"
13- "github.com/metal-stack/api/go/permissions"
1412 "github.com/metal-stack/metal-apiserver/pkg/errorutil"
1513 "github.com/metal-stack/metal-apiserver/pkg/request"
1614
@@ -33,14 +31,14 @@ type Config struct {
3331}
3432
3533type tokenService struct {
36- issuer string
37- adminSubjects []string
38- tokens tokenutil.TokenStore
39- certs certs.CertStore
40- log * slog.Logger
41- servicePermissions * permissions.ServicePermissions
34+ issuer string
35+ adminSubjects []string
36+ tokens tokenutil.TokenStore
37+ certs certs.CertStore
38+ log * slog.Logger
4239
4340 projectsAndTenantsGetter func (ctx context.Context , userId string ) (* repository.ProjectsAndTenants , error )
41+ authorizer request.Authorizer
4442}
4543
4644type TokenService interface {
@@ -51,19 +49,20 @@ type TokenService interface {
5149}
5250
5351func New (c Config ) TokenService {
54- servicePermissions := permissions .GetServicePermissions ()
52+ projectsAndTenantsGetter := func (ctx context.Context , userId string ) (* repository.ProjectsAndTenants , error ) {
53+ return c .Repo .UnscopedProject ().AdditionalMethods ().GetProjectsAndTenants (ctx , userId )
54+ }
55+ log := c .Log .WithGroup ("tokenService" )
5556
5657 return & tokenService {
57- tokens : c .TokenStore ,
58- certs : c .CertStore ,
59- issuer : c .Issuer ,
60- log : c .Log .WithGroup ("tokenService" ),
61- servicePermissions : servicePermissions ,
62- adminSubjects : c .AdminSubjects ,
58+ tokens : c .TokenStore ,
59+ certs : c .CertStore ,
60+ issuer : c .Issuer ,
61+ log : log ,
62+ adminSubjects : c .AdminSubjects ,
6363
64- projectsAndTenantsGetter : func (ctx context.Context , userId string ) (* repository.ProjectsAndTenants , error ) {
65- return c .Repo .UnscopedProject ().AdditionalMethods ().GetProjectsAndTenants (ctx , userId )
66- },
64+ projectsAndTenantsGetter : projectsAndTenantsGetter ,
65+ authorizer : request .NewAuthorizer (log , projectsAndTenantsGetter ),
6766 }
6867}
6968
@@ -119,6 +118,7 @@ func (t *tokenService) CreateApiTokenWithoutPermissionCheck(ctx context.Context,
119118 token .ProjectRoles = req .ProjectRoles
120119 token .TenantRoles = req .TenantRoles
121120 token .AdminRole = req .AdminRole
121+ token .InfraRole = req .InfraRole
122122
123123 err = t .tokens .Set (ctx , token )
124124 if err != nil {
@@ -167,9 +167,10 @@ func (t *tokenService) Update(ctx context.Context, req *apiv2.TokenServiceUpdate
167167 ProjectRoles : req .ProjectRoles ,
168168 TenantRoles : req .TenantRoles ,
169169 AdminRole : req .AdminRole ,
170+ InfraRole : req .InfraRole ,
170171 }
171172
172- err := t .validateCreate (ctx , token , createRequest )
173+ err := t .validateTokenRequest (ctx , token , createRequest )
173174 if err != nil {
174175 return nil , errorutil .NewPermissionDenied (err )
175176 }
@@ -187,11 +188,12 @@ func (t *tokenService) Update(ctx context.Context, req *apiv2.TokenServiceUpdate
187188 ProjectRoles : projectsAndTenants .ProjectRoles ,
188189 TenantRoles : projectsAndTenants .TenantRoles ,
189190 AdminRole : nil ,
191+ InfraRole : token .InfraRole ,
190192 }
191193 if slices .Contains (t .adminSubjects , token .User ) {
192194 fullUserToken .AdminRole = apiv2 .AdminRole_ADMIN_ROLE_EDITOR .Enum ()
193195 }
194- err = t .validateCreate (ctx , fullUserToken , createRequest )
196+ err = t .validateTokenRequest (ctx , fullUserToken , createRequest )
195197 if err != nil {
196198 return nil , errorutil .PermissionDenied ("outdated token: %w" , err )
197199 }
@@ -254,7 +256,7 @@ func (t *tokenService) CreateTokenForUser(ctx context.Context, user *string, req
254256 // we first validate token permission elevation for the token used in the token create request,
255257 // which might be an API token with restricted permissions
256258
257- err := t .validateCreate (ctx , token , req )
259+ err := t .validateTokenRequest (ctx , token , req )
258260 if err != nil {
259261 return nil , errorutil .NewPermissionDenied (err )
260262 }
@@ -272,6 +274,7 @@ func (t *tokenService) CreateTokenForUser(ctx context.Context, user *string, req
272274 ProjectRoles : projectsAndTenants .ProjectRoles ,
273275 TenantRoles : projectsAndTenants .TenantRoles ,
274276 AdminRole : nil ,
277+ InfraRole : token .InfraRole ,
275278 }
276279
277280 tokenUser := token .GetUser ()
@@ -288,7 +291,7 @@ func (t *tokenService) CreateTokenForUser(ctx context.Context, user *string, req
288291 tokenUser = * user
289292 }
290293
291- err = t .validateCreate (ctx , fullUserToken , req )
294+ err = t .validateTokenRequest (ctx , fullUserToken , req )
292295 if err != nil {
293296 return nil , errorutil .PermissionDenied ("outdated token: %w" , err )
294297 }
@@ -308,6 +311,7 @@ func (t *tokenService) CreateTokenForUser(ctx context.Context, user *string, req
308311 token .ProjectRoles = req .ProjectRoles
309312 token .TenantRoles = req .TenantRoles
310313 token .AdminRole = req .AdminRole
314+ token .InfraRole = req .InfraRole
311315
312316 err = t .tokens .Set (ctx , token )
313317 if err != nil {
@@ -374,9 +378,10 @@ func (t *tokenService) Refresh(ctx context.Context, _ *apiv2.TokenServiceRefresh
374378 ProjectRoles : oldtoken .ProjectRoles ,
375379 TenantRoles : oldtoken .TenantRoles ,
376380 AdminRole : oldtoken .AdminRole ,
381+ InfraRole : oldtoken .InfraRole ,
377382 }
378383
379- err = t .validateCreate (ctx , token , createRequest )
384+ err = t .validateTokenRequest (ctx , token , createRequest )
380385 if err != nil {
381386 return nil , errorutil .NewPermissionDenied (err )
382387 }
@@ -394,11 +399,12 @@ func (t *tokenService) Refresh(ctx context.Context, _ *apiv2.TokenServiceRefresh
394399 ProjectRoles : projectsAndTenants .ProjectRoles ,
395400 TenantRoles : projectsAndTenants .TenantRoles ,
396401 AdminRole : nil ,
402+ InfraRole : token .InfraRole ,
397403 }
398404 if slices .Contains (t .adminSubjects , token .User ) {
399405 fullUserToken .AdminRole = apiv2 .AdminRole_ADMIN_ROLE_EDITOR .Enum ()
400406 }
401- err = t .validateCreate (ctx , fullUserToken , createRequest )
407+ err = t .validateTokenRequest (ctx , fullUserToken , createRequest )
402408 if err != nil {
403409 return nil , errorutil .PermissionDenied ("outdated token: %w" , err )
404410 }
@@ -423,6 +429,7 @@ func (t *tokenService) Refresh(ctx context.Context, _ *apiv2.TokenServiceRefresh
423429 newToken .ProjectRoles = oldtoken .ProjectRoles
424430 newToken .TenantRoles = oldtoken .TenantRoles
425431 newToken .AdminRole = oldtoken .AdminRole
432+ newToken .InfraRole = oldtoken .InfraRole
426433
427434 err = t .tokens .Set (ctx , newToken )
428435 if err != nil {
@@ -435,29 +442,39 @@ func (t *tokenService) Refresh(ctx context.Context, _ *apiv2.TokenServiceRefresh
435442 }, nil
436443}
437444
438- type TokenRequest interface {
445+ type tokenRequest interface {
439446 GetPermissions () []* apiv2.MethodPermission
440447 GetProjectRoles () map [string ]apiv2.ProjectRole
441448 GetTenantRoles () map [string ]apiv2.TenantRole
442449 GetAdminRole () apiv2.AdminRole
443450 GetInfraRole () apiv2.InfraRole
444451}
445452
446- func (t * tokenService ) validateCreate (ctx context.Context , currentToken * apiv2.Token , req TokenRequest ) error {
447- authorizer := request .NewAuthorizer (t .log , t .projectsAndTenantsGetter )
448-
449- currentPermission , err := authorizer .TokenPermissions (ctx , currentToken )
453+ func (t * tokenService ) validateTokenRequest (ctx context.Context , currentToken * apiv2.Token , req tokenRequest ) error {
454+ currentPermission , err := t .authorizer .TokenPermissions (ctx , currentToken )
450455 if err != nil {
451456 return err
452457 }
453458
454- requestedPermissions , err := authorizer .TokenPermissions (ctx , & apiv2.Token {
459+ var (
460+ adminRole * apiv2.AdminRole
461+ infraRole * apiv2.InfraRole
462+ )
463+
464+ if req .GetAdminRole () != apiv2 .AdminRole_ADMIN_ROLE_UNSPECIFIED {
465+ adminRole = req .GetAdminRole ().Enum ()
466+ }
467+ if req .GetInfraRole () != apiv2 .InfraRole_INFRA_ROLE_UNSPECIFIED {
468+ infraRole = req .GetInfraRole ().Enum ()
469+ }
470+
471+ requestedPermissions , err := t .authorizer .TokenPermissions (ctx , & apiv2.Token {
455472 User : currentToken .User ,
456473 Permissions : req .GetPermissions (),
457474 ProjectRoles : req .GetProjectRoles (),
458475 TenantRoles : req .GetTenantRoles (),
459- AdminRole : req . GetAdminRole (). Enum () ,
460- InfraRole : req . GetInfraRole (). Enum () ,
476+ AdminRole : adminRole ,
477+ InfraRole : infraRole ,
461478 })
462479 if err != nil {
463480 return err
@@ -466,18 +483,19 @@ func (t *tokenService) validateCreate(ctx context.Context, currentToken *apiv2.T
466483 for method , subjects := range requestedPermissions {
467484 currentSubjects , ok := currentPermission [method ]
468485 if ! ok {
469- return fmt . Errorf ("requested method %q is not allowed in your current token" , method )
486+ return errors . New ("requested methods are not allowed with your current token" )
470487 }
471488
472- if _ , ok := subjects ["*" ]; ok {
489+ if _ , ok := currentSubjects ["*" ]; ok {
473490 continue
474491 }
475492
476493 for subject := range subjects {
477494 if _ , ok := currentSubjects [subject ]; ! ok {
478- return fmt . Errorf ("requested subject %q on method %q is not allowed in your current token" , subject , method )
495+ return errors . New ("requested subjects are not allowed with your current token" )
479496 }
480497 }
481498 }
499+
482500 return nil
483501}
0 commit comments