2022-05-05 13:25:50 +00:00
|
|
|
// Copyright 2022 Cloudbase Solutions SRL
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
|
|
|
// not use this file except in compliance with the License. You may obtain
|
|
|
|
|
// a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
|
// License for the specific language governing permissions and limitations
|
|
|
|
|
// under the License.
|
|
|
|
|
|
2022-04-28 16:13:20 +00:00
|
|
|
package auth
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
2024-07-02 22:26:12 +00:00
|
|
|
"time"
|
2022-04-28 16:13:20 +00:00
|
|
|
|
2023-08-28 09:44:18 +00:00
|
|
|
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
2023-03-12 16:01:49 +02:00
|
|
|
"github.com/cloudbase/garm/params"
|
2022-04-28 16:13:20 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type contextFlags string
|
|
|
|
|
|
|
|
|
|
const (
|
2023-01-26 14:02:53 +01:00
|
|
|
isAdminKey contextFlags = "is_admin"
|
|
|
|
|
fullNameKey contextFlags = "full_name"
|
|
|
|
|
readMetricsKey contextFlags = "read_metrics"
|
2022-04-28 16:13:20 +00:00
|
|
|
// UserIDFlag is the User ID flag we set in the context
|
2024-07-02 22:26:12 +00:00
|
|
|
UserIDFlag contextFlags = "user_id"
|
|
|
|
|
isEnabledFlag contextFlags = "is_enabled"
|
|
|
|
|
jwtTokenFlag contextFlags = "jwt_token"
|
|
|
|
|
authExpiresFlag contextFlags = "auth_expires"
|
|
|
|
|
passwordGenerationFlag contextFlags = "password_generation"
|
2022-05-03 19:49:14 +00:00
|
|
|
|
2022-12-01 18:00:22 +02:00
|
|
|
instanceIDKey contextFlags = "id"
|
|
|
|
|
instanceNameKey contextFlags = "name"
|
|
|
|
|
instancePoolIDKey contextFlags = "pool_id"
|
|
|
|
|
instancePoolTypeKey contextFlags = "scope"
|
|
|
|
|
instanceEntityKey contextFlags = "entity"
|
|
|
|
|
instanceRunnerStatus contextFlags = "status"
|
2022-12-29 22:57:10 +00:00
|
|
|
instanceTokenFetched contextFlags = "tokenFetched"
|
2023-08-20 13:45:16 +00:00
|
|
|
instanceHasJITConfig contextFlags = "hasJITConfig"
|
2023-08-28 09:44:18 +00:00
|
|
|
instanceParams contextFlags = "instanceParams"
|
2025-05-19 19:45:45 +00:00
|
|
|
instanceForgeTypeKey contextFlags = "forge_type"
|
2022-04-28 16:13:20 +00:00
|
|
|
)
|
|
|
|
|
|
2025-05-19 19:45:45 +00:00
|
|
|
func SetInstanceForgeType(ctx context.Context, val string) context.Context {
|
|
|
|
|
return context.WithValue(ctx, instanceForgeTypeKey, val)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func InstanceForgeType(ctx context.Context) params.EndpointType {
|
|
|
|
|
elem := ctx.Value(instanceForgeTypeKey)
|
|
|
|
|
if elem == nil {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return elem.(params.EndpointType)
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-03 19:49:14 +00:00
|
|
|
func SetInstanceID(ctx context.Context, id string) context.Context {
|
|
|
|
|
return context.WithValue(ctx, instanceIDKey, id)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func InstanceID(ctx context.Context) string {
|
|
|
|
|
elem := ctx.Value(instanceIDKey)
|
|
|
|
|
if elem == nil {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return elem.(string)
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-29 22:57:10 +00:00
|
|
|
func SetInstanceTokenFetched(ctx context.Context, fetched bool) context.Context {
|
|
|
|
|
return context.WithValue(ctx, instanceTokenFetched, fetched)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func InstanceTokenFetched(ctx context.Context) bool {
|
|
|
|
|
elem := ctx.Value(instanceTokenFetched)
|
|
|
|
|
if elem == nil {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
return elem.(bool)
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-20 13:45:16 +00:00
|
|
|
func SetInstanceHasJITConfig(ctx context.Context, cfg map[string]string) context.Context {
|
|
|
|
|
return context.WithValue(ctx, instanceHasJITConfig, len(cfg) > 0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func InstanceHasJITConfig(ctx context.Context) bool {
|
|
|
|
|
elem := ctx.Value(instanceHasJITConfig)
|
|
|
|
|
if elem == nil {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
return elem.(bool)
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-28 09:44:18 +00:00
|
|
|
func SetInstanceParams(ctx context.Context, instance params.Instance) context.Context {
|
|
|
|
|
return context.WithValue(ctx, instanceParams, instance)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func InstanceParams(ctx context.Context) (params.Instance, error) {
|
|
|
|
|
elem := ctx.Value(instanceParams)
|
|
|
|
|
if elem == nil {
|
|
|
|
|
return params.Instance{}, runnerErrors.ErrNotFound
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
instanceParams, ok := elem.(params.Instance)
|
|
|
|
|
if !ok {
|
|
|
|
|
return params.Instance{}, runnerErrors.ErrNotFound
|
|
|
|
|
}
|
|
|
|
|
return instanceParams, nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-21 15:30:22 +00:00
|
|
|
func SetInstanceRunnerStatus(ctx context.Context, val params.RunnerStatus) context.Context {
|
2022-12-01 18:00:22 +02:00
|
|
|
return context.WithValue(ctx, instanceRunnerStatus, val)
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-21 15:30:22 +00:00
|
|
|
func InstanceRunnerStatus(ctx context.Context) params.RunnerStatus {
|
2022-12-01 18:00:22 +02:00
|
|
|
elem := ctx.Value(instanceRunnerStatus)
|
|
|
|
|
if elem == nil {
|
2023-07-21 15:30:22 +00:00
|
|
|
return params.RunnerPending
|
2022-12-01 18:00:22 +02:00
|
|
|
}
|
2023-07-21 15:30:22 +00:00
|
|
|
return elem.(params.RunnerStatus)
|
2022-12-01 18:00:22 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-03 19:49:14 +00:00
|
|
|
func SetInstanceName(ctx context.Context, val string) context.Context {
|
|
|
|
|
return context.WithValue(ctx, instanceNameKey, val)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func InstanceName(ctx context.Context) string {
|
|
|
|
|
elem := ctx.Value(instanceNameKey)
|
|
|
|
|
if elem == nil {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return elem.(string)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func SetInstancePoolID(ctx context.Context, val string) context.Context {
|
|
|
|
|
return context.WithValue(ctx, instancePoolIDKey, val)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func InstancePoolID(ctx context.Context) string {
|
|
|
|
|
elem := ctx.Value(instancePoolIDKey)
|
|
|
|
|
if elem == nil {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return elem.(string)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func SetInstancePoolType(ctx context.Context, val string) context.Context {
|
|
|
|
|
return context.WithValue(ctx, instancePoolTypeKey, val)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func InstancePoolType(ctx context.Context) string {
|
|
|
|
|
elem := ctx.Value(instancePoolTypeKey)
|
|
|
|
|
if elem == nil {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return elem.(string)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func SetInstanceEntity(ctx context.Context, val string) context.Context {
|
|
|
|
|
return context.WithValue(ctx, instanceEntityKey, val)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func InstanceEntity(ctx context.Context) string {
|
|
|
|
|
elem := ctx.Value(instanceEntityKey)
|
|
|
|
|
if elem == nil {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return elem.(string)
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-19 19:45:45 +00:00
|
|
|
func PopulateInstanceContext(ctx context.Context, instance params.Instance, claims *InstanceJWTClaims) context.Context {
|
2022-05-03 19:49:14 +00:00
|
|
|
ctx = SetInstanceID(ctx, instance.ID)
|
|
|
|
|
ctx = SetInstanceName(ctx, instance.Name)
|
|
|
|
|
ctx = SetInstancePoolID(ctx, instance.PoolID)
|
2022-12-01 18:00:22 +02:00
|
|
|
ctx = SetInstanceRunnerStatus(ctx, instance.RunnerStatus)
|
2022-12-29 22:57:10 +00:00
|
|
|
ctx = SetInstanceTokenFetched(ctx, instance.TokenFetched)
|
2023-08-20 13:45:16 +00:00
|
|
|
ctx = SetInstanceHasJITConfig(ctx, instance.JitConfiguration)
|
2023-08-28 09:44:18 +00:00
|
|
|
ctx = SetInstanceParams(ctx, instance)
|
2025-05-19 19:45:45 +00:00
|
|
|
ctx = SetInstanceForgeType(ctx, claims.ForgeType)
|
2022-05-03 19:49:14 +00:00
|
|
|
return ctx
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-28 16:13:20 +00:00
|
|
|
// PopulateContext sets the appropriate fields in the context, based on
|
|
|
|
|
// the user object
|
2024-07-02 22:26:12 +00:00
|
|
|
func PopulateContext(ctx context.Context, user params.User, authExpires *time.Time) context.Context {
|
2022-04-28 16:13:20 +00:00
|
|
|
ctx = SetUserID(ctx, user.ID)
|
|
|
|
|
ctx = SetAdmin(ctx, user.IsAdmin)
|
|
|
|
|
ctx = SetIsEnabled(ctx, user.Enabled)
|
|
|
|
|
ctx = SetFullName(ctx, user.FullName)
|
2024-07-02 22:26:12 +00:00
|
|
|
ctx = SetExpires(ctx, authExpires)
|
|
|
|
|
ctx = SetPasswordGeneration(ctx, user.Generation)
|
2022-04-28 16:13:20 +00:00
|
|
|
return ctx
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-02 22:26:12 +00:00
|
|
|
func SetExpires(ctx context.Context, expires *time.Time) context.Context {
|
|
|
|
|
if expires == nil {
|
|
|
|
|
return ctx
|
|
|
|
|
}
|
|
|
|
|
return context.WithValue(ctx, authExpiresFlag, expires)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Expires(ctx context.Context) *time.Time {
|
|
|
|
|
elem := ctx.Value(authExpiresFlag)
|
|
|
|
|
if elem == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return elem.(*time.Time)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func SetPasswordGeneration(ctx context.Context, val uint) context.Context {
|
|
|
|
|
return context.WithValue(ctx, passwordGenerationFlag, val)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func PasswordGeneration(ctx context.Context) uint {
|
|
|
|
|
elem := ctx.Value(passwordGenerationFlag)
|
|
|
|
|
if elem == nil {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
return elem.(uint)
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-28 16:13:20 +00:00
|
|
|
// SetFullName sets the user full name in the context
|
|
|
|
|
func SetFullName(ctx context.Context, fullName string) context.Context {
|
|
|
|
|
return context.WithValue(ctx, fullNameKey, fullName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FullName returns the full name from context
|
|
|
|
|
func FullName(ctx context.Context) string {
|
|
|
|
|
name := ctx.Value(fullNameKey)
|
|
|
|
|
if name == nil {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return name.(string)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetIsEnabled sets a flag indicating if account is enabled
|
|
|
|
|
func SetIsEnabled(ctx context.Context, enabled bool) context.Context {
|
|
|
|
|
return context.WithValue(ctx, isEnabledFlag, enabled)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IsEnabled returns the a boolean indicating if the enabled flag is
|
|
|
|
|
// set and is true or false
|
|
|
|
|
func IsEnabled(ctx context.Context) bool {
|
|
|
|
|
elem := ctx.Value(isEnabledFlag)
|
|
|
|
|
if elem == nil {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
return elem.(bool)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetAdmin sets the isAdmin flag on the context
|
|
|
|
|
func SetAdmin(ctx context.Context, isAdmin bool) context.Context {
|
|
|
|
|
return context.WithValue(ctx, isAdminKey, isAdmin)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IsAdmin returns a boolean indicating whether
|
|
|
|
|
// or not the context belongs to a logged in user
|
|
|
|
|
// and if that context has the admin flag set
|
|
|
|
|
func IsAdmin(ctx context.Context) bool {
|
|
|
|
|
elem := ctx.Value(isAdminKey)
|
|
|
|
|
if elem == nil {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
return elem.(bool)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetUserID sets the userID in the context
|
|
|
|
|
func SetUserID(ctx context.Context, userID string) context.Context {
|
|
|
|
|
return context.WithValue(ctx, UserIDFlag, userID)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// UserID returns the userID from the context
|
|
|
|
|
func UserID(ctx context.Context) string {
|
|
|
|
|
userID := ctx.Value(UserIDFlag)
|
|
|
|
|
if userID == nil {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return userID.(string)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetAdminContext will return an admin context. This can be used internally
|
|
|
|
|
// when fetching users.
|
2024-02-20 06:33:21 +01:00
|
|
|
func GetAdminContext(ctx context.Context) context.Context {
|
|
|
|
|
if ctx == nil {
|
|
|
|
|
ctx = context.Background()
|
|
|
|
|
}
|
2022-04-28 16:13:20 +00:00
|
|
|
ctx = SetUserID(ctx, "")
|
|
|
|
|
ctx = SetAdmin(ctx, true)
|
|
|
|
|
ctx = SetIsEnabled(ctx, true)
|
|
|
|
|
return ctx
|
|
|
|
|
}
|