Skip to content

Commit

Permalink
Merge pull request #2947 from hashicorp/f-vault-grace
Browse files Browse the repository at this point in the history
Allow template to set Vault grace
  • Loading branch information
dadgar committed Aug 7, 2017
2 parents a768eca + 18e3bd9 commit 798b779
Show file tree
Hide file tree
Showing 38 changed files with 1,110 additions and 302 deletions.
3 changes: 3 additions & 0 deletions api/jobs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ func TestJobs_Canonicalize(t *testing.T) {
EmbeddedTmpl: helper.StringToPtr("FOO=bar\n"),
DestPath: helper.StringToPtr("local/file.env"),
Envvars: helper.BoolToPtr(true),
VaultGrace: helper.TimeToPtr(3 * time.Second),
},
},
},
Expand Down Expand Up @@ -389,6 +390,7 @@ func TestJobs_Canonicalize(t *testing.T) {
LeftDelim: helper.StringToPtr("{{"),
RightDelim: helper.StringToPtr("}}"),
Envvars: helper.BoolToPtr(false),
VaultGrace: helper.TimeToPtr(5 * time.Minute),
},
{
SourcePath: helper.StringToPtr(""),
Expand All @@ -401,6 +403,7 @@ func TestJobs_Canonicalize(t *testing.T) {
LeftDelim: helper.StringToPtr("{{"),
RightDelim: helper.StringToPtr("}}"),
Envvars: helper.BoolToPtr(true),
VaultGrace: helper.TimeToPtr(3 * time.Second),
},
},
},
Expand Down
4 changes: 4 additions & 0 deletions api/tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ type Template struct {
LeftDelim *string `mapstructure:"left_delimiter"`
RightDelim *string `mapstructure:"right_delimiter"`
Envvars *bool `mapstructure:"env"`
VaultGrace *time.Duration `mapstructure:"vault_grace"`
}

func (tmpl *Template) Canonicalize() {
Expand Down Expand Up @@ -404,6 +405,9 @@ func (tmpl *Template) Canonicalize() {
if tmpl.Envvars == nil {
tmpl.Envvars = helper.BoolToPtr(false)
}
if tmpl.VaultGrace == nil {
tmpl.VaultGrace = helper.TimeToPtr(5 * time.Minute)
}
}

type Vault struct {
Expand Down
58 changes: 37 additions & 21 deletions client/consul_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/client/driver/env"
"github.com/hashicorp/nomad/helper"
"github.com/hashicorp/nomad/nomad/structs"
)

Expand Down Expand Up @@ -341,25 +342,18 @@ func templateRunner(tmpls []*structs.Template, config *config.Config,
return nil, nil, nil
}

runnerConfig, err := runnerConfig(config, vaultToken)
if err != nil {
return nil, nil, err
}

// Parse the templates
allowAbs := config.ReadBoolDefault(hostSrcOption, true)
ctmplMapping, err := parseTemplateConfigs(tmpls, taskDir, taskEnv, allowAbs)
if err != nil {
return nil, nil, err
}

// Set the config
flat := ctconf.TemplateConfigs(make([]*ctconf.TemplateConfig, 0, len(ctmplMapping)))
for ctmpl := range ctmplMapping {
local := ctmpl
flat = append(flat, &local)
// Create the runner configuration.
runnerConfig, err := newRunnerConfig(config, vaultToken, ctmplMapping)
if err != nil {
return nil, nil, err
}
runnerConfig.Templates = &flat

runner, err := manager.NewRunner(runnerConfig, false, false)
if err != nil {
Expand Down Expand Up @@ -429,12 +423,33 @@ func parseTemplateConfigs(tmpls []*structs.Template, taskDir string,
return ctmpls, nil
}

// runnerConfig returns a consul-template runner configuration, setting the
// Vault and Consul configurations based on the clients configs.
func runnerConfig(config *config.Config, vaultToken string) (*ctconf.Config, error) {
// newRunnerConfig returns a consul-template runner configuration, setting the
// Vault and Consul configurations based on the clients configs. The parameters
// are the client config, Vault token if set and the mapping of consul-templates
// to Nomad templates.
func newRunnerConfig(config *config.Config, vaultToken string,
templateMapping map[ctconf.TemplateConfig]*structs.Template) (*ctconf.Config, error) {

conf := ctconf.DefaultConfig()

t, f := true, false
// Gather the consul-template tempates
flat := ctconf.TemplateConfigs(make([]*ctconf.TemplateConfig, 0, len(templateMapping)))
for ctmpl := range templateMapping {
local := ctmpl
flat = append(flat, &local)
}
conf.Templates = &flat

// Go through the templates and determine the minimum Vault grace
vaultGrace := time.Duration(-1)
for _, tmpl := range templateMapping {
// Initial condition
if vaultGrace < 0 {
vaultGrace = tmpl.VaultGrace
} else if tmpl.VaultGrace < vaultGrace {
vaultGrace = tmpl.VaultGrace
}
}

// Force faster retries
if testRetryRate != 0 {
Expand All @@ -450,7 +465,7 @@ func runnerConfig(config *config.Config, vaultToken string) (*ctconf.Config, err
if config.ConsulConfig.EnableSSL != nil && *config.ConsulConfig.EnableSSL {
verify := config.ConsulConfig.VerifySSL != nil && *config.ConsulConfig.VerifySSL
conf.Consul.SSL = &ctconf.SSLConfig{
Enabled: &t,
Enabled: helper.BoolToPtr(true),
Verify: &verify,
Cert: &config.ConsulConfig.CertFile,
Key: &config.ConsulConfig.KeyFile,
Expand All @@ -465,7 +480,7 @@ func runnerConfig(config *config.Config, vaultToken string) (*ctconf.Config, err
}

conf.Consul.Auth = &ctconf.AuthConfig{
Enabled: &t,
Enabled: helper.BoolToPtr(true),
Username: &parts[0],
Password: &parts[1],
}
Expand All @@ -475,17 +490,18 @@ func runnerConfig(config *config.Config, vaultToken string) (*ctconf.Config, err
// Setup the Vault config
// Always set these to ensure nothing is picked up from the environment
emptyStr := ""
conf.Vault.RenewToken = &f
conf.Vault.RenewToken = helper.BoolToPtr(false)
conf.Vault.Token = &emptyStr
if config.VaultConfig != nil && config.VaultConfig.IsEnabled() {
conf.Vault.Address = &config.VaultConfig.Addr
conf.Vault.Token = &vaultToken
conf.Vault.Grace = helper.TimeToPtr(vaultGrace)

if strings.HasPrefix(config.VaultConfig.Addr, "https") || config.VaultConfig.TLSCertFile != "" {
skipVerify := config.VaultConfig.TLSSkipVerify != nil && *config.VaultConfig.TLSSkipVerify
verify := !skipVerify
conf.Vault.SSL = &ctconf.SSLConfig{
Enabled: &t,
Enabled: helper.BoolToPtr(true),
Verify: &verify,
Cert: &config.VaultConfig.TLSCertFile,
Key: &config.VaultConfig.TLSKeyFile,
Expand All @@ -495,8 +511,8 @@ func runnerConfig(config *config.Config, vaultToken string) (*ctconf.Config, err
}
} else {
conf.Vault.SSL = &ctconf.SSLConfig{
Enabled: &f,
Verify: &f,
Enabled: helper.BoolToPtr(false),
Verify: helper.BoolToPtr(false),
Cert: &emptyStr,
Key: &emptyStr,
CaCert: &emptyStr,
Expand Down
41 changes: 40 additions & 1 deletion client/consul_template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/hashicorp/nomad/nomad/structs"
sconfig "github.com/hashicorp/nomad/nomad/structs/config"
"github.com/hashicorp/nomad/testutil"
"github.com/stretchr/testify/assert"
)

const (
Expand Down Expand Up @@ -1062,7 +1063,7 @@ func TestTaskTemplateManager_Config_ServerName(t *testing.T) {
Addr: "https://localhost/",
TLSServerName: "notlocalhost",
}
ctconf, err := runnerConfig(c, "token")
ctconf, err := newRunnerConfig(c, "token", nil)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand All @@ -1071,3 +1072,41 @@ func TestTaskTemplateManager_Config_ServerName(t *testing.T) {
t.Fatalf("expected %q but found %q", c.VaultConfig.TLSServerName, *ctconf.Vault.SSL.ServerName)
}
}

// TestTaskTemplateManager_Config_VaultGrace asserts the vault_grace setting is
// propogated to consul-template's configuration.
func TestTaskTemplateManager_Config_VaultGrace(t *testing.T) {
t.Parallel()
assert := assert.New(t)
c := config.DefaultConfig()
c.VaultConfig = &sconfig.VaultConfig{
Enabled: helper.BoolToPtr(true),
Addr: "https://localhost/",
TLSServerName: "notlocalhost",
}

// Make a template that will render immediately
templates := []*structs.Template{
{
EmbeddedTmpl: "bar",
DestPath: "foo",
ChangeMode: structs.TemplateChangeModeNoop,
VaultGrace: 10 * time.Second,
},
{
EmbeddedTmpl: "baz",
DestPath: "bam",
ChangeMode: structs.TemplateChangeModeNoop,
VaultGrace: 100 * time.Second,
},
}

taskEnv := env.NewTaskEnv(nil, nil)
ctmplMapping, err := parseTemplateConfigs(templates, "/fake/dir", taskEnv, false)
assert.Nil(err, "Parsing Templates")

ctconf, err := newRunnerConfig(c, "token", ctmplMapping)
assert.Nil(err, "Building Runner Config")
assert.NotNil(ctconf.Vault.Grace, "Vault Grace Pointer")
assert.Equal(10*time.Second, *ctconf.Vault.Grace, "Vault Grace Value")
}
1 change: 1 addition & 0 deletions command/agent/job_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,7 @@ func ApiTaskToStructsTask(apiTask *api.Task, structsTask *structs.Task) {
LeftDelim: *template.LeftDelim,
RightDelim: *template.RightDelim,
Envvars: *template.Envvars,
VaultGrace: *template.VaultGrace,
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions command/agent/job_endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,8 @@ func TestJobs_ApiJobToStructsJob(t *testing.T) {
Perms: helper.StringToPtr("666"),
LeftDelim: helper.StringToPtr("abc"),
RightDelim: helper.StringToPtr("def"),
Envvars: helper.BoolToPtr(true),
VaultGrace: helper.TimeToPtr(3 * time.Second),
},
},
DispatchPayload: &api.DispatchPayloadConfig{
Expand Down Expand Up @@ -1357,6 +1359,8 @@ func TestJobs_ApiJobToStructsJob(t *testing.T) {
Perms: "666",
LeftDelim: "abc",
RightDelim: "def",
Envvars: true,
VaultGrace: 3 * time.Second,
},
},
DispatchPayload: &structs.DispatchPayloadConfig{
Expand Down
1 change: 1 addition & 0 deletions jobspec/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,7 @@ func parseTemplates(result *[]*api.Template, list *ast.ObjectList) error {
"source",
"splay",
"env",
"vault_grace",
}
if err := checkHCLKeys(o.Val, valid); err != nil {
return err
Expand Down
1 change: 1 addition & 0 deletions jobspec/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ func TestParse(t *testing.T) {
Splay: helper.TimeToPtr(10 * time.Second),
Perms: helper.StringToPtr("0644"),
Envvars: helper.BoolToPtr(true),
VaultGrace: helper.TimeToPtr(33 * time.Second),
},
{
SourcePath: helper.StringToPtr("bar"),
Expand Down
1 change: 1 addition & 0 deletions jobspec/test-fixtures/basic.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ job "binstore-storagelocker" {
change_signal = "foo"
splay = "10s"
env = true
vault_grace = "33s"
}

template {
Expand Down
9 changes: 9 additions & 0 deletions nomad/structs/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3314,6 +3314,11 @@ type Template struct {
// Empty lines and lines starting with # will be ignored, but to avoid
// escaping issues #s within lines will not be treated as comments.
Envvars bool

// VaultGrace is the grace duration between lease renewal and reacquiring a
// secret. If the lease of a secret is less than the grace, a new secret is
// acquired.
VaultGrace time.Duration
}

// DefaultTemplate returns a default template.
Expand Down Expand Up @@ -3387,6 +3392,10 @@ func (t *Template) Validate() error {
}
}

if t.VaultGrace.Nanoseconds() < 0 {
multierror.Append(&mErr, fmt.Errorf("Vault grace must be greater than zero: %v < 0", t.VaultGrace))
}

return mErr.ErrorOrNil()
}

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 798b779

Please sign in to comment.