issueRuntimeToken issues a runtime JWT for a deployment based on the provided options and the currently authenticated user. It should only be used from server handlers as it requires the context to carry auth claims.
(ctx context.Context, opts *issueRuntimeTokenOptions)
| 55 | // issueRuntimeToken issues a runtime JWT for a deployment based on the provided options and the currently authenticated user. |
| 56 | // It should only be used from server handlers as it requires the context to carry auth claims. |
| 57 | func (s *Server) issueRuntimeToken(ctx context.Context, opts *issueRuntimeTokenOptions) (string, error) { |
| 58 | // Get claims |
| 59 | claims := auth.GetClaims(ctx) |
| 60 | if claims == nil { |
| 61 | return "", status.Error(codes.Unauthenticated, "cannot issue runtime token without claims") |
| 62 | } |
| 63 | |
| 64 | // Validate that at most one "for" mode is set. |
| 65 | // Note: it is valid to set none of them, which means no base subject/attributes/rules will be resolved. |
| 66 | // Note: forManagement is treated differently as it is a modifier on forOwner, which is checked separately below. |
| 67 | forCount := 0 |
| 68 | if opts.forOwner { |
| 69 | forCount++ |
| 70 | } |
| 71 | if opts.forUserID != "" { |
| 72 | forCount++ |
| 73 | } |
| 74 | if opts.forUserEmail != "" { |
| 75 | forCount++ |
| 76 | } |
| 77 | if opts.forUserAttributes != nil { |
| 78 | forCount++ |
| 79 | } |
| 80 | if forCount > 1 { |
| 81 | return "", status.Error(codes.Internal, "at most one of forOwner/forUserID/forUserEmail/forUserAttributes may be set") |
| 82 | } |
| 83 | |
| 84 | // Resolve principal: subject, attributes, and resource-restriction rules. |
| 85 | var subject string |
| 86 | var attr map[string]any |
| 87 | var rules []*runtimev1.SecurityRule |
| 88 | switch { |
| 89 | case opts.forOwner: |
| 90 | if opts.externalUserID != "" { |
| 91 | return "", status.Error(codes.Internal, "externalUserID cannot be specified together with forOwner") |
| 92 | } |
| 93 | switch claims.OwnerType() { |
| 94 | case auth.OwnerTypeUser: |
| 95 | subject = claims.OwnerID() |
| 96 | a, err := s.jwtAttributesForUser(ctx, claims.OwnerID(), opts.project.OrganizationID, opts.projectPermissions) |
| 97 | if err != nil { |
| 98 | return "", err |
| 99 | } |
| 100 | attr = a |
| 101 | restrict, resources, err := s.getResourceRestrictionsForUser(ctx, opts.project.ID, claims.OwnerID()) |
| 102 | if err != nil { |
| 103 | return "", err |
| 104 | } |
| 105 | rules = append(rules, securityRulesFromResources(restrict, resources)...) |
| 106 | case auth.OwnerTypeService: |
| 107 | subject = claims.OwnerID() |
| 108 | a, err := s.jwtAttributesForService(ctx, claims.OwnerID(), opts.projectPermissions) |
| 109 | if err != nil { |
| 110 | return "", err |
| 111 | } |
| 112 | attr = a |
| 113 | case auth.OwnerTypeMagicAuthToken: |
| 114 | subject = claims.OwnerID() |
no test coverage detected