2
0
Files
gitcaddy-vault/plugin_service.go
logikonline 99b5464399 feat: implement vault.Plugin service interface
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>
2026-01-18 01:01:03 -05:00

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
}