Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions age/encrypted_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func (i *LazyScryptIdentity) Unwrap(stanzas []*age.Stanza) (fileKey []byte, err
return fileKey, err
}

func unwrapIdentities(location string, reader io.Reader) (ParsedIdentities, error) {
func unwrapIdentities(location string, shortID string, reader io.Reader) (ParsedIdentities, error) {
b := bufio.NewReader(reader)
p, _ := b.Peek(14) // length of "age-encryption" and "-----BEGIN AGE"
peeked := string(p)
Expand Down Expand Up @@ -134,7 +134,7 @@ func unwrapIdentities(location string, reader io.Reader) (ParsedIdentities, erro
log.Errorf("failed to close connection with gpg-agent: %s", err)
}
}(conn)
err = conn.RemoveFromCache(location)
err = conn.RemoveFromCache(shortID)
if err != nil {
log.Warnf("gpg-agent remove cache request errored: %s", err)
return
Expand All @@ -154,8 +154,7 @@ func unwrapIdentities(location string, reader io.Reader) (ParsedIdentities, erro
}(conn)

req := gpgagent.PassphraseRequest{
// TODO is the cachekey good enough?
CacheKey: location,
CacheKey: shortID,
Prompt: "Passphrase",
Desc: fmt.Sprintf("Enter passphrase for identity '%s':", location),
}
Expand Down
46 changes: 39 additions & 7 deletions age/keysource.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package age
import (
"bufio"
"bytes"
"crypto/sha256"
"encoding/base64"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -227,7 +229,7 @@ func formatError(msg string, err error, errs errSet, unusedLocations []string) e
} else if count == 2 {
unusedSuffix = fmt.Sprintf("s '%s' and '%s'", unusedLocations[0], unusedLocations[1])
} else {
unusedSuffix = fmt.Sprintf("s '%s', and '%s'", strings.Join(unusedLocations[:count - 1], "', '"), unusedLocations[count - 1])
unusedSuffix = fmt.Sprintf("s '%s', and '%s'", strings.Join(unusedLocations[:count-1], "', '"), unusedLocations[count-1])
}
unusedSuffix = fmt.Sprintf(". Did not find keys in location%s.", unusedSuffix)
}
Expand Down Expand Up @@ -399,17 +401,35 @@ func getUserConfigDir() (string, error) {
return os.UserConfigDir()
}

type readerData struct {
reader io.Reader
source string
path string
}

func (d *readerData) getShortID() string {
if len(d.path) == 0 {
return fmt.Sprintf("sops-%s", d.source)
}
pathHash := sha256.Sum256([]byte(d.path))
return fmt.Sprintf("sops-%s-%s", d.source, base64.StdEncoding.EncodeToString(pathHash[:27]))
}

// loadIdentities attempts to load the age identities based on runtime
// environment configurations (e.g. SopsAgeKeyEnv, SopsAgeKeyFileEnv,
// SopsAgeSshPrivateKeyFileEnv, SopsAgeKeyUserConfigPath). It will load all
// found references, and expects at least one configuration to be present.
func (key *MasterKey) loadIdentities() (ParsedIdentities, []string, errSet) {
identities, unusedLocations, errs := key.loadAgeSSHIdentities()

var readers = make(map[string]io.Reader, 0)
var readers = make(map[string]readerData, 0)

if ageKey, ok := os.LookupEnv(SopsAgeKeyEnv); ok {
readers[SopsAgeKeyEnv] = strings.NewReader(ageKey)
readers[SopsAgeKeyEnv] = readerData{
reader: strings.NewReader(ageKey),
source: SopsAgeKeyEnv,
path: "",
}
} else {
unusedLocations = append(unusedLocations, SopsAgeKeyEnv)
}
Expand All @@ -420,7 +440,11 @@ func (key *MasterKey) loadIdentities() (ParsedIdentities, []string, errSet) {
errs = append(errs, fmt.Errorf("failed to open %s file: %w", SopsAgeKeyFileEnv, err))
} else {
defer f.Close()
readers[SopsAgeKeyFileEnv] = f
readers[SopsAgeKeyFileEnv] = readerData{
reader: f,
source: SopsAgeKeyFileEnv,
path: "",
}
}
} else {
unusedLocations = append(unusedLocations, SopsAgeKeyFileEnv)
Expand All @@ -431,7 +455,11 @@ func (key *MasterKey) loadIdentities() (ParsedIdentities, []string, errSet) {
if err != nil {
errs = append(errs, err)
} else {
readers[SopsAgeKeyCmdEnv] = bytes.NewReader(out)
readers[SopsAgeKeyCmdEnv] = readerData{
reader: bytes.NewReader(out),
source: SopsAgeKeyCmdEnv,
path: "",
}
}
} else {
unusedLocations = append(unusedLocations, SopsAgeKeyCmdEnv)
Expand All @@ -449,12 +477,16 @@ func (key *MasterKey) loadIdentities() (ParsedIdentities, []string, errSet) {
unusedLocations = append(unusedLocations, ageKeyFilePath)
} else if err == nil {
defer f.Close()
readers[ageKeyFilePath] = f
readers[ageKeyFilePath] = readerData{
reader: f,
source: "file",
path: ageKeyFilePath,
}
}
}

for location, r := range readers {
ids, err := unwrapIdentities(location, r)
ids, err := unwrapIdentities(location, r.getShortID(), r.reader)
if err != nil {
errs = append(errs, err)
} else {
Expand Down
Loading