Merge pull request #491 from adrianosela/golint

Address Go Lint messages
This commit is contained in:
Adrian Utrilla 2019-07-16 11:36:51 +02:00 коммит произвёл GitHub
Родитель 48f92ee92e 41b9e9f4b6
Коммит 9998e16c3e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
21 изменённых файлов: 152 добавлений и 44 удалений

Просмотреть файл

@ -45,6 +45,7 @@ type Cipher struct {
stash map[stashKey][]byte
}
// NewCipher is the constructor for a new Cipher object
func NewCipher() Cipher {
return Cipher{
stash: make(map[stashKey][]byte),

Просмотреть файл

@ -9,7 +9,9 @@ import (
"github.com/pkg/errors"
// empty import as per https://godoc.org/github.com/lib/pq
_ "github.com/lib/pq"
"github.com/sirupsen/logrus"
"go.mozilla.org/sops/logging"
"gopkg.in/yaml.v2"
@ -67,36 +69,52 @@ type config struct {
var auditors []Auditor
// SubmitEvent handles an event for all auditors
func SubmitEvent(event interface{}) {
for _, auditor := range auditors {
auditor.Handle(event)
}
}
// Register registers a new Auditor in the global auditor list
func Register(auditor Auditor) {
auditors = append(auditors, auditor)
}
// Auditor is notified when noteworthy events happen,
// for example when a file is encrypted or decrypted.
type Auditor interface {
// Handle() takes an audit event and attempts to persists it;
// how it is persisted and how errors are handled is up to the
// implementation of this interface.
Handle(event interface{})
}
// DecryptEvent contains fields relevant to a decryption event
type DecryptEvent struct {
File string
}
// EncryptEvent contains fields relevant to an encryption event
type EncryptEvent struct {
File string
}
// RotateEvent contains fields relevant to a key rotation event
type RotateEvent struct {
File string
}
// PostgresAuditor is a Postgres SQL DB implementation of the Auditor interface.
// It persists the audit event by writing a row to the 'audit_event' table.
// Errors with writing to the database will output a log message and the
// process will exit with status set to 1
type PostgresAuditor struct {
DB *sql.DB
}
// NewPostgresAuditor is the constructor for a new PostgresAuditor struct
// initialized with the given db connection string
func NewPostgresAuditor(connStr string) (*PostgresAuditor, error) {
db, err := sql.Open("postgres", connStr)
pg := &PostgresAuditor{DB: db}
@ -113,6 +131,8 @@ func NewPostgresAuditor(connStr string) (*PostgresAuditor, error) {
return pg, nil
}
// Handle persists the audit event by writing a row to the
// 'audit_event' postgres table
func (p *PostgresAuditor) Handle(event interface{}) {
u, err := user.Current()
if err != nil {

Просмотреть файл

@ -73,7 +73,7 @@ func MasterKeysFromURLs(urls string) ([]*MasterKey, error) {
return keys, nil
}
// NewMasterKeyFromResourceID takes an Azure Key Vault key URL and returns a new MasterKey
// NewMasterKeyFromURL takes an Azure Key Vault key URL and returns a new MasterKey
// URL format is {vaultUrl}/keys/{key-name}/{key-version}
func NewMasterKeyFromURL(url string) (*MasterKey, error) {
k := &MasterKey{}

Просмотреть файл

@ -92,16 +92,16 @@ func TestKeyToMap(t *testing.T) {
}, key.ToMap())
}
var azureKeyAcceptanceTestUrl = flag.String("azure-key", "", "URL to Azure Key Vault (note that this can incur real costs!)")
var azureKeyAcceptanceTestURL = flag.String("azure-key", "", "URL to Azure Key Vault (note that this can incur real costs!)")
func TestRoundtrip(t *testing.T) {
if *azureKeyAcceptanceTestUrl == "" {
if *azureKeyAcceptanceTestURL == "" {
t.Skip("Azure URL not provided, skipping acceptance test")
}
input := []byte("test-string")
key, err := NewMasterKeyFromURL(*azureKeyAcceptanceTestUrl)
key, err := NewMasterKeyFromURL(*azureKeyAcceptanceTestURL)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -24,10 +24,13 @@ import (
"gopkg.in/urfave/cli.v1"
)
// ExampleFileEmitter emits example files. This is used by the `sops` binary
// whenever a new file is created, in order to present the user with a non-empty file
type ExampleFileEmitter interface {
EmitExample() []byte
}
// Store handles marshaling and unmarshaling from SOPS files
type Store interface {
sops.Store
ExampleFileEmitter
@ -107,6 +110,8 @@ func LoadEncryptedFile(loader sops.EncryptedFileLoader, inputPath string) (*sops
return &tree, err
}
// NewExitError returns a cli.ExitError given an error (wrapped in a generic interface{})
// and an exit code to represent the failure
func NewExitError(i interface{}, exitCode int) *cli.ExitError {
if userErr, ok := i.(sops.UserError); ok {
return NewExitError(userErr.UserError(), exitCode)
@ -114,22 +119,28 @@ func NewExitError(i interface{}, exitCode int) *cli.ExitError {
return cli.NewExitError(i, exitCode)
}
// IsYAMLFile returns true if a given file path corresponds to a YAML file
func IsYAMLFile(path string) bool {
return strings.HasSuffix(path, ".yaml") || strings.HasSuffix(path, ".yml")
}
// IsJSONFile returns true if a given file path corresponds to a JSON file
func IsJSONFile(path string) bool {
return strings.HasSuffix(path, ".json")
}
// IsEnvFile returns true if a given file path corresponds to a .env file
func IsEnvFile(path string) bool {
return strings.HasSuffix(path, ".env")
}
// IsIniFile returns true if a given file path corresponds to a INI file
func IsIniFile(path string) bool {
return strings.HasSuffix(path, ".ini")
}
// DefaultStoreForPath returns the correct format-specific implementation
// of the Store interface given the path to a file
func DefaultStoreForPath(path string) Store {
if IsYAMLFile(path) {
return &yaml.Store{}
@ -143,8 +154,12 @@ func DefaultStoreForPath(path string) Store {
return &json.BinaryStore{}
}
// KMS_ENC_CTX_BUG_FIXED_VERSION represents the SOPS version in which the
// encryption context bug was fixed
const KMS_ENC_CTX_BUG_FIXED_VERSION = "3.3.0"
// DetectKMSEncryptionContextBug returns true if the encryption context bug is detected
// in a given runtime sops.Tree object
func DetectKMSEncryptionContextBug(tree *sops.Tree) (bool, error) {
versionCheck, err := version.AIsNewerThanB(KMS_ENC_CTX_BUG_FIXED_VERSION, tree.Metadata.Version)
if err != nil {
@ -161,6 +176,7 @@ func DetectKMSEncryptionContextBug(tree *sops.Tree) (bool, error) {
return false, nil
}
// GetKMSKeyWithEncryptionCtx returns the first KMS key affected by the encryption context bug as well as its location in the key groups.
func GetKMSKeyWithEncryptionCtx(tree *sops.Tree) (keyGroupIndex int, keyIndex int, key *kms.MasterKey) {
for i, kg := range tree.Metadata.KeyGroups {
for n, k := range kg {
@ -181,6 +197,7 @@ func GetKMSKeyWithEncryptionCtx(tree *sops.Tree) (keyGroupIndex int, keyIndex in
return 0, 0, nil
}
// GenericDecryptOpts represents decryption options and config
type GenericDecryptOpts struct {
Cipher sops.Cipher
InputStore sops.Store
@ -235,10 +252,9 @@ func FixAWSKMSEncryptionContextBug(opts GenericDecryptOpts, tree *sops.Tree) (*s
}
}
if response == "n" {
return nil, fmt.Errorf("Exiting. User responded no.")
} else {
persistFix = true
return nil, fmt.Errorf("Exiting. User responded no")
}
persistFix = true
}
// If there is another key, then we should be able to just decrypt
@ -341,6 +357,7 @@ func RecoverDataKeyFromBuggyKMS(opts GenericDecryptOpts, tree *sops.Tree) []byte
return nil
}
// Diff represents a key diff
type Diff struct {
Common []keys.MasterKey
Added []keys.MasterKey
@ -354,6 +371,7 @@ func max(a, b int) int {
return b
}
// DiffKeyGroups returns the list of diffs found in two sops.keyGroup slices
func DiffKeyGroups(ours, theirs []sops.KeyGroup) []Diff {
var diffs []Diff
for i := 0; i < max(len(ours), len(theirs)); i++ {
@ -388,6 +406,7 @@ func DiffKeyGroups(ours, theirs []sops.KeyGroup) []Diff {
return diffs
}
// PrettyPrintDiffs prints a slice of Diff objects to stdout
func PrettyPrintDiffs(diffs []Diff) {
for i, diff := range diffs {
color.New(color.Underline).Printf("Group %d\n", i+1)

Просмотреть файл

@ -24,6 +24,7 @@ func init() {
log = logging.NewLogger("PUBLISH")
}
// Opts represents publish options and config
type Opts struct {
Interactive bool
Cipher sops.Cipher
@ -33,6 +34,7 @@ type Opts struct {
InputStore sops.Store
}
// Run publish operation
func Run(opts Opts) error {
var fileContents []byte
path, err := filepath.Abs(opts.InputPath)

Просмотреть файл

@ -12,6 +12,7 @@ import (
"go.mozilla.org/sops/keyservice"
)
// Opts represents key operation options and config
type Opts struct {
InputPath string
GroupQuorum int
@ -20,6 +21,7 @@ type Opts struct {
ConfigPath string
}
// UpdateKeys update the keys for a given file
func UpdateKeys(opts Opts) error {
path, err := filepath.Abs(opts.InputPath)
if err != nil {

Просмотреть файл

@ -17,12 +17,14 @@ type TextFormatter struct {
logrus.TextFormatter
}
// Format formats a log entry onto bytes
func (f *TextFormatter) Format(entry *logrus.Entry) ([]byte, error) {
bytes, err := f.TextFormatter.Format(entry)
name := color.New(color.Bold).Sprintf("[%s]", f.LoggerName)
return []byte(fmt.Sprintf("%s\t %s", name, bytes)), err
}
// NewLogger is the constructor for a new Logger object with the given name
func NewLogger(name string) *logrus.Logger {
log := logrus.New()
log.SetLevel(logrus.WarnLevel)
@ -33,10 +35,12 @@ func NewLogger(name string) *logrus.Logger {
return log
}
// SetLevel sets the given level for all current Loggers
func SetLevel(level logrus.Level) {
for k := range Loggers {
Loggers[k].SetLevel(level)
}
}
// Loggers is the runtime map of logger name to logger object
var Loggers map[string]*logrus.Logger

Просмотреть файл

@ -7,19 +7,23 @@ import (
"cloud.google.com/go/storage"
)
// GCSDestination represents the Google Cloud Storage destination
type GCSDestination struct {
gcsBucket string
gcsPrefix string
}
// NewGCSDestination is the constructor for a Google Cloud Storage destination
func NewGCSDestination(gcsBucket string, gcsPrefix string) *GCSDestination {
return &GCSDestination{gcsBucket, gcsPrefix}
}
// Path returns a the GCS path for a file within this GCS Destination
func (gcsd *GCSDestination) Path(fileName string) string {
return fmt.Sprintf("gcs://%s/%s%s", gcsd.gcsBucket, gcsd.gcsPrefix, fileName)
}
// Upload uploads contents to a file in GCS
func (gcsd *GCSDestination) Upload(fileContents []byte, fileName string) error {
ctx := context.Background()
client, err := storage.NewClient(ctx)

Просмотреть файл

@ -1,5 +1,7 @@
package publish
// Destination represents actions which all destination types
// must implement in order to be used by SOPS
type Destination interface {
Upload(fileContents []byte, fileName string) error
Path(fileName string) string

Просмотреть файл

@ -9,19 +9,23 @@ import (
"github.com/aws/aws-sdk-go/service/s3"
)
// S3Destination is the AWS S3 implementation of the Destination interface
type S3Destination struct {
s3Bucket string
s3Prefix string
}
// NewS3Destination is the constructor for an S3 Destination
func NewS3Destination(s3Bucket string, s3Prefix string) *S3Destination {
return &S3Destination{s3Bucket, s3Prefix}
}
// Path returns the S3 path of a file in an S3 Destination (bucket)
func (s3d *S3Destination) Path(fileName string) string {
return fmt.Sprintf("s3://%s/%s%s", s3d.s3Bucket, s3d.s3Prefix, fileName)
}
// Upload uploads contents to a file in an S3 Destination (bucket)
func (s3d *S3Destination) Upload(fileContents []byte, fileName string) error {
sess := session.Must(session.NewSession())
svc := s3.New(sess)

Просмотреть файл

@ -73,8 +73,8 @@ func (p *polynomial) evaluate(x uint8) uint8 {
// An implementation of Lagrange interpolation
// <https://en.wikipedia.org/wiki/Lagrange_polynomial>
// For this particular implementation, x is always 0
func interpolatePolynomial(x_samples, y_samples []uint8, x uint8) uint8 {
limit := len(x_samples)
func interpolatePolynomial(xSamples, ySamples []uint8, x uint8) uint8 {
limit := len(xSamples)
var result, basis uint8
for i := 0; i < limit; i++ {
basis = 1
@ -82,12 +82,12 @@ func interpolatePolynomial(x_samples, y_samples []uint8, x uint8) uint8 {
if i == j {
continue
}
num := add(x, x_samples[j])
denom := add(x_samples[i], x_samples[j])
num := add(x, xSamples[j])
denom := add(xSamples[i], xSamples[j])
term := div(num, denom)
basis = mult(basis, term)
}
group := mult(y_samples[i], basis)
group := mult(ySamples[i], basis)
result = add(result, group)
}
return result
@ -103,9 +103,9 @@ func div(a, b uint8) uint8 {
}
var goodVal, zero uint8
log_a := logTable[a]
log_b := logTable[b]
diff := (int(log_a) - int(log_b)) % 255
logA := logTable[a]
logB := logTable[b]
diff := (int(logA) - int(logB)) % 255
if diff < 0 {
diff += 255
}
@ -258,8 +258,8 @@ func Combine(parts [][]byte) ([]byte, error) {
secret := make([]byte, firstPartLen-1)
// Buffer to store the samples
x_samples := make([]uint8, len(parts))
y_samples := make([]uint8, len(parts))
xSamples := make([]uint8, len(parts))
ySamples := make([]uint8, len(parts))
// Set the x value for each sample and ensure no x_sample values are the same,
// otherwise div() can be unhappy
@ -272,19 +272,19 @@ func Combine(parts [][]byte) ([]byte, error) {
return nil, fmt.Errorf("duplicate part detected")
}
checkMap[samp] = true
x_samples[i] = samp
xSamples[i] = samp
}
// Reconstruct each byte
for idx := range secret {
// Set the y value for each sample
for i, part := range parts {
y_samples[i] = part[idx]
ySamples[i] = part[idx]
}
// Use Lagrange interpolation to retrieve the free term
// of the original polynomial
val := interpolatePolynomial(x_samples, y_samples, 0)
val := interpolatePolynomial(xSamples, ySamples, 0)
// Evaluate the 0th value to get the intercept
secret[idx] = val

Просмотреть файл

@ -188,9 +188,9 @@ func TestInterpolate_Rand(t *testing.T) {
t.Fatalf("err: %v", err)
}
x_vals := []uint8{1, 2, 3}
y_vals := []uint8{p.evaluate(1), p.evaluate(2), p.evaluate(3)}
out := interpolatePolynomial(x_vals, y_vals, 0)
xVals := []uint8{1, 2, 3}
yVals := []uint8{p.evaluate(1), p.evaluate(2), p.evaluate(3)}
out := interpolatePolynomial(xVals, yVals, 0)
if out != uint8(i) {
t.Fatalf("Bad: %v %d", out, i)
}

38
sops.go
Просмотреть файл

@ -100,6 +100,7 @@ type TreeItem struct {
// TreeBranch is a branch inside sops's tree. It is a slice of TreeItems and is therefore ordered
type TreeBranch []TreeItem
// TreeBranches is a collection of TreeBranch
// Trees usually have more than one branch
type TreeBranches []TreeBranch
@ -110,10 +111,9 @@ func valueFromPathAndLeaf(path []interface{}, leaf interface{}) interface{} {
return []interface{}{
leaf,
}
} else {
return []interface{}{
valueFromPathAndLeaf(path[1:], leaf),
}
}
return []interface{}{
valueFromPathAndLeaf(path[1:], leaf),
}
default:
if len(path) == 1 {
@ -123,13 +123,12 @@ func valueFromPathAndLeaf(path []interface{}, leaf interface{}) interface{} {
Value: leaf,
},
}
} else {
return TreeBranch{
TreeItem{
Key: component,
Value: valueFromPathAndLeaf(path[1:], leaf),
},
}
}
return TreeBranch{
TreeItem{
Key: component,
Value: valueFromPathAndLeaf(path[1:], leaf),
},
}
}
}
@ -150,31 +149,28 @@ func set(branch interface{}, path []interface{}, value interface{}) interface{}
// Not found, need to add the next path entry to the branch
if len(path) == 1 {
return append(branch, TreeItem{Key: path[0], Value: value})
} else {
return valueFromPathAndLeaf(path, value)
}
return valueFromPathAndLeaf(path, value)
case []interface{}:
position := path[0].(int)
if len(path) == 1 {
if position >= len(branch) {
return append(branch, value)
} else {
branch[position] = value
}
return branch
branch[position] = value
} else {
if position >= len(branch) {
branch = append(branch, valueFromPathAndLeaf(path[1:], value))
} else {
branch[position] = set(branch[position], path[1:], value)
}
return branch
branch[position] = set(branch[position], path[1:], value)
}
return branch
default:
return valueFromPathAndLeaf(path, value)
}
}
// Set sets a value on a given tree for the specified path
func (branch TreeBranch) Set(path []interface{}, value interface{}) TreeBranch {
return set(branch, path, value).(TreeBranch)
}
@ -486,6 +482,8 @@ type PlainFileEmitter interface {
EmitPlainFile(TreeBranches) ([]byte, error)
}
// ValueEmitter is the interface for emitting a value. It provides a way to emit
// values from the internal SOPS representation so that they can be shown
type ValueEmitter interface {
EmitValue(interface{}) ([]byte, error)
}
@ -634,7 +632,7 @@ func decryptKeyGroup(group KeyGroup, svcs []keyservice.KeyServiceClient) ([]byte
// of the key services, returning as soon as one key service succeeds.
func decryptKey(key keys.MasterKey, svcs []keyservice.KeyServiceClient) ([]byte, error) {
svcKey := keyservice.KeyFromMasterKey(key)
var part []byte = nil
var part []byte
decryptErr := decryptKeyError{
keyName: key.ToString(),
}

Просмотреть файл

@ -10,12 +10,14 @@ import (
"go.mozilla.org/sops/stores"
)
// SopsPrefix is the prefix for all metadatada entry keys
const SopsPrefix = "sops_"
// Store handles storage of dotenv data
type Store struct {
}
// LoadEncryptedFile loads an encrypted file's bytes onto a sops.Tree runtime object
func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) {
branches, err := store.LoadPlainFile(in)
if err != nil {
@ -57,6 +59,8 @@ func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) {
}, nil
}
// LoadPlainFile returns the contents of a plaintext file loaded onto a
// sops runtime object
func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranches, error) {
var branches sops.TreeBranches
var branch sops.TreeBranch
@ -86,6 +90,8 @@ func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranches, error) {
return branches, nil
}
// EmitEncryptedFile returns the encrypted file's bytes corresponding to a sops
// runtime object
func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) {
metadata := stores.MetadataFromInternal(in.Metadata)
mdItems, err := metadataToMap(metadata)
@ -101,6 +107,8 @@ func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) {
return store.EmitPlainFile(in.Branches)
}
// EmitPlainFile returns the plaintext file's bytes corresponding to a sops
// runtime object
func (store *Store) EmitPlainFile(in sops.TreeBranches) ([]byte, error) {
buffer := bytes.Buffer{}
for _, item := range in[0] {
@ -118,6 +126,7 @@ func (store *Store) EmitPlainFile(in sops.TreeBranches) ([]byte, error) {
return buffer.Bytes(), nil
}
// EmitValue returns a single value as bytes
func (Store) EmitValue(v interface{}) ([]byte, error) {
if s, ok := v.(string); ok {
return []byte(s), nil
@ -125,6 +134,7 @@ func (Store) EmitValue(v interface{}) ([]byte, error) {
return nil, fmt.Errorf("the dotenv store only supports emitting strings, got %T", v)
}
// EmitExample returns the bytes corresponding to an example Flat Tree runtime object
func (store *Store) EmitExample() []byte {
bytes, err := store.EmitPlainFile(stores.ExampleFlatTree.Branches)
if err != nil {

Просмотреть файл

@ -106,7 +106,7 @@ func tokenize(path string) []token {
state = StateList
i += len(listSeparator)
} else {
i += 1
i++
}
}
finishPrevToken()

Просмотреть файл

@ -136,6 +136,7 @@ func (store Store) treeItemFromSection(section *ini.Section) (sops.TreeItem, err
return sectionItem, nil
}
// LoadEncryptedFile loads encrypted INI file's bytes onto a sops.Tree runtime object
func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) {
iniFileOuter, err := ini.Load(in)
if err != nil {
@ -192,6 +193,7 @@ func (store *Store) iniSectionToMetadata(sopsSection *ini.Section) (stores.Metad
return md, err
}
// LoadPlainFile loads a plaintext INI file's bytes onto a sops.TreeBranches runtime object
func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranches, error) {
branches, err := store.treeBranchesFromIni(in)
if err != nil {
@ -200,6 +202,8 @@ func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranches, error) {
return branches, nil
}
// EmitEncryptedFile returns encrypted INI file bytes corresponding to a sops.Tree
// runtime object
func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) {
metadata := stores.MetadataFromInternal(in.Metadata)
@ -298,6 +302,7 @@ func encodeMetadataItem(prefix string, kind reflect.Kind, field reflect.Value) (
return result, nil
}
// EmitPlainFile returns the plaintext INI file bytes corresponding to a sops.TreeBranches object
func (store *Store) EmitPlainFile(in sops.TreeBranches) ([]byte, error) {
out, err := store.iniFromTreeBranches(in)
if err != nil {
@ -315,10 +320,12 @@ func (store Store) encodeValue(v interface{}) ([]byte, error) {
}
}
// EmitValue returns a single value encoded in a generic interface{} as bytes
func (store *Store) EmitValue(v interface{}) ([]byte, error) {
return store.encodeValue(v)
}
// EmitExample returns the plaintext INI file bytes corresponding to the SimpleTree example
func (store *Store) EmitExample() []byte {
bytes, err := store.EmitPlainFile(stores.ExampleSimpleTree.Branches)
if err != nil {

Просмотреть файл

@ -19,10 +19,13 @@ type BinaryStore struct {
store Store
}
// LoadEncryptedFile loads an encrypted json file onto a sops.Tree object
func (store BinaryStore) LoadEncryptedFile(in []byte) (sops.Tree, error) {
return store.store.LoadEncryptedFile(in)
}
// LoadPlainFile loads a plaintext json file onto a sops.Tree encapsulated
// within a sops.TreeBranches object
func (store BinaryStore) LoadPlainFile(in []byte) (sops.TreeBranches, error) {
return sops.TreeBranches{
sops.TreeBranch{
@ -34,10 +37,12 @@ func (store BinaryStore) LoadPlainFile(in []byte) (sops.TreeBranches, error) {
}, nil
}
// EmitEncryptedFile produces an encrypted json file's bytes from its corresponding sops.Tree object
func (store BinaryStore) EmitEncryptedFile(in sops.Tree) ([]byte, error) {
return store.store.EmitEncryptedFile(in)
}
// EmitPlainFile produces plaintext json file's bytes from its corresponding sops.TreeBranches object
func (store BinaryStore) EmitPlainFile(in sops.TreeBranches) ([]byte, error) {
// JSON stores a single object per file
for _, item := range in[0] {
@ -48,10 +53,13 @@ func (store BinaryStore) EmitPlainFile(in sops.TreeBranches) ([]byte, error) {
return nil, fmt.Errorf("No binary data found in tree")
}
// EmitValue extracts a value from a generic interface{} object representing a structured set
// of binary files
func (store BinaryStore) EmitValue(v interface{}) ([]byte, error) {
return nil, fmt.Errorf("Binary files are not structured and extracting a single value is not possible")
}
// EmitExample returns the example's plaintext json file bytes
func (store BinaryStore) EmitExample() []byte {
return []byte("Welcome to SOPS! Edit this file as you please!")
}
@ -207,6 +215,7 @@ func (store Store) reindentJSON(in []byte) ([]byte, error) {
return out.Bytes(), err
}
// LoadEncryptedFile loads an encrypted secrets file onto a sops.Tree object
func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) {
// Because we don't know what fields the input file will have, we have to
// load the file in two steps.
@ -252,6 +261,7 @@ func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) {
}, nil
}
// LoadPlainFile loads plaintext json file bytes onto a sops.TreeBranches object
func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranches, error) {
branch, err := store.treeBranchFromJSON(in)
if err != nil {
@ -262,6 +272,8 @@ func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranches, error) {
}, nil
}
// EmitEncryptedFile returns the encrypted bytes of the json file corresponding to a
// sops.Tree runtime object
func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) {
tree := append(in.Branches[0], sops.TreeItem{Key: "sops", Value: stores.MetadataFromInternal(in.Metadata)})
out, err := store.jsonFromTreeBranch(tree)
@ -271,6 +283,8 @@ func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) {
return out, nil
}
// EmitPlainFile returns the plaintext bytes of the json file corresponding to a
// sops.TreeBranches runtime object
func (store *Store) EmitPlainFile(in sops.TreeBranches) ([]byte, error) {
out, err := store.jsonFromTreeBranch(in[0])
if err != nil {
@ -279,6 +293,8 @@ func (store *Store) EmitPlainFile(in sops.TreeBranches) ([]byte, error) {
return out, nil
}
// EmitValue returns bytes corresponding to a single encoded value
// in a generic interface{} object
func (store *Store) EmitValue(v interface{}) ([]byte, error) {
s, err := store.encodeValue(v)
if err != nil {
@ -287,6 +303,7 @@ func (store *Store) EmitValue(v interface{}) ([]byte, error) {
return store.reindentJSON(s)
}
// EmitExample returns the bytes corresponding to an example complex tree
func (store *Store) EmitExample() []byte {
bytes, err := store.EmitPlainFile(stores.ExampleComplexTree.Branches)
if err != nil {

Просмотреть файл

@ -309,6 +309,7 @@ func (pgpKey *pgpkey) toInternal() (*pgp.MasterKey, error) {
}, nil
}
// ExampleComplexTree is an example sops.Tree object exhibiting complex relationships
var ExampleComplexTree = sops.Tree{
Branches: sops.TreeBranches{
sops.TreeBranch{
@ -343,6 +344,8 @@ var ExampleComplexTree = sops.Tree{
},
}
// ExampleSimpleTree is an example sops.Tree object exhibiting only simple relationships
// with only one nested branch and only simple string values
var ExampleSimpleTree = sops.Tree{
Branches: sops.TreeBranches{
sops.TreeBranch{
@ -367,6 +370,8 @@ var ExampleSimpleTree = sops.Tree{
},
}
// ExampleFlatTree is an example sops.Tree object exhibiting only simple relationships
// with no nested branches and only simple string values
var ExampleFlatTree = sops.Tree{
Branches: sops.TreeBranches{
sops.TreeBranch{

Просмотреть файл

@ -101,6 +101,8 @@ func (store Store) treeBranchToYamlMap(in sops.TreeBranch) yaml.MapSlice {
return branch
}
// LoadEncryptedFile loads the contents of an encrypted yaml file onto a
// sops.Tree runtime object
func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) {
var data []yaml.MapSlice
if err := (yaml.CommentUnmarshaler{}).UnmarshalDocuments(in, &data); err != nil {
@ -136,6 +138,8 @@ func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) {
}, nil
}
// LoadPlainFile loads the contents of a plaintext yaml file onto a
// sops.Tree runtime obejct
func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranches, error) {
var data []yaml.MapSlice
if err := (yaml.CommentUnmarshaler{}).UnmarshalDocuments(in, &data); err != nil {
@ -149,6 +153,8 @@ func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranches, error) {
return branches, nil
}
// EmitEncryptedFile returns the encrypted bytes of the yaml file corresponding to a
// sops.Tree runtime object
func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) {
out := []byte{}
for i, branch := range in.Branches {
@ -166,6 +172,8 @@ func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) {
return out, nil
}
// EmitPlainFile returns the plaintext bytes of the yaml file corresponding to a
// sops.TreeBranches runtime object
func (store *Store) EmitPlainFile(branches sops.TreeBranches) ([]byte, error) {
var out []byte
for i, branch := range branches {
@ -182,11 +190,14 @@ func (store *Store) EmitPlainFile(branches sops.TreeBranches) ([]byte, error) {
return out, nil
}
// EmitValue returns bytes corresponding to a single encoded value
// in a generic interface{} object
func (store *Store) EmitValue(v interface{}) ([]byte, error) {
v = store.treeValueToYamlValue(v)
return (&yaml.YAMLMarshaler{Indent: 4}).Marshal(v)
}
// EmitExample returns the bytes corresponding to an example complex tree
func (store *Store) EmitExample() []byte {
bytes, err := store.EmitPlainFile(stores.ExampleComplexTree.Branches)
if err != nil {

Просмотреть файл

@ -10,8 +10,10 @@ import (
"gopkg.in/urfave/cli.v1"
)
// Version represents the value of the current semantic version
const Version = "3.3.1"
// PrintVersion handles the version command for sops
func PrintVersion(c *cli.Context) {
out := fmt.Sprintf("%s %s", c.App.Name, c.App.Version)
upstreamVersion, err := RetrieveLatestVersionFromUpstream()