mirror of
https://github.com/GlueOps/autoglue.git
synced 2026-02-13 04:40:05 +01:00
feat: add credentials management
Signed-off-by: allanice001 <allanice001@gmail.com>
This commit is contained in:
138
internal/handlers/dto/credentials.go
Normal file
138
internal/handlers/dto/credentials.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
// RawJSON is a swagger-friendly wrapper for json.RawMessage.
|
||||
type RawJSON json.RawMessage
|
||||
|
||||
var Validate = validator.New()
|
||||
|
||||
func init() {
|
||||
_ = Validate.RegisterValidation("awsarn", func(fl validator.FieldLevel) bool {
|
||||
v := fl.Field().String()
|
||||
return len(v) > 10 && len(v) < 2048 && len(v) >= 4 && v[:4] == "arn:"
|
||||
})
|
||||
}
|
||||
|
||||
/*** Shapes for secrets ***/
|
||||
|
||||
type AWSCredential struct {
|
||||
AccessKeyID string `json:"access_key_id" validate:"required,alphanum,len=20"`
|
||||
SecretAccessKey string `json:"secret_access_key" validate:"required"`
|
||||
Region string `json:"region" validate:"omitempty"`
|
||||
}
|
||||
|
||||
type BasicAuth struct {
|
||||
Username string `json:"username" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
}
|
||||
|
||||
type APIToken struct {
|
||||
Token string `json:"token" validate:"required"`
|
||||
}
|
||||
|
||||
type OAuth2Credential struct {
|
||||
ClientID string `json:"client_id" validate:"required"`
|
||||
ClientSecret string `json:"client_secret" validate:"required"`
|
||||
RefreshToken string `json:"refresh_token" validate:"required"`
|
||||
}
|
||||
|
||||
/*** Shapes for scopes ***/
|
||||
|
||||
type AWSProviderScope struct{}
|
||||
|
||||
type AWSServiceScope struct {
|
||||
Service string `json:"service" validate:"required,oneof=route53 s3 ec2 iam rds dynamodb"`
|
||||
}
|
||||
|
||||
type AWSResourceScope struct {
|
||||
ARN string `json:"arn" validate:"required,awsarn"`
|
||||
}
|
||||
|
||||
/*** Registries ***/
|
||||
|
||||
type ProviderDef struct {
|
||||
New func() any
|
||||
Validate func(any) error
|
||||
}
|
||||
|
||||
type ScopeDef struct {
|
||||
New func() any
|
||||
Validate func(any) error
|
||||
Specificity int // 0=provider, 1=service, 2=resource
|
||||
}
|
||||
|
||||
// Secret shapes per provider/kind/version
|
||||
|
||||
var CredentialRegistry = map[string]map[string]map[int]ProviderDef{
|
||||
"aws": {
|
||||
"aws_access_key": {
|
||||
1: {New: func() any { return &AWSCredential{} }, Validate: func(x any) error { return Validate.Struct(x) }},
|
||||
},
|
||||
},
|
||||
"cloudflare": {"api_token": {1: {New: func() any { return &APIToken{} }, Validate: func(x any) error { return Validate.Struct(x) }}}},
|
||||
"hetzner": {"api_token": {1: {New: func() any { return &APIToken{} }, Validate: func(x any) error { return Validate.Struct(x) }}}},
|
||||
"digitalocean": {"api_token": {1: {New: func() any { return &APIToken{} }, Validate: func(x any) error { return Validate.Struct(x) }}}},
|
||||
"generic": {
|
||||
"basic_auth": {1: {New: func() any { return &BasicAuth{} }, Validate: func(x any) error { return Validate.Struct(x) }}},
|
||||
"oauth2": {1: {New: func() any { return &OAuth2Credential{} }, Validate: func(x any) error { return Validate.Struct(x) }}},
|
||||
},
|
||||
}
|
||||
|
||||
// Scope shapes per provider/scopeKind/version
|
||||
|
||||
var ScopeRegistry = map[string]map[string]map[int]ScopeDef{
|
||||
"aws": {
|
||||
"provider": {1: {New: func() any { return &AWSProviderScope{} }, Validate: func(any) error { return nil }, Specificity: 0}},
|
||||
"service": {1: {New: func() any { return &AWSServiceScope{} }, Validate: func(x any) error { return Validate.Struct(x) }, Specificity: 1}},
|
||||
"resource": {1: {New: func() any { return &AWSResourceScope{} }, Validate: func(x any) error { return Validate.Struct(x) }, Specificity: 2}},
|
||||
},
|
||||
}
|
||||
|
||||
/*** API DTOs used by swagger ***/
|
||||
|
||||
// CreateCredentialRequest represents the POST /credentials payload
|
||||
type CreateCredentialRequest struct {
|
||||
Provider string `json:"provider" validate:"required,oneof=aws cloudflare hetzner digitalocean generic"`
|
||||
Kind string `json:"kind" validate:"required"` // aws_access_key, api_token, basic_auth, oauth2
|
||||
SchemaVersion int `json:"schema_version" validate:"required,gte=1"` // secret schema version
|
||||
Name string `json:"name" validate:"omitempty,max=100"` // human label
|
||||
ScopeKind string `json:"scope_kind" validate:"required,oneof=provider service resource"`
|
||||
ScopeVersion int `json:"scope_version" validate:"required,gte=1"` // scope schema version
|
||||
Scope RawJSON `json:"scope" validate:"required" swaggertype:"object"` // {"service":"route53"} or {"arn":"..."}
|
||||
AccountID string `json:"account_id,omitempty" validate:"omitempty,max=32"`
|
||||
Region string `json:"region,omitempty" validate:"omitempty,max=32"`
|
||||
Secret RawJSON `json:"secret" validate:"required" swaggertype:"object"` // encrypted later
|
||||
}
|
||||
|
||||
// UpdateCredentialRequest represents PATCH /credentials/{id}
|
||||
type UpdateCredentialRequest struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
AccountID *string `json:"account_id,omitempty"`
|
||||
Region *string `json:"region,omitempty"`
|
||||
ScopeKind *string `json:"scope_kind,omitempty"`
|
||||
ScopeVersion *int `json:"scope_version,omitempty"`
|
||||
Scope *RawJSON `json:"scope,omitempty" swaggertype:"object"`
|
||||
Secret *RawJSON `json:"secret,omitempty" swaggertype:"object"` // set if rotating
|
||||
|
||||
}
|
||||
|
||||
// CredentialOut is what we return (no secrets)
|
||||
type CredentialOut struct {
|
||||
ID string `json:"id"`
|
||||
Provider string `json:"provider"`
|
||||
Kind string `json:"kind"`
|
||||
SchemaVersion int `json:"schema_version"`
|
||||
Name string `json:"name"`
|
||||
ScopeKind string `json:"scope_kind"`
|
||||
ScopeVersion int `json:"scope_version"`
|
||||
Scope RawJSON `json:"scope" swaggertype:"object"`
|
||||
AccountID string `json:"account_id,omitempty"`
|
||||
Region string `json:"region,omitempty"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
Reference in New Issue
Block a user