agent/templates: update consul-template to v0.25.1 (#9626)

This commit is contained in:
Jason O'Donnell 2020-08-17 14:31:48 -04:00 committed by GitHub
parent f0f576f5bf
commit e3fcb4c5b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 188 additions and 124 deletions

2
go.mod
View File

@ -48,7 +48,7 @@ require (
github.com/golang/protobuf v1.4.2
github.com/google/go-github v17.0.0+incompatible
github.com/google/go-metrics-stackdriver v0.2.0
github.com/hashicorp/consul-template v0.25.0
github.com/hashicorp/consul-template v0.25.1
github.com/hashicorp/consul/api v1.4.0
github.com/hashicorp/errwrap v1.0.0
github.com/hashicorp/go-bindata v3.0.8-0.20180209072458-bf7910af8997+incompatible

4
go.sum
View File

@ -431,8 +431,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hashicorp/consul-template v0.25.0 h1:wsnv4jSqBIVzlg6U0wNg+ePzfrsF3Vi9MqIqDEUrg9U=
github.com/hashicorp/consul-template v0.25.0/go.mod h1:/vUsrJvDuuQHcxEw0zik+YXTS7ZKWZjQeaQhshBmfH0=
github.com/hashicorp/consul-template v0.25.1 h1:+D2s8eyRqWyX7GPNxeUi8tsyh8pRn3J6k8giEchPfKQ=
github.com/hashicorp/consul-template v0.25.1/go.mod h1:/vUsrJvDuuQHcxEw0zik+YXTS7ZKWZjQeaQhshBmfH0=
github.com/hashicorp/consul/api v1.4.0 h1:jfESivXnO5uLdH650JU/6AnjRoHrLhULq0FnC3Kp9EY=
github.com/hashicorp/consul/api v1.4.0/go.mod h1:xc8u05kyMa3Wjr9eEAsIAo3dg8+LywT5E/Cl7cNS5nU=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=

View File

@ -11,15 +11,21 @@ import (
// variable filtering. You should not use this directly and it is only public
// for mapstructure's decoding.
type EnvConfig struct {
// BlacklistEnv specifies a list of environment variables to explicitly
// Denylist specifies a list of environment variables to explicitly
// exclude from the list of environment variables populated to the child.
// If both WhitelistEnv and BlacklistEnv are provided, BlacklistEnv takes
// precedence over the values in WhitelistEnv.
Blacklist []string `mapstructure:"blacklist"`
// If both Allowlist and Denylist are provided, Denylist takes
// precedence over the values in Allowlist.
Denylist []string `mapstructure:"denylist"`
// DenylistDeprecated is the backward compatible option for Denylist for
// configuration supported by v0.25.0 and older. This should not be used
// directly, use Denylist instead. Values from this are combined to
// Denylist in Finalize().
DenylistDeprecated []string `mapstructure:"blacklist" json:"-"`
// CustomEnv specifies custom environment variables to pass to the child
// process. These are provided programmatically, override any environment
// variables of the same name, are ignored from whitelist/blacklist, and
// variables of the same name, are ignored from allowlist/denylist, and
// are still included even if PristineEnv is set to true.
Custom []string `mapstructure:"custom"`
@ -27,9 +33,15 @@ type EnvConfig struct {
// environment.
Pristine *bool `mapstructure:"pristine"`
// WhitelistEnv specifies a list of environment variables to exclusively
// Allowlist specifies a list of environment variables to exclusively
// include in the list of environment variables populated to the child.
Whitelist []string `mapstructure:"whitelist"`
Allowlist []string `mapstructure:"allowlist"`
// AllowlistDeprecated is the backward compatible option for Allowlist for
// configuration supported by v0.25.0 and older. This should not be used
// directly, use Allowlist instead. Values from this are combined to
// Allowlist in Finalize().
AllowlistDeprecated []string `mapstructure:"whitelist" json:"-"`
}
// DefaultEnvConfig returns a configuration that is populated with the
@ -46,8 +58,12 @@ func (c *EnvConfig) Copy() *EnvConfig {
var o EnvConfig
if c.Blacklist != nil {
o.Blacklist = append([]string{}, c.Blacklist...)
if c.Denylist != nil {
o.Denylist = append([]string{}, c.Denylist...)
}
if c.DenylistDeprecated != nil {
o.DenylistDeprecated = append([]string{}, c.DenylistDeprecated...)
}
if c.Custom != nil {
@ -56,8 +72,12 @@ func (c *EnvConfig) Copy() *EnvConfig {
o.Pristine = c.Pristine
if c.Whitelist != nil {
o.Whitelist = append([]string{}, c.Whitelist...)
if c.Allowlist != nil {
o.Allowlist = append([]string{}, c.Allowlist...)
}
if c.AllowlistDeprecated != nil {
o.AllowlistDeprecated = append([]string{}, c.AllowlistDeprecated...)
}
return &o
@ -81,8 +101,12 @@ func (c *EnvConfig) Merge(o *EnvConfig) *EnvConfig {
r := c.Copy()
if o.Blacklist != nil {
r.Blacklist = append(r.Blacklist, o.Blacklist...)
if o.Denylist != nil {
r.Denylist = append(r.Denylist, o.Denylist...)
}
if o.DenylistDeprecated != nil {
r.DenylistDeprecated = append(r.DenylistDeprecated, o.DenylistDeprecated...)
}
if o.Custom != nil {
@ -93,16 +117,20 @@ func (c *EnvConfig) Merge(o *EnvConfig) *EnvConfig {
r.Pristine = o.Pristine
}
if o.Whitelist != nil {
r.Whitelist = append(r.Whitelist, o.Whitelist...)
if o.Allowlist != nil {
r.Allowlist = append(r.Allowlist, o.Allowlist...)
}
if o.AllowlistDeprecated != nil {
r.AllowlistDeprecated = append(r.AllowlistDeprecated, o.AllowlistDeprecated...)
}
return r
}
// Env calculates and returns the finalized environment for this exec
// configuration. It takes into account pristine, custom environment, whitelist,
// and blacklist values.
// configuration. It takes into account pristine, custom environment, allowlist,
// and denylist values.
func (c *EnvConfig) Env() []string {
// In pristine mode, just return the custom environment. If the user did not
// specify a custom environment, just return the empty slice to force an
@ -136,22 +164,30 @@ func (c *EnvConfig) Env() []string {
return false
}
// Pull out any envvars that match the whitelist.
if len(c.Whitelist) > 0 {
// Pull out any envvars that match the allowlist.
// Combining lists on each reference may be slightly inefficient but this
// allows for out of order method calls, not requiring the config to be
// finalized first.
allowlist := combineLists(c.Allowlist, c.AllowlistDeprecated)
if len(allowlist) > 0 {
newKeys := make([]string, 0, len(keys))
for _, k := range keys {
if anyGlobMatch(k, c.Whitelist) {
if anyGlobMatch(k, allowlist) {
newKeys = append(newKeys, k)
}
}
keys = newKeys
}
// Remove any envvars that match the blacklist.
if len(c.Blacklist) > 0 {
// Remove any envvars that match the denylist.
// Combining lists on each reference may be slightly inefficient but this
// allows for out of order method calls, not requiring the config to be
// finalized first.
denylist := combineLists(c.Denylist, c.DenylistDeprecated)
if len(denylist) > 0 {
newKeys := make([]string, 0, len(keys))
for _, k := range keys {
if !anyGlobMatch(k, c.Blacklist) {
if !anyGlobMatch(k, denylist) {
newKeys = append(newKeys, k)
}
}
@ -172,8 +208,11 @@ func (c *EnvConfig) Env() []string {
// Finalize ensures there no nil pointers.
func (c *EnvConfig) Finalize() {
if c.Blacklist == nil {
c.Blacklist = []string{}
if c.Denylist == nil && c.DenylistDeprecated == nil {
c.Denylist = []string{}
c.DenylistDeprecated = []string{}
} else {
c.Denylist = combineLists(c.Denylist, c.DenylistDeprecated)
}
if c.Custom == nil {
@ -184,8 +223,11 @@ func (c *EnvConfig) Finalize() {
c.Pristine = Bool(false)
}
if c.Whitelist == nil {
c.Whitelist = []string{}
if c.Allowlist == nil && c.AllowlistDeprecated == nil {
c.Allowlist = []string{}
c.AllowlistDeprecated = []string{}
} else {
c.Allowlist = combineLists(c.Allowlist, c.AllowlistDeprecated)
}
}
@ -196,14 +238,33 @@ func (c *EnvConfig) GoString() string {
}
return fmt.Sprintf("&EnvConfig{"+
"Blacklist:%v, "+
"Denylist:%v, "+
"Custom:%v, "+
"Pristine:%s, "+
"Whitelist:%v"+
"Allowlist:%v"+
"}",
c.Blacklist,
combineLists(c.Denylist, c.DenylistDeprecated),
c.Custom,
BoolGoString(c.Pristine),
c.Whitelist,
combineLists(c.Allowlist, c.AllowlistDeprecated),
)
}
// combineLists makes a new list that combines 2 lists by adding values from
// the second list without removing any duplicates from the first.
func combineLists(a, b []string) []string {
combined := make([]string, len(a), len(a)+len(b))
m := make(map[string]bool)
for i, v := range a {
m[v] = true
combined[i] = v
}
for _, v := range b {
if !m[v] {
combined = append(combined, v)
}
}
return combined
}

View File

@ -76,9 +76,15 @@ type TemplateConfig struct {
LeftDelim *string `mapstructure:"left_delimiter"`
RightDelim *string `mapstructure:"right_delimiter"`
// FunctionBlacklist is a list of functions that this template is not
// FunctionDenylist is a list of functions that this template is not
// permitted to run.
FunctionBlacklist []string `mapstructure:"function_blacklist"`
FunctionDenylist []string `mapstructure:"function_denylist"`
// FunctionDenylistDeprecated is the backward compatible option for
// FunctionDenylist for configuration supported by v0.25.0 and older. This
// should not be used directly, use FunctionDenylist instead. Values from
// this are combined to FunctionDenylist in Finalize().
FunctionDenylistDeprecated []string `mapstructure:"function_blacklist" json:"-"`
// SandboxPath adds a prefix to any path provided to the `file` function
// and causes an error if a relative path tries to traverse outside that
@ -132,9 +138,14 @@ func (c *TemplateConfig) Copy() *TemplateConfig {
o.LeftDelim = c.LeftDelim
o.RightDelim = c.RightDelim
for _, fun := range c.FunctionBlacklist {
o.FunctionBlacklist = append(o.FunctionBlacklist, fun)
for _, fun := range c.FunctionDenylist {
o.FunctionDenylist = append(o.FunctionDenylist, fun)
}
for _, fun := range c.FunctionDenylistDeprecated {
o.FunctionDenylistDeprecated = append(o.FunctionDenylistDeprecated, fun)
}
o.SandboxPath = c.SandboxPath
return &o
@ -210,9 +221,14 @@ func (c *TemplateConfig) Merge(o *TemplateConfig) *TemplateConfig {
r.RightDelim = o.RightDelim
}
for _, fun := range o.FunctionBlacklist {
r.FunctionBlacklist = append(r.FunctionBlacklist, fun)
for _, fun := range o.FunctionDenylist {
r.FunctionDenylist = append(r.FunctionDenylist, fun)
}
for _, fun := range o.FunctionDenylistDeprecated {
r.FunctionDenylistDeprecated = append(r.FunctionDenylistDeprecated, fun)
}
if o.SandboxPath != nil {
r.SandboxPath = o.SandboxPath
}
@ -288,6 +304,13 @@ func (c *TemplateConfig) Finalize() {
if c.SandboxPath == nil {
c.SandboxPath = String("")
}
if c.FunctionDenylist == nil && c.FunctionDenylistDeprecated == nil {
c.FunctionDenylist = []string{}
c.FunctionDenylistDeprecated = []string{}
} else {
c.FunctionDenylist = combineLists(c.FunctionDenylist, c.FunctionDenylistDeprecated)
}
}
// GoString defines the printable version of this struct.
@ -309,8 +332,8 @@ func (c *TemplateConfig) GoString() string {
"Source:%s, "+
"Wait:%#v, "+
"LeftDelim:%s, "+
"RightDelim:%s"+
"FunctionBlacklist:%s"+
"RightDelim:%s, "+
"FunctionDenylist:%s, "+
"SandboxPath:%s"+
"}",
BoolGoString(c.Backup),
@ -326,7 +349,7 @@ func (c *TemplateConfig) GoString() string {
c.Wait,
StringGoString(c.LeftDelim),
StringGoString(c.RightDelim),
c.FunctionBlacklist,
combineLists(c.FunctionDenylist, c.FunctionDenylistDeprecated),
StringGoString(c.SandboxPath),
)
}

View File

@ -3,14 +3,9 @@ package dependency
import (
"log"
"math/rand"
"path"
"strings"
"time"
"crypto/x509"
"encoding/json"
"encoding/pem"
"github.com/hashicorp/vault/api"
)
@ -106,22 +101,6 @@ func renewSecret(clients *ClientSet, d renewer) error {
}
}
// durationFrom cert gets the duration of validity from cert data and
// returns that value as an integer number of seconds
func durationFromCert(certData string) int {
block, _ := pem.Decode([]byte(certData))
if block == nil {
return -1
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
log.Printf("[WARN] Unable to parse certificate data: %s", err)
return -1
}
return int(cert.NotAfter.Sub(cert.NotBefore).Seconds())
}
// leaseCheckWait accepts a secret and returns the recommended amount of
// time to sleep.
func leaseCheckWait(s *Secret) time.Duration {
@ -132,12 +111,11 @@ func leaseCheckWait(s *Secret) time.Duration {
}
// Handle if this is a certificate with no lease
if certInterface, ok := s.Data["certificate"]; ok && s.LeaseID == "" {
if certData, ok := certInterface.(string); ok {
newDuration := durationFromCert(certData)
if newDuration > 0 {
log.Printf("[DEBUG] Found certificate and set lease duration to %d seconds", newDuration)
base = newDuration
if _, ok := s.Data["certificate"]; ok && s.LeaseID == "" {
if expInterface, ok := s.Data["expiration"]; ok {
if expData, err := expInterface.(json.Number).Int64(); err == nil {
base = int(expData - time.Now().Unix())
log.Printf("[DEBUG] Found certificate and set lease duration to %d seconds", base)
}
}
}
@ -349,21 +327,3 @@ func isKVv2(client *api.Client, path string) (string, bool, error) {
return mountPath, false, nil
}
func addPrefixToVKVPath(p, mountPath, apiPrefix string) string {
switch {
case p == mountPath, p == strings.TrimSuffix(mountPath, "/"):
return path.Join(mountPath, apiPrefix)
default:
p = strings.TrimPrefix(p, mountPath)
// Don't add /data/ to the path if it's been added manually.
apiPathPrefix := apiPrefix
if !strings.HasSuffix(apiPrefix, "/") {
apiPathPrefix += "/"
}
if strings.HasPrefix(p, apiPathPrefix) {
return path.Join(mountPath, p)
}
return path.Join(mountPath, apiPrefix, p)
}
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"log"
"net/url"
"path"
"strings"
"time"
@ -145,7 +146,7 @@ func (d *VaultReadQuery) readSecret(clients *ClientSet, opts *QueryOptions) (*ap
isKVv2 = false
d.secretPath = d.rawPath
} else if isKVv2 {
d.secretPath = addPrefixToVKVPath(d.rawPath, mountPath, "data")
d.secretPath = shimKVv2Path(d.rawPath, mountPath)
} else {
d.secretPath = d.rawPath
}
@ -176,3 +177,21 @@ func deletedKVv2(s *api.Secret) bool {
}
return false
}
// shimKVv2Path aligns the supported legacy path to KV v2 specs by inserting
// /data/ into the path for reading secrets. Paths for metadata are not modified.
func shimKVv2Path(rawPath, mountPath string) string {
switch {
case rawPath == mountPath, rawPath == strings.TrimSuffix(mountPath, "/"):
return path.Join(mountPath, "data")
default:
p := strings.TrimPrefix(rawPath, mountPath)
// Only add /data/ prefix to the path if neither /data/ or /metadata/ are
// present.
if strings.HasPrefix(p, "data/") || strings.HasPrefix(p, "metadata/") {
return rawPath
}
return path.Join(mountPath, "data", p)
}
}

View File

@ -47,7 +47,6 @@ func (d *VaultTokenQuery) Fetch(clients *ClientSet, opts *QueryOptions,
if err != nil {
return nil, nil, errors.Wrap(err, d.String())
}
renewSecret(clients, d)
}
return nil, nil, ErrLeaseExpired

View File

@ -102,6 +102,7 @@ type Runner struct {
// template and command runtime with. These environment variables will be
// available in both the command's environment as well as the template's
// environment.
// NOTE this is only used when CT is being used as a library.
Env map[string]string
// stopLock is the lock around checking if the runner can be stopped
@ -883,13 +884,13 @@ func (r *Runner) init() error {
}
tmpl, err := template.NewTemplate(&template.NewTemplateInput{
Source: config.StringVal(ctmpl.Source),
Contents: config.StringVal(ctmpl.Contents),
ErrMissingKey: config.BoolVal(ctmpl.ErrMissingKey),
LeftDelim: leftDelim,
RightDelim: rightDelim,
FunctionBlacklist: ctmpl.FunctionBlacklist,
SandboxPath: config.StringVal(ctmpl.SandboxPath),
Source: config.StringVal(ctmpl.Source),
Contents: config.StringVal(ctmpl.Contents),
ErrMissingKey: config.BoolVal(ctmpl.ErrMissingKey),
LeftDelim: leftDelim,
RightDelim: rightDelim,
FunctionDenylist: ctmpl.FunctionDenylist,
SandboxPath: config.StringVal(ctmpl.SandboxPath),
})
if err != nil {
return err

View File

@ -60,11 +60,12 @@ type RenderResult struct {
// whether it would have rendered and actually did render.
func Render(i *RenderInput) (*RenderResult, error) {
existing, err := ioutil.ReadFile(i.Path)
if err != nil && !os.IsNotExist(err) {
fileExists := !os.IsNotExist(err)
if err != nil && fileExists {
return nil, errors.Wrap(err, "failed reading file")
}
if bytes.Equal(existing, i.Contents) {
if bytes.Equal(existing, i.Contents) && fileExists {
return &RenderResult{
DidRender: false,
WouldRender: true,

View File

@ -1501,8 +1501,8 @@ func maximum(b, a interface{}) (interface{}, error) {
}
}
// blacklisted always returns an error, to be used in place of blacklisted template functions
func blacklisted(...string) (string, error) {
// denied always returns an error, to be used in place of denied template functions
func denied(...string) (string, error) {
return "", errors.New("function is disabled")
}

View File

@ -46,9 +46,9 @@ type Template struct {
// is indexed with a key that does not exist.
errMissingKey bool
// functionBlacklist are functions not permitted to be executed
// functionDenylist are functions not permitted to be executed
// when we render this template
functionBlacklist []string
functionDenylist []string
// sandboxPath adds a prefix to any path provided to the `file` function
// and causes an error if a relative path tries to traverse outside that
@ -72,9 +72,9 @@ type NewTemplateInput struct {
LeftDelim string
RightDelim string
// FunctionBlacklist are functions not permitted to be executed
// FunctionDenylist are functions not permitted to be executed
// when we render this template
FunctionBlacklist []string
FunctionDenylist []string
// SandboxPath adds a prefix to any path provided to the `file` function
// and causes an error if a relative path tries to traverse outside that
@ -104,7 +104,7 @@ func NewTemplate(i *NewTemplateInput) (*Template, error) {
t.leftDelim = i.LeftDelim
t.rightDelim = i.RightDelim
t.errMissingKey = i.ErrMissingKey
t.functionBlacklist = i.FunctionBlacklist
t.functionDenylist = i.FunctionDenylist
t.sandboxPath = i.SandboxPath
if i.Source != "" {
@ -175,13 +175,13 @@ func (t *Template) Execute(i *ExecuteInput) (*ExecuteResult, error) {
tmpl.Delims(t.leftDelim, t.rightDelim)
tmpl.Funcs(funcMap(&funcMapInput{
t: tmpl,
brain: i.Brain,
env: i.Env,
used: &used,
missing: &missing,
functionBlacklist: t.functionBlacklist,
sandboxPath: t.sandboxPath,
t: tmpl,
brain: i.Brain,
env: i.Env,
used: &used,
missing: &missing,
functionDenylist: t.functionDenylist,
sandboxPath: t.sandboxPath,
}))
if t.errMissingKey {
@ -210,13 +210,13 @@ func (t *Template) Execute(i *ExecuteInput) (*ExecuteResult, error) {
// funcMapInput is input to the funcMap, which builds the template functions.
type funcMapInput struct {
t *template.Template
brain *Brain
env []string
functionBlacklist []string
sandboxPath string
used *dep.Set
missing *dep.Set
t *template.Template
brain *Brain
env []string
functionDenylist []string
sandboxPath string
used *dep.Set
missing *dep.Set
}
// funcMap is the map of template functions to their respective functions.
@ -300,9 +300,9 @@ func funcMap(i *funcMapInput) template.FuncMap {
"maximum": maximum,
}
for _, bf := range i.functionBlacklist {
for _, bf := range i.functionDenylist {
if _, ok := r[bf]; ok {
r[bf] = blacklisted
r[bf] = denied
}
}

View File

@ -2,7 +2,7 @@ package version
import "fmt"
const Version = "0.25.0"
const Version = "0.25.1"
var (
Name string

2
vendor/modules.txt vendored
View File

@ -364,7 +364,7 @@ github.com/gorhill/cronexpr
github.com/gorilla/websocket
# github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed
github.com/hailocab/go-hostpool
# github.com/hashicorp/consul-template v0.25.0
# github.com/hashicorp/consul-template v0.25.1
github.com/hashicorp/consul-template/child
github.com/hashicorp/consul-template/config
github.com/hashicorp/consul-template/dependency