mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-11-04 04:28:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			98 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			98 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package pgpkeys
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"encoding/base64"
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"os"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"golang.org/x/crypto/openpgp"
 | 
						|
)
 | 
						|
 | 
						|
// PGPPubKeyFiles implements the flag.Value interface and allows
 | 
						|
// parsing and reading a list of pgp public key files
 | 
						|
type PubKeyFilesFlag []string
 | 
						|
 | 
						|
func (p *PubKeyFilesFlag) String() string {
 | 
						|
	return fmt.Sprint(*p)
 | 
						|
}
 | 
						|
 | 
						|
func (p *PubKeyFilesFlag) Set(value string) error {
 | 
						|
	if len(*p) > 0 {
 | 
						|
		return errors.New("pgp-keys can only be specified once")
 | 
						|
	}
 | 
						|
 | 
						|
	splitValues := strings.Split(value, ",")
 | 
						|
 | 
						|
	keybaseMap, err := FetchKeybasePubkeys(splitValues)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	// Now go through the actual flag, and substitute in resolved keybase
 | 
						|
	// entries where appropriate
 | 
						|
	for _, keyfile := range splitValues {
 | 
						|
		if strings.HasPrefix(keyfile, kbPrefix) {
 | 
						|
			key := keybaseMap[keyfile]
 | 
						|
			if key == "" {
 | 
						|
				return fmt.Errorf("key for keybase user %s was not found in the map", strings.TrimPrefix(keyfile, kbPrefix))
 | 
						|
			}
 | 
						|
			*p = append(*p, key)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		pgpStr, err := ReadPGPFile(keyfile)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		*p = append(*p, pgpStr)
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func ReadPGPFile(path string) (string, error) {
 | 
						|
	if path[0] == '@' {
 | 
						|
		path = path[1:]
 | 
						|
	}
 | 
						|
	f, err := os.Open(path)
 | 
						|
	if err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
	defer f.Close()
 | 
						|
	buf := bytes.NewBuffer(nil)
 | 
						|
	_, err = buf.ReadFrom(f)
 | 
						|
	if err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
 | 
						|
	// First parse as an armored keyring file, if that doesn't work, treat it as a straight binary/b64 string
 | 
						|
	keyReader := bytes.NewReader(buf.Bytes())
 | 
						|
	entityList, err := openpgp.ReadArmoredKeyRing(keyReader)
 | 
						|
	if err == nil {
 | 
						|
		if len(entityList) != 1 {
 | 
						|
			return "", fmt.Errorf("more than one key found in file %s", path)
 | 
						|
		}
 | 
						|
		if entityList[0] == nil {
 | 
						|
			return "", fmt.Errorf("primary key was nil for file %s", path)
 | 
						|
		}
 | 
						|
 | 
						|
		serializedEntity := bytes.NewBuffer(nil)
 | 
						|
		err = entityList[0].Serialize(serializedEntity)
 | 
						|
		if err != nil {
 | 
						|
			return "", fmt.Errorf("error serializing entity for file %s: %s", path, err)
 | 
						|
		}
 | 
						|
 | 
						|
		return base64.StdEncoding.EncodeToString(serializedEntity.Bytes()), nil
 | 
						|
	}
 | 
						|
 | 
						|
	_, err = base64.StdEncoding.DecodeString(buf.String())
 | 
						|
	if err == nil {
 | 
						|
		return buf.String(), nil
 | 
						|
	}
 | 
						|
	return base64.StdEncoding.EncodeToString(buf.Bytes()), nil
 | 
						|
 | 
						|
}
 |