Files
scriptos fd13e67aef
Release Docker Image / Build & Push Docker Image (release) Failing after 1m30s
Release: v0.1.0-alpha
2026-04-05 16:56:16 +02:00

181 lines
7.8 KiB
Go

// Keywarden - Centralized SSH Key Management and Deployment
// Copyright (C) 2026 Patrick Asmus (scriptos)
// SPDX-License-Identifier: AGPL-3.0-or-later
package models
import "time"
// User represents a registered user
type User struct {
ID int64 `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
PasswordHash string `json:"-"`
Role string `json:"role"`
MFAEnabled bool `json:"mfa_enabled"`
MFASecret string `json:"-"`
Theme string `json:"theme"` // "auto", "light", "dark"
EmailNotifyLogin bool `json:"email_notify_login"`
AvatarBase64 string `json:"avatar_base64"` // base64-encoded profile picture (data URI)
MustChangePassword bool `json:"must_change_password"` // force password change on next login
FailedLoginAttempts int `json:"failed_login_attempts"` // consecutive failed login attempts
LockedUntil *time.Time `json:"locked_until"` // account locked until this time
LastLoginAt *time.Time `json:"last_login_at"` // last successful login
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// PasswordPolicy holds the password complexity requirements
type PasswordPolicy struct {
MinLength int `json:"min_length"`
RequireUpper bool `json:"require_upper"`
RequireLower bool `json:"require_lower"`
RequireDigit bool `json:"require_digit"`
RequireSpecial bool `json:"require_special"`
}
// SSHKey represents a stored SSH key pair
type SSHKey struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
Name string `json:"name"`
KeyType string `json:"key_type"` // "rsa", "ed25519", or "ed448"
Bits int `json:"bits"` // 2048, 4096 for RSA; 256 for Ed25519; 456 for Ed448
Fingerprint string `json:"fingerprint"`
PublicKey string `json:"public_key"`
PrivateKeyEnc string `json:"-"` // encrypted private key
PassphraseEnc string `json:"-"` // encrypted passphrase (optional)
CreatedAt time.Time `json:"created_at"`
}
// SSHKeyWithOwner extends SSHKey with the owner's username for admin views
type SSHKeyWithOwner struct {
SSHKey
OwnerUsername string `json:"owner_username"`
}
// Server represents a remote SSH server
type Server struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
Name string `json:"name"`
Hostname string `json:"hostname"`
Port int `json:"port"`
Username string `json:"username"`
Description string `json:"description"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// KeyDeployment represents a key deployed to a server
type KeyDeployment struct {
ID int64 `json:"id"`
SSHKeyID int64 `json:"ssh_key_id"`
ServerID int64 `json:"server_id"`
DeployedAt time.Time `json:"deployed_at"`
Status string `json:"status"` // "pending", "success", "failed"
Message string `json:"message"`
}
// ServerGroup represents a group of servers
type ServerGroup struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
Name string `json:"name"`
Description string `json:"description"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// ServerGroupWithCount extends ServerGroup with the number of member servers
type ServerGroupWithCount struct {
ServerGroup
ServerCount int `json:"server_count"`
}
// AuditLog represents an audit trail entry
type AuditLog struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
Action string `json:"action"`
Details string `json:"details"`
IPAddress string `json:"ip_address"`
CreatedAt time.Time `json:"created_at"`
}
// CronJob represents a scheduled temporary access job
type CronJob struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
Name string `json:"name"`
SSHKeyID int64 `json:"ssh_key_id"`
ServerID int64 `json:"server_id"` // 0 if targeting a group
GroupID int64 `json:"group_id"` // 0 if targeting a single server
Schedule string `json:"schedule"` // "once", "hourly", "daily", "weekly", "monthly"
ScheduledAt time.Time `json:"scheduled_at"`
NextRun time.Time `json:"next_run"`
LastRun *time.Time `json:"last_run"`
RemoveAfterMin int `json:"remove_after_min"` // 0 = permanent
Status string `json:"status"` // "active", "paused", "running", "done", "failed"
Message string `json:"message"`
Timezone string `json:"timezone"` // IANA timezone, e.g. "Europe/Berlin"
TimeOfDay string `json:"time_of_day"` // "HH:MM" for daily/weekly/monthly
DayOfWeek int `json:"day_of_week"` // 0=Sunday..6=Saturday (-1=unset)
DayOfMonth int `json:"day_of_month"` // 1-31 (0=unset)
MinuteOfHour int `json:"minute_of_hour"` // 0-59 for hourly schedule
TargetUserID int64 `json:"target_user_id"` // KeyWarden user to grant access
SystemUser string `json:"system_user"` // system user on target host
Sudo bool `json:"sudo"` // grant sudo rights
CreateUser bool `json:"create_user"` // create system user if missing
InitialPassword string `json:"initial_password"` // encrypted initial password for created user
ExpiryAction string `json:"expiry_action"` // "remove_key", "disable_user", "delete_user"
CreatedAt time.Time `json:"created_at"`
}
// CronJobDisplay extends CronJob with resolved names for UI display
type CronJobDisplay struct {
CronJob
KeyName string `json:"key_name"`
TargetName string `json:"target_name"`
TargetType string `json:"target_type"` // "host" or "group"
TargetUsername string `json:"target_username"` // KeyWarden username
}
// AccessAssignment represents an access assignment (user+key → host/group)
type AccessAssignment struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"` // Keywarden user
SSHKeyID int64 `json:"ssh_key_id"` // SSH key to deploy
ServerID int64 `json:"server_id"` // target host (0 if group)
GroupID int64 `json:"group_id"` // target group (0 if single host)
SystemUser string `json:"system_user"` // system user on target host
DesiredState string `json:"desired_state"` // "present" or "absent"
Sudo bool `json:"sudo"` // grant sudo rights
CreateUser bool `json:"create_user"` // create system user if missing
InitialPassword string `json:"initial_password"` // encrypted initial password for created user
Status string `json:"status"` // "pending", "synced", "failed"
LastSyncAt *time.Time `json:"last_sync_at"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// AccessAssignmentDisplay extends AccessAssignment with resolved names for UI
type AccessAssignmentDisplay struct {
AccessAssignment
Username string `json:"username"`
KeyName string `json:"key_name"`
TargetName string `json:"target_name"`
TargetType string `json:"target_type"` // "host" or "group"
}
// InvitationToken represents a one-time invitation link for a new user
type InvitationToken struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
Token string `json:"token"`
ExpiresAt time.Time `json:"expires_at"`
Used bool `json:"used"`
CreatedAt time.Time `json:"created_at"`
}