Update authentication system for multi-tenant support: - API key management with tenant scoping - Permission checks for multi-tenant operations - Database layer with tenant isolation - Keychain integration with audit logging
212 lines
5.2 KiB
Go
212 lines
5.2 KiB
Go
package auth
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// Permission constants for type safety
|
|
const (
|
|
// Job permissions
|
|
PermissionJobsCreate = "jobs:create"
|
|
PermissionJobsRead = "jobs:read"
|
|
PermissionJobsUpdate = "jobs:update"
|
|
PermissionJobsDelete = "jobs:delete"
|
|
|
|
// Data permissions
|
|
PermissionDataCreate = "data:create"
|
|
PermissionDataRead = "data:read"
|
|
PermissionDataUpdate = "data:update"
|
|
PermissionDataDelete = "data:delete"
|
|
|
|
// Model permissions
|
|
PermissionModelsCreate = "models:create"
|
|
PermissionModelsRead = "models:read"
|
|
PermissionModelsUpdate = "models:update"
|
|
PermissionModelsDelete = "models:delete"
|
|
|
|
// System permissions
|
|
PermissionSystemConfig = "system:config"
|
|
PermissionSystemMetrics = "system:metrics"
|
|
PermissionSystemLogs = "system:logs"
|
|
PermissionSystemUsers = "system:users"
|
|
|
|
// Wildcard permission
|
|
PermissionAll = "*"
|
|
)
|
|
|
|
// Role constants
|
|
const (
|
|
RoleAdmin = "admin"
|
|
RoleDataScientist = "data_scientist"
|
|
RoleDataEngineer = "data_engineer"
|
|
RoleViewer = "viewer"
|
|
RoleOperator = "operator"
|
|
)
|
|
|
|
// PermissionGroup represents a group of related permissions
|
|
type PermissionGroup struct {
|
|
Name string
|
|
Description string
|
|
Permissions []string
|
|
}
|
|
|
|
// PermissionGroups defines built-in permission groups.
|
|
var PermissionGroups = map[string]PermissionGroup{
|
|
"full_access": {
|
|
Name: "Full Access",
|
|
Permissions: []string{PermissionAll},
|
|
Description: "Complete system access",
|
|
},
|
|
"job_management": {
|
|
Name: "Job Management",
|
|
Permissions: []string{
|
|
PermissionJobsCreate,
|
|
PermissionJobsRead,
|
|
PermissionJobsUpdate,
|
|
PermissionJobsDelete,
|
|
},
|
|
Description: "Create, read, update, and delete ML jobs",
|
|
},
|
|
"data_access": {
|
|
Name: "Data Access",
|
|
Permissions: []string{
|
|
PermissionDataRead,
|
|
PermissionDataCreate,
|
|
PermissionDataUpdate,
|
|
PermissionDataDelete,
|
|
},
|
|
Description: "Access and manage datasets",
|
|
},
|
|
"readonly": {
|
|
Name: "Read Only",
|
|
Permissions: []string{
|
|
PermissionJobsRead,
|
|
PermissionDataRead,
|
|
PermissionModelsRead,
|
|
PermissionSystemMetrics,
|
|
},
|
|
Description: "View-only access to system resources",
|
|
},
|
|
"system_admin": {
|
|
Name: "System Administration",
|
|
Permissions: []string{
|
|
PermissionSystemConfig,
|
|
PermissionSystemLogs,
|
|
PermissionSystemUsers,
|
|
PermissionSystemMetrics,
|
|
},
|
|
Description: "System configuration and user management",
|
|
},
|
|
}
|
|
|
|
// GetPermissionGroup returns a permission group by name
|
|
func GetPermissionGroup(name string) (PermissionGroup, bool) {
|
|
group, exists := PermissionGroups[name]
|
|
return group, exists
|
|
}
|
|
|
|
// ValidatePermission checks if a permission string is valid
|
|
func ValidatePermission(permission string) error {
|
|
if permission == PermissionAll {
|
|
return nil
|
|
}
|
|
|
|
// Check if permission matches known patterns
|
|
validPrefixes := []string{"jobs:", "data:", "models:", "system:"}
|
|
for _, prefix := range validPrefixes {
|
|
if strings.HasPrefix(permission, prefix) {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf("invalid permission format: %s", permission)
|
|
}
|
|
|
|
// ValidateRole checks if a role is valid
|
|
func ValidateRole(role string) error {
|
|
validRoles := []string{RoleAdmin, RoleDataScientist, RoleDataEngineer, RoleViewer, RoleOperator}
|
|
for _, validRole := range validRoles {
|
|
if role == validRole {
|
|
return nil
|
|
}
|
|
}
|
|
return fmt.Errorf("invalid role: %s", role)
|
|
}
|
|
|
|
// ExpandPermissionGroups converts permission group names to actual permissions
|
|
func ExpandPermissionGroups(groups []string) ([]string, error) {
|
|
var permissions []string
|
|
|
|
for _, groupName := range groups {
|
|
if groupName == PermissionAll {
|
|
return []string{PermissionAll}, nil
|
|
}
|
|
|
|
group, exists := GetPermissionGroup(groupName)
|
|
if !exists {
|
|
return nil, fmt.Errorf("unknown permission group: %s", groupName)
|
|
}
|
|
|
|
permissions = append(permissions, group.Permissions...)
|
|
}
|
|
|
|
// Remove duplicates
|
|
unique := make(map[string]bool)
|
|
for _, perm := range permissions {
|
|
unique[perm] = true
|
|
}
|
|
|
|
result := make([]string, 0, len(unique))
|
|
for perm := range unique {
|
|
result = append(result, perm)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// PermissionCheckResult represents the result of a permission check
|
|
type PermissionCheckResult struct {
|
|
Permission string `json:"permission"`
|
|
User string `json:"user"`
|
|
Roles []string `json:"roles"`
|
|
Missing []string `json:"missing,omitempty"`
|
|
Allowed bool `json:"allowed"`
|
|
}
|
|
|
|
// CheckMultiplePermissions checks multiple permissions at once
|
|
func (u *User) CheckMultiplePermissions(permissions []string) []PermissionCheckResult {
|
|
results := make([]PermissionCheckResult, len(permissions))
|
|
|
|
for i, permission := range permissions {
|
|
allowed := u.HasPermission(permission)
|
|
missing := []string{}
|
|
if !allowed {
|
|
missing = []string{permission}
|
|
}
|
|
|
|
results[i] = PermissionCheckResult{
|
|
Allowed: allowed,
|
|
Permission: permission,
|
|
User: u.Name,
|
|
Roles: u.Roles,
|
|
Missing: missing,
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
// GetEffectivePermissions returns all effective permissions for a user
|
|
func (u *User) GetEffectivePermissions() []string {
|
|
if u.Permissions[PermissionAll] {
|
|
return []string{PermissionAll}
|
|
}
|
|
|
|
permissions := make([]string, 0, len(u.Permissions))
|
|
for perm := range u.Permissions {
|
|
permissions = append(permissions, perm)
|
|
}
|
|
|
|
return permissions
|
|
}
|