2
0
Files
gitcaddy-vault/plugin.go
logikonline d9c35526bc
Some checks failed
Build and Release / Lint (push) Failing after 24s
Build and Release / Tests (push) Failing after 23s
Build and Release / Create Release (push) Has been skipped
feat(crypto): add key source tracking and fallback detection
Adds tracking of master key source (app.ini, env var, file, or Gitea SECRET_KEY fallback) and exposes methods to check if fallback key is in use. This enables better visibility into which key configuration is active and helps identify when the system is using the less secure fallback option.
2026-02-04 13:47:33 -05:00

170 lines
4.8 KiB
Go

// Copyright 2026 MarketAlly. All rights reserved.
// Business Source License 1.1 - See LICENSE file for details.
package vault
import (
"context"
"git.marketally.com/gitcaddy/gitcaddy-vault/crypto"
"git.marketally.com/gitcaddy/gitcaddy-vault/license"
"git.marketally.com/gitcaddy/gitcaddy-vault/models"
"git.marketally.com/gitcaddy/gitcaddy-vault/routes"
"code.gitcaddy.com/server/v3/modules/log"
"code.gitcaddy.com/server/v3/modules/plugins"
"xorm.io/xorm"
)
const PluginName = "vault"
// Version can be set at build time via ldflags:
// -ldflags "-X git.marketally.com/gitcaddy/gitcaddy-vault.Version=v1.0.30"
var Version = "dev"
// init automatically registers the vault when this package is imported
func init() {
// Set version in routes package
routes.Version = Version
Register()
}
// VaultPlugin is the main entry point for the GitCaddy Vault plugin
type VaultPlugin struct {
license *license.Manager
}
// New creates a new VaultPlugin instance
func New() *VaultPlugin {
return &VaultPlugin{
license: license.NewManager(),
}
}
// Name returns the plugin name
func (p *VaultPlugin) Name() string {
return PluginName
}
// Version returns the plugin version
func (p *VaultPlugin) Version() string {
return Version
}
// Description returns the plugin description
func (p *VaultPlugin) Description() string {
return "Secure secrets management for GitCaddy repositories"
}
// Init initializes the plugin
func (p *VaultPlugin) Init(ctx context.Context) error {
log.Info("Initializing GitCaddy Vault plugin v%s", Version)
// Load master encryption key
if err := crypto.LoadMasterKey(); err != nil {
log.Warn("Vault master key not configured: %v", err)
log.Warn("Vault encryption will not work. Set MASTER_KEY in [vault] section of app.ini or GITCADDY_VAULT_KEY environment variable.")
}
// Load and validate license
if err := p.license.Load(); err != nil {
log.Warn("Vault license not found or invalid: %v", err)
log.Warn("Vault features will be disabled. Visit https://gitcaddy.com/vault to purchase a license.")
} else {
info := p.license.Info()
log.Info("Vault licensed: tier=%s, expires=%v", info.Tier, info.ExpiresAt)
}
return nil
}
// Shutdown cleans up the plugin
func (p *VaultPlugin) Shutdown(ctx context.Context) error {
log.Info("Shutting down GitCaddy Vault plugin")
return nil
}
// RegisterModels returns the database models for this plugin
func (p *VaultPlugin) RegisterModels() []any {
return []any{
new(models.VaultSecret),
new(models.VaultSecretVersion),
new(models.VaultAuditEntry),
new(models.VaultToken),
new(models.VaultRepoKey),
}
}
// Migrate runs database migrations for this plugin
func (p *VaultPlugin) Migrate(ctx context.Context, x *xorm.Engine) error {
return x.Sync(p.RegisterModels()...)
}
// RegisterRepoWebRoutes adds vault routes under /{owner}/{repo}/vault
func (p *VaultPlugin) RegisterRepoWebRoutes(r plugins.PluginRouter) {
routes.RegisterRepoWebRoutes(r, p.license)
}
// RegisterRepoAPIRoutes adds vault API routes under /api/v1/repos/{owner}/{repo}/vault
func (p *VaultPlugin) RegisterRepoAPIRoutes(r plugins.PluginRouter) {
routes.RegisterRepoAPIRoutes(r, p.license)
}
// ValidateLicense validates the plugin license
func (p *VaultPlugin) ValidateLicense(ctx context.Context) error {
return p.license.Validate()
}
// LicenseInfo returns current license information
func (p *VaultPlugin) LicenseInfo() *plugins.LicenseInfo {
info := p.license.Info()
if info == nil {
return nil
}
return &plugins.LicenseInfo{
Valid: info.Valid,
Tier: info.Tier,
CustomerID: info.CustomerEmail,
ExpiresAt: info.ExpiresAt,
GracePeriod: info.GracePeriod,
}
}
// IsConfigured returns true if the vault has a master key configured
func (p *VaultPlugin) IsConfigured() bool {
return crypto.HasMasterKey()
}
// ConfigurationError returns the configuration error message if vault is not properly configured
func (p *VaultPlugin) ConfigurationError() string {
if !crypto.HasMasterKey() {
return "no master key configured - add MASTER_KEY to [vault] section in app.ini"
}
return ""
}
// IsUsingFallbackKey returns true if the vault is using Gitea's SECRET_KEY
// as the encryption key instead of an explicit vault-specific key.
func (p *VaultPlugin) IsUsingFallbackKey() bool {
return crypto.IsUsingFallbackKey()
}
// KeySource returns a human-readable description of where the master key was loaded from.
func (p *VaultPlugin) KeySource() string {
return crypto.KeySource()
}
// Ensure VaultPlugin implements all required interfaces
var (
_ plugins.Plugin = (*VaultPlugin)(nil)
_ plugins.DatabasePlugin = (*VaultPlugin)(nil)
_ plugins.RepoRoutesPlugin = (*VaultPlugin)(nil)
_ plugins.LicensedPlugin = (*VaultPlugin)(nil)
)
// Register registers the vault plugin with GitCaddy
func Register() {
plugins.Register(New())
}