feat: share env files as encrypted links
CI / Checks (pull_request) Failing after 10s
PR title / Conventional title (pull_request) Successful in 0s

S → f on a repo, an env file or a key in one copies a
lazysecrets://share link holding the env files, encrypted (age) with
a secret's value: whoever can read that secret can open it. The key is
share.key in the repo's .lazysecrets.yaml, else in the config, else
picked when sharing; on Azure the link pins its version. Opening one
says what it holds, decrypts when asked, and saves the files in the
clone of the repo (or a folder chosen), replacing existing ones only
when asked. lazysecrets share prints a link from the command line.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kebandClaude Opus 5.5 committed 2026-10-13 11:59:39 +02:00
1 parent 1a5e40a012
commit 4b2f685921
26 files changed
+1541 -98

No files matched your search

+14
View File
@@ -14,6 +14,7 @@ import (
"go.yaml.in/yaml/v3"
"git.kebcloud.no/keb/lazysecrets/internal/commands"
"git.kebcloud.no/keb/lazysecrets/internal/ref"
"git.kebcloud.no/keb/lazysecrets/internal/update"
)
@@ -54,6 +55,8 @@ type Config struct {
Providers Providers `yaml:"providers"`
// LinkHandler sets how lazysecrets:// links open; see linkhandler.
LinkHandler LinkHandler `yaml:"linkHandler"`
// Share sets how env files are shared; see package share.
Share Share `yaml:"share"`
// CustomCommands run shell commands on the selected item; see
// package commands.
CustomCommands []commands.Command `yaml:"customCommands"`
@@ -82,6 +85,12 @@ type LinkHandler struct {
Prompt *bool `yaml:"prompt"`
}
type Share struct {
// Key is the link to the secret whose value encrypts shared files,
// for repos whose .lazysecrets.yaml doesn't name one.
Key string `yaml:"key"`
}
type Providers struct {
Azure Azure `yaml:"azure"`
Databricks Databricks `yaml:"databricks"`
@@ -221,6 +230,11 @@ func (c Config) validate(path string) error {
return fmt.Errorf("%s: releases[%d]: %q is not an https:// repository address, like %s", path, i, r, update.GitHubRepo)
}
}
if k := c.Share.Key; k != "" {
if r, err := ref.Parse(k); err != nil || r.IsShare() || r.IsSource() || r.IsContainer() {
return fmt.Errorf("%s: share.key: %q is not a lazysecrets:// link to a secret", path, k)
}
}
for i, v := range c.Providers.Azure.Vaults {
if !strings.HasPrefix(v, "https://") {
return fmt.Errorf("%s: providers.azure.vaults[%d]: %q is not an https:// vault URL", path, i, v)