mirror of
https://github.com/gopasspw/gopass.git
synced 2026-05-30 11:18:48 +02:00
7c63ba09b7
Migrate the entire codebase from github.com/urfave/cli/v2 to github.com/urfave/cli/v3 (v3.9.0). Key breaking changes addressed: - cli.App removed, replaced by *cli.Command - ActionFunc signature: func(*Context) error -> func(context.Context, *Command) error - BeforeFunc signature: func(*Context) error -> func(context.Context, *Command) (context.Context, error) - app.RunContext -> app.Run - app.EnableBashCompletion -> app.EnableShellCompletion - Subcommands field renamed to Commands - EnvVars on flags -> Sources: cli.EnvVars(...) - cli.NewContext removed; test helpers updated to use cmd.Run() pattern - cli.Flag interface updated (Apply removed, Get/PreParse/PostParse/Set added) - VersionPrinter type changed to func(*Command) Also updates .capabilities.json baseline to reflect new cli/v3 call paths. Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org>
74 lines
2.1 KiB
Go
74 lines
2.1 KiB
Go
package action
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/gopasspw/gopass/internal/action/exit"
|
|
"github.com/gopasspw/gopass/internal/out"
|
|
"github.com/gopasspw/gopass/internal/tpl"
|
|
"github.com/gopasspw/gopass/pkg/ctxutil"
|
|
"github.com/gopasspw/gopass/pkg/gopass"
|
|
"github.com/urfave/cli/v3"
|
|
)
|
|
|
|
// secretGetter is the minimal store interface required by the template engine.
|
|
type secretGetter interface {
|
|
Get(context.Context, string) (gopass.Secret, error)
|
|
}
|
|
|
|
// pathRestrictedStore wraps a secretGetter and only allows Get() calls for
|
|
// secret names that have one of the configured path prefixes. All other
|
|
// accesses are denied with a generic error so untrusted templates cannot
|
|
// exfiltrate secrets outside the declared scope.
|
|
type pathRestrictedStore struct {
|
|
inner secretGetter
|
|
allowPaths []string
|
|
}
|
|
|
|
func (p *pathRestrictedStore) Get(ctx context.Context, name string) (gopass.Secret, error) {
|
|
for _, prefix := range p.allowPaths {
|
|
if strings.HasPrefix(name, prefix) {
|
|
return p.inner.Get(ctx, name)
|
|
}
|
|
}
|
|
|
|
return nil, fmt.Errorf("access denied: %q is not within an allowed path", name)
|
|
}
|
|
|
|
// Process is a command to process a template and replace secrets contained in it.
|
|
func (s *miscHandler) Process(ctx context.Context, cmd *cli.Command) error {
|
|
ctx = ctxutil.WithGlobalFlags(ctx, cmd)
|
|
file := cmd.Args().First()
|
|
if file == "" {
|
|
return exit.Error(exit.Usage, nil, "Usage: %s process <FILE>", s.Name)
|
|
}
|
|
|
|
allowPaths := cmd.StringSlice("allow-path")
|
|
|
|
buf, err := os.ReadFile(file)
|
|
if err != nil {
|
|
return exit.Error(exit.IO, err, "Failed to read file: %s", file)
|
|
}
|
|
|
|
// Decide which store view the template engine may access.
|
|
var store secretGetter
|
|
if len(allowPaths) > 0 {
|
|
store = &pathRestrictedStore{inner: s.Store, allowPaths: allowPaths}
|
|
} else {
|
|
out.Warningf(ctx, "No --allow-path flag set. The template has unrestricted access to ALL secrets in the store. Only process templates from trusted sources.")
|
|
store = s.Store
|
|
}
|
|
|
|
obuf, err := tpl.Execute(ctx, string(buf), file, nil, store)
|
|
if err != nil {
|
|
return exit.Error(exit.IO, err, "Failed to process file: %s", file)
|
|
}
|
|
|
|
out.Print(ctx, string(obuf))
|
|
|
|
return nil
|
|
}
|