Add service interface methods to VaultPlugin that delegate to the standalone service functions. This allows the server's vault_service to use GetPlugin() and call methods directly on the plugin. Methods implemented: - ListSecrets, GetSecret, GetSecretValue, CreateSecret, UpdateSecret - DeleteSecret, RestoreSecret, RollbackSecret - ListVersions - ListTokens, CreateToken, RevokeToken, ValidateToken - ListAuditEntries 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
288 lines
8.6 KiB
Go
288 lines
8.6 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/services"
|
|
|
|
vault_service "code.gitcaddy.com/server/v3/services/vault"
|
|
)
|
|
|
|
// Ensure VaultPlugin implements the vault service Plugin interface
|
|
var _ vault_service.Plugin = (*VaultPlugin)(nil)
|
|
|
|
// ListSecrets lists all secrets for a repository
|
|
func (p *VaultPlugin) ListSecrets(ctx context.Context, repoID int64, includeDeleted bool) ([]vault_service.Secret, error) {
|
|
secrets, err := services.ListSecrets(ctx, repoID, includeDeleted)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
result := make([]vault_service.Secret, len(secrets))
|
|
for i, s := range secrets {
|
|
result[i] = vault_service.Secret{
|
|
ID: s.ID,
|
|
RepoID: s.RepoID,
|
|
Name: s.Name,
|
|
Description: s.Description,
|
|
Type: string(s.Type),
|
|
CurrentVersion: s.CurrentVersion,
|
|
CreatedUnix: int64(s.CreatedUnix),
|
|
UpdatedUnix: int64(s.UpdatedUnix),
|
|
DeletedUnix: int64(s.DeletedUnix),
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// GetSecret returns a secret by name
|
|
func (p *VaultPlugin) GetSecret(ctx context.Context, repoID int64, name string) (*vault_service.Secret, error) {
|
|
s, err := services.GetSecret(ctx, repoID, name)
|
|
if err != nil {
|
|
if err == services.ErrSecretNotFound {
|
|
return nil, vault_service.ErrSecretNotFound
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
return &vault_service.Secret{
|
|
ID: s.ID,
|
|
RepoID: s.RepoID,
|
|
Name: s.Name,
|
|
Description: s.Description,
|
|
Type: string(s.Type),
|
|
CurrentVersion: s.CurrentVersion,
|
|
CreatedUnix: int64(s.CreatedUnix),
|
|
UpdatedUnix: int64(s.UpdatedUnix),
|
|
DeletedUnix: int64(s.DeletedUnix),
|
|
}, nil
|
|
}
|
|
|
|
// GetSecretValue returns the decrypted value of a secret
|
|
func (p *VaultPlugin) GetSecretValue(ctx context.Context, repoID int64, name string, version int) (string, error) {
|
|
return services.GetSecretValue(ctx, repoID, name, version)
|
|
}
|
|
|
|
// CreateSecret creates a new secret
|
|
func (p *VaultPlugin) CreateSecret(ctx context.Context, repoID int64, opts vault_service.CreateSecretOptions) (*vault_service.Secret, error) {
|
|
s, err := services.CreateSecret(ctx, repoID, services.CreateSecretOptions{
|
|
Name: opts.Name,
|
|
Description: opts.Description,
|
|
Type: opts.Type,
|
|
Value: opts.Value,
|
|
CreatorID: opts.CreatorID,
|
|
})
|
|
if err != nil {
|
|
if err == services.ErrSecretExists {
|
|
return nil, vault_service.ErrSecretExists
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
return &vault_service.Secret{
|
|
ID: s.ID,
|
|
RepoID: s.RepoID,
|
|
Name: s.Name,
|
|
Description: s.Description,
|
|
Type: string(s.Type),
|
|
CurrentVersion: s.CurrentVersion,
|
|
CreatedUnix: int64(s.CreatedUnix),
|
|
UpdatedUnix: int64(s.UpdatedUnix),
|
|
DeletedUnix: int64(s.DeletedUnix),
|
|
}, nil
|
|
}
|
|
|
|
// UpdateSecret updates an existing secret
|
|
func (p *VaultPlugin) UpdateSecret(ctx context.Context, repoID int64, name string, opts vault_service.UpdateSecretOptions) (*vault_service.Secret, error) {
|
|
s, err := services.UpdateSecret(ctx, repoID, name, services.UpdateSecretOptions{
|
|
Type: opts.Type,
|
|
Value: opts.Value,
|
|
Comment: opts.Comment,
|
|
UpdaterID: opts.UpdaterID,
|
|
})
|
|
if err != nil {
|
|
if err == services.ErrSecretNotFound {
|
|
return nil, vault_service.ErrSecretNotFound
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
return &vault_service.Secret{
|
|
ID: s.ID,
|
|
RepoID: s.RepoID,
|
|
Name: s.Name,
|
|
Description: s.Description,
|
|
Type: string(s.Type),
|
|
CurrentVersion: s.CurrentVersion,
|
|
CreatedUnix: int64(s.CreatedUnix),
|
|
UpdatedUnix: int64(s.UpdatedUnix),
|
|
DeletedUnix: int64(s.DeletedUnix),
|
|
}, nil
|
|
}
|
|
|
|
// DeleteSecret soft-deletes a secret
|
|
func (p *VaultPlugin) DeleteSecret(ctx context.Context, repoID int64, name string, userID int64) error {
|
|
err := services.DeleteSecret(ctx, repoID, name, userID)
|
|
if err == services.ErrSecretNotFound {
|
|
return vault_service.ErrSecretNotFound
|
|
}
|
|
return err
|
|
}
|
|
|
|
// RestoreSecret restores a soft-deleted secret
|
|
func (p *VaultPlugin) RestoreSecret(ctx context.Context, repoID int64, name string) error {
|
|
err := services.RestoreSecret(ctx, repoID, name)
|
|
if err == services.ErrSecretNotFound {
|
|
return vault_service.ErrSecretNotFound
|
|
}
|
|
return err
|
|
}
|
|
|
|
// RollbackSecret rolls back a secret to a previous version
|
|
func (p *VaultPlugin) RollbackSecret(ctx context.Context, repoID int64, name string, version int, userID int64) error {
|
|
err := services.RollbackSecret(ctx, repoID, name, version, userID)
|
|
if err == services.ErrSecretNotFound {
|
|
return vault_service.ErrSecretNotFound
|
|
}
|
|
if err == services.ErrVersionNotFound {
|
|
return vault_service.ErrSecretNotFound // Map to generic not found
|
|
}
|
|
return err
|
|
}
|
|
|
|
// ListVersions lists all versions of a secret
|
|
func (p *VaultPlugin) ListVersions(ctx context.Context, repoID int64, name string) ([]vault_service.SecretVersion, error) {
|
|
versions, err := services.ListVersions(ctx, repoID, name)
|
|
if err != nil {
|
|
if err == services.ErrSecretNotFound {
|
|
return nil, vault_service.ErrSecretNotFound
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
result := make([]vault_service.SecretVersion, len(versions))
|
|
for i, v := range versions {
|
|
result[i] = vault_service.SecretVersion{
|
|
ID: v.ID,
|
|
SecretID: v.SecretID,
|
|
Version: v.Version,
|
|
CreatorID: v.CreatedBy,
|
|
Comment: v.Comment,
|
|
CreatedUnix: int64(v.CreatedUnix),
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// ListTokens lists all tokens for a repository
|
|
func (p *VaultPlugin) ListTokens(ctx context.Context, repoID int64) ([]vault_service.Token, error) {
|
|
tokens, err := services.ListTokens(ctx, repoID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
result := make([]vault_service.Token, len(tokens))
|
|
for i, t := range tokens {
|
|
result[i] = vault_service.Token{
|
|
ID: t.ID,
|
|
RepoID: t.RepoID,
|
|
Description: t.Description,
|
|
Scope: string(t.Scope),
|
|
ExpiresUnix: int64(t.ExpiresUnix),
|
|
LastUsedUnix: int64(t.LastUsedUnix),
|
|
IsRevoked: t.IsRevoked(),
|
|
IsExpired: t.IsExpired(),
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// CreateToken creates a new CI/CD token
|
|
func (p *VaultPlugin) CreateToken(ctx context.Context, repoID int64, opts vault_service.CreateTokenOptions) (*vault_service.Token, string, error) {
|
|
t, rawToken, err := services.CreateToken(ctx, repoID, services.CreateTokenOptions{
|
|
Description: opts.Description,
|
|
Scope: opts.Scope,
|
|
TTL: opts.TTL,
|
|
CreatorID: opts.CreatorID,
|
|
})
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
|
|
return &vault_service.Token{
|
|
ID: t.ID,
|
|
RepoID: t.RepoID,
|
|
Description: t.Description,
|
|
Scope: string(t.Scope),
|
|
ExpiresUnix: int64(t.ExpiresUnix),
|
|
LastUsedUnix: int64(t.LastUsedUnix),
|
|
IsRevoked: t.IsRevoked(),
|
|
IsExpired: t.IsExpired(),
|
|
}, rawToken, nil
|
|
}
|
|
|
|
// RevokeToken revokes a token
|
|
func (p *VaultPlugin) RevokeToken(ctx context.Context, repoID, tokenID int64) error {
|
|
err := services.RevokeToken(ctx, repoID, tokenID)
|
|
if err == services.ErrTokenNotFound {
|
|
return vault_service.ErrTokenNotFound
|
|
}
|
|
return err
|
|
}
|
|
|
|
// ValidateToken validates a token for a specific action
|
|
func (p *VaultPlugin) ValidateToken(ctx context.Context, rawToken, action, secretName string) (*vault_service.Token, error) {
|
|
t, err := services.ValidateToken(ctx, rawToken, action, secretName)
|
|
if err != nil {
|
|
switch err {
|
|
case services.ErrTokenNotFound, services.ErrInvalidToken:
|
|
return nil, vault_service.ErrInvalidToken
|
|
case services.ErrTokenExpired:
|
|
return nil, vault_service.ErrTokenExpired
|
|
case services.ErrTokenRevoked:
|
|
return nil, vault_service.ErrTokenNotFound
|
|
case services.ErrAccessDenied:
|
|
return nil, vault_service.ErrAccessDenied
|
|
default:
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return &vault_service.Token{
|
|
ID: t.ID,
|
|
RepoID: t.RepoID,
|
|
Description: t.Description,
|
|
Scope: string(t.Scope),
|
|
ExpiresUnix: int64(t.ExpiresUnix),
|
|
LastUsedUnix: int64(t.LastUsedUnix),
|
|
IsRevoked: t.IsRevoked(),
|
|
IsExpired: t.IsExpired(),
|
|
}, nil
|
|
}
|
|
|
|
// ListAuditEntries lists audit entries for a repository
|
|
func (p *VaultPlugin) ListAuditEntries(ctx context.Context, repoID int64, page, pageSize int) ([]vault_service.AuditEntry, int64, error) {
|
|
entries, total, err := services.ListAuditEntries(ctx, repoID, page, pageSize)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
result := make([]vault_service.AuditEntry, len(entries))
|
|
for i, e := range entries {
|
|
result[i] = vault_service.AuditEntry{
|
|
ID: e.ID,
|
|
RepoID: e.RepoID,
|
|
Action: string(e.Action),
|
|
UserID: e.UserID,
|
|
IPAddress: e.IPAddress,
|
|
Success: e.Success,
|
|
FailReason: e.FailReason,
|
|
Timestamp: int64(e.Timestamp),
|
|
}
|
|
}
|
|
return result, total, nil
|
|
}
|