mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-20 22:15:00 +00:00
101 lines
2.6 KiB
Go
101 lines
2.6 KiB
Go
// Copyright 2019 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package main
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
"go.mozilla.org/sops/decrypt"
|
|
"sigs.k8s.io/kustomize/pkg/ifc"
|
|
"sigs.k8s.io/kustomize/pkg/resmap"
|
|
"sigs.k8s.io/kustomize/pkg/types"
|
|
"sigs.k8s.io/yaml"
|
|
)
|
|
|
|
// Loads secrets from a sops-encoded file.
|
|
// See https://github.com/mozilla/sops
|
|
// Based on https://github.com/Agilicus/kustomize-sops
|
|
// and the sibling example SecretsFromDatabase.
|
|
type plugin struct {
|
|
rf *resmap.Factory
|
|
ldr ifc.Loader
|
|
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
|
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
|
|
File string `json:"file,omitempty" file:"name,omitempty"`
|
|
// List of keys to extract from secret map.
|
|
Keys []string `json:"keys,omitempty" yaml:"keys,omitempty"`
|
|
}
|
|
|
|
//noinspection GoUnusedGlobalVariable
|
|
//nolint: golint
|
|
var KustomizePlugin plugin
|
|
|
|
func (p *plugin) Config(
|
|
ldr ifc.Loader, rf *resmap.Factory, c []byte) error {
|
|
p.rf = rf
|
|
p.ldr = ldr
|
|
return yaml.Unmarshal(c, p)
|
|
}
|
|
|
|
func (p *plugin) Generate() (resmap.ResMap, error) {
|
|
secrets, err := p.loadSecretsViaSops()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return p.makeK8sSecret(secrets)
|
|
}
|
|
|
|
func (p *plugin) loadSecretsViaSops() (secrets map[string]string, err error) {
|
|
bytes, err := p.ldr.Load(p.File)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "trouble reading file %s", p.File)
|
|
}
|
|
var yamlMap []byte
|
|
if isFakeEncryptedData(bytes) {
|
|
yamlMap = []byte(fakeDecryptedData)
|
|
} else {
|
|
yamlMap, err = decrypt.Data(bytes, "yaml")
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "decrypting content from %s", p.File)
|
|
}
|
|
}
|
|
secrets = make(map[string]string)
|
|
err = yaml.Unmarshal(yamlMap, &secrets)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(
|
|
err, "unmarshal failure from '%s'", string(yamlMap))
|
|
}
|
|
return
|
|
}
|
|
|
|
func (p *plugin) makeK8sSecret(
|
|
secrets map[string]string) (resmap.ResMap, error) {
|
|
args := types.SecretArgs{}
|
|
args.Name = p.Name
|
|
args.Namespace = p.Namespace
|
|
for _, k := range p.Keys {
|
|
if v, ok := secrets[k]; ok {
|
|
args.LiteralSources = append(
|
|
args.LiteralSources, k+"="+v)
|
|
}
|
|
}
|
|
return p.rf.FromSecretArgs(p.ldr, nil, args)
|
|
}
|
|
|
|
// See test for justification of this hackery.
|
|
// The test is meant to just cover plugin behavior,
|
|
// and assume that sops works. There's currently
|
|
// no way to inject a "mock" sops into this plugin.
|
|
const fakeDecryptedData = `
|
|
VEGETABLE: carrot
|
|
ROCKET: saturn-v
|
|
FRUIT: apple
|
|
CAR: dymaxion
|
|
`
|
|
|
|
func isFakeEncryptedData(bytes []byte) bool {
|
|
return strings.Contains(string(bytes), "__ELIDED_FOR_KUSTOMIZE_TEST__")
|
|
}
|