mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
command, docs: create and document consul token configuration for connect acls (gh-6716)
This change provides an initial pass at setting up the configuration necessary to enable use of Connect with Consul ACLs. Operators will be able to pass in a Consul Token through `-consul-token` or `$CONSUL_TOKEN` in the `job run` and `job revert` commands (similar to Vault tokens). These values are not actually used yet in this changeset.
This commit is contained in:
15
api/jobs.go
15
api/jobs.go
@@ -336,14 +336,15 @@ func (j *Jobs) Dispatch(jobID string, meta map[string]string,
|
||||
// enforceVersion is set, the job is only reverted if the current version is at
|
||||
// the passed version.
|
||||
func (j *Jobs) Revert(jobID string, version uint64, enforcePriorVersion *uint64,
|
||||
q *WriteOptions, vaultToken string) (*JobRegisterResponse, *WriteMeta, error) {
|
||||
q *WriteOptions, consulToken, vaultToken string) (*JobRegisterResponse, *WriteMeta, error) {
|
||||
|
||||
var resp JobRegisterResponse
|
||||
req := &JobRevertRequest{
|
||||
JobID: jobID,
|
||||
JobVersion: version,
|
||||
EnforcePriorVersion: enforcePriorVersion,
|
||||
VaultToken: vaultToken,
|
||||
// ConsulToken: consulToken, // TODO(shoenig) enable!
|
||||
VaultToken: vaultToken,
|
||||
}
|
||||
wm, err := j.client.write("/v1/job/"+url.PathEscape(jobID)+"/revert", req, &resp, q)
|
||||
if err != nil {
|
||||
@@ -670,6 +671,7 @@ type Job struct {
|
||||
Reschedule *ReschedulePolicy
|
||||
Migrate *MigrateStrategy
|
||||
Meta map[string]string
|
||||
ConsulToken *string `mapstructure:"consul_token"`
|
||||
VaultToken *string `mapstructure:"vault_token"`
|
||||
Status *string
|
||||
StatusDescription *string
|
||||
@@ -722,6 +724,9 @@ func (j *Job) Canonicalize() {
|
||||
if j.AllAtOnce == nil {
|
||||
j.AllAtOnce = boolToPtr(false)
|
||||
}
|
||||
if j.ConsulToken == nil {
|
||||
j.ConsulToken = stringToPtr("")
|
||||
}
|
||||
if j.VaultToken == nil {
|
||||
j.VaultToken = stringToPtr("")
|
||||
}
|
||||
@@ -966,6 +971,12 @@ type JobRevertRequest struct {
|
||||
// version before reverting.
|
||||
EnforcePriorVersion *uint64
|
||||
|
||||
// ConsulToken is the Consul token that proves the submitter of the job revert
|
||||
// has access to the Service Identity policies associated with the job's
|
||||
// Consul Connect enabled services. This field is only used to transfer the
|
||||
// token and is not stored after the Job revert.
|
||||
ConsulToken string `json:",omitempty"`
|
||||
|
||||
// VaultToken is the Vault token that proves the submitter of the job revert
|
||||
// has access to any Vault policies specified in the targeted job version. This
|
||||
// field is only used to authorize the revert and is not stored after the Job
|
||||
|
||||
@@ -99,6 +99,7 @@ func TestJobs_Canonicalize(t *testing.T) {
|
||||
ParentID: stringToPtr(""),
|
||||
Priority: intToPtr(50),
|
||||
AllAtOnce: boolToPtr(false),
|
||||
ConsulToken: stringToPtr(""),
|
||||
VaultToken: stringToPtr(""),
|
||||
Status: stringToPtr(""),
|
||||
StatusDescription: stringToPtr(""),
|
||||
@@ -186,6 +187,7 @@ func TestJobs_Canonicalize(t *testing.T) {
|
||||
ParentID: stringToPtr(""),
|
||||
Priority: intToPtr(50),
|
||||
AllAtOnce: boolToPtr(false),
|
||||
ConsulToken: stringToPtr(""),
|
||||
VaultToken: stringToPtr(""),
|
||||
Status: stringToPtr(""),
|
||||
StatusDescription: stringToPtr(""),
|
||||
@@ -256,6 +258,7 @@ func TestJobs_Canonicalize(t *testing.T) {
|
||||
ParentID: stringToPtr("lol"),
|
||||
Priority: intToPtr(50),
|
||||
AllAtOnce: boolToPtr(false),
|
||||
ConsulToken: stringToPtr(""),
|
||||
VaultToken: stringToPtr(""),
|
||||
Stop: boolToPtr(false),
|
||||
Stable: boolToPtr(false),
|
||||
@@ -416,6 +419,7 @@ func TestJobs_Canonicalize(t *testing.T) {
|
||||
Region: stringToPtr("global"),
|
||||
Type: stringToPtr("service"),
|
||||
AllAtOnce: boolToPtr(false),
|
||||
ConsulToken: stringToPtr(""),
|
||||
VaultToken: stringToPtr(""),
|
||||
Stop: boolToPtr(false),
|
||||
Stable: boolToPtr(false),
|
||||
@@ -566,6 +570,7 @@ func TestJobs_Canonicalize(t *testing.T) {
|
||||
Type: stringToPtr("service"),
|
||||
Priority: intToPtr(50),
|
||||
AllAtOnce: boolToPtr(false),
|
||||
ConsulToken: stringToPtr(""),
|
||||
VaultToken: stringToPtr(""),
|
||||
Stop: boolToPtr(false),
|
||||
Stable: boolToPtr(false),
|
||||
@@ -650,6 +655,7 @@ func TestJobs_Canonicalize(t *testing.T) {
|
||||
ParentID: stringToPtr("lol"),
|
||||
Priority: intToPtr(50),
|
||||
AllAtOnce: boolToPtr(false),
|
||||
ConsulToken: stringToPtr(""),
|
||||
VaultToken: stringToPtr(""),
|
||||
Stop: boolToPtr(false),
|
||||
Stable: boolToPtr(false),
|
||||
@@ -846,13 +852,13 @@ func TestJobs_Revert(t *testing.T) {
|
||||
assertWriteMeta(t, wm)
|
||||
|
||||
// Fail revert at incorrect enforce
|
||||
_, _, err = jobs.Revert(*job.ID, 0, uint64ToPtr(10), nil, "")
|
||||
_, _, err = jobs.Revert(*job.ID, 0, uint64ToPtr(10), nil, "", "")
|
||||
if err == nil || !strings.Contains(err.Error(), "enforcing version") {
|
||||
t.Fatalf("expected enforcement error: %v", err)
|
||||
}
|
||||
|
||||
// Works at correct index
|
||||
revertResp, wm, err := jobs.Revert(*job.ID, 0, uint64ToPtr(1), nil, "")
|
||||
revertResp, wm, err := jobs.Revert(*job.ID, 0, uint64ToPtr(1), nil, "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
@@ -155,6 +155,10 @@ func (c *Command) readConfig() *Config {
|
||||
return nil
|
||||
}), "consul-verify-ssl", "")
|
||||
flags.StringVar(&cmdConfig.Consul.Addr, "consul-address", "", "")
|
||||
flags.Var((flaghelper.FuncBoolVar)(func(b bool) error {
|
||||
cmdConfig.Consul.AllowUnauthenticated = &b
|
||||
return nil
|
||||
}), "consul-allow-unauthenticated", "")
|
||||
|
||||
// Vault options
|
||||
flags.Var((flaghelper.FuncBoolVar)(func(b bool) error {
|
||||
@@ -560,6 +564,7 @@ func (c *Command) AutocompleteFlags() complete.Flags {
|
||||
"-consul-ssl": complete.PredictNothing,
|
||||
"-consul-verify-ssl": complete.PredictNothing,
|
||||
"-consul-address": complete.PredictAnything,
|
||||
"-consul-token": complete.PredictAnything,
|
||||
"-vault-enabled": complete.PredictNothing,
|
||||
"-vault-allow-unauthenticated": complete.PredictNothing,
|
||||
"-vault-token": complete.PredictAnything,
|
||||
|
||||
@@ -151,25 +151,26 @@ var basicConfig = &Config{
|
||||
DisableUpdateCheck: helper.BoolToPtr(true),
|
||||
DisableAnonymousSignature: true,
|
||||
Consul: &config.ConsulConfig{
|
||||
ServerServiceName: "nomad",
|
||||
ServerHTTPCheckName: "nomad-server-http-health-check",
|
||||
ServerSerfCheckName: "nomad-server-serf-health-check",
|
||||
ServerRPCCheckName: "nomad-server-rpc-health-check",
|
||||
ClientServiceName: "nomad-client",
|
||||
ClientHTTPCheckName: "nomad-client-http-health-check",
|
||||
Addr: "127.0.0.1:9500",
|
||||
Token: "token1",
|
||||
Auth: "username:pass",
|
||||
EnableSSL: &trueValue,
|
||||
VerifySSL: &trueValue,
|
||||
CAFile: "/path/to/ca/file",
|
||||
CertFile: "/path/to/cert/file",
|
||||
KeyFile: "/path/to/key/file",
|
||||
ServerAutoJoin: &trueValue,
|
||||
ClientAutoJoin: &trueValue,
|
||||
AutoAdvertise: &trueValue,
|
||||
ChecksUseAdvertise: &trueValue,
|
||||
Timeout: 5 * time.Second,
|
||||
ServerServiceName: "nomad",
|
||||
ServerHTTPCheckName: "nomad-server-http-health-check",
|
||||
ServerSerfCheckName: "nomad-server-serf-health-check",
|
||||
ServerRPCCheckName: "nomad-server-rpc-health-check",
|
||||
ClientServiceName: "nomad-client",
|
||||
ClientHTTPCheckName: "nomad-client-http-health-check",
|
||||
Addr: "127.0.0.1:9500",
|
||||
AllowUnauthenticated: &trueValue,
|
||||
Token: "token1",
|
||||
Auth: "username:pass",
|
||||
EnableSSL: &trueValue,
|
||||
VerifySSL: &trueValue,
|
||||
CAFile: "/path/to/ca/file",
|
||||
CertFile: "/path/to/cert/file",
|
||||
KeyFile: "/path/to/key/file",
|
||||
ServerAutoJoin: &trueValue,
|
||||
ClientAutoJoin: &trueValue,
|
||||
AutoAdvertise: &trueValue,
|
||||
ChecksUseAdvertise: &trueValue,
|
||||
Timeout: 5 * time.Second,
|
||||
},
|
||||
Vault: &config.VaultConfig{
|
||||
Addr: "127.0.0.1:9500",
|
||||
|
||||
@@ -159,21 +159,22 @@ func TestConfig_Merge(t *testing.T) {
|
||||
TLSServerName: "1",
|
||||
},
|
||||
Consul: &config.ConsulConfig{
|
||||
ServerServiceName: "1",
|
||||
ClientServiceName: "1",
|
||||
AutoAdvertise: &falseValue,
|
||||
Addr: "1",
|
||||
Timeout: 1 * time.Second,
|
||||
Token: "1",
|
||||
Auth: "1",
|
||||
EnableSSL: &falseValue,
|
||||
VerifySSL: &falseValue,
|
||||
CAFile: "1",
|
||||
CertFile: "1",
|
||||
KeyFile: "1",
|
||||
ServerAutoJoin: &falseValue,
|
||||
ClientAutoJoin: &falseValue,
|
||||
ChecksUseAdvertise: &falseValue,
|
||||
ServerServiceName: "1",
|
||||
ClientServiceName: "1",
|
||||
AutoAdvertise: &falseValue,
|
||||
Addr: "1",
|
||||
AllowUnauthenticated: &falseValue,
|
||||
Timeout: 1 * time.Second,
|
||||
Token: "1",
|
||||
Auth: "1",
|
||||
EnableSSL: &falseValue,
|
||||
VerifySSL: &falseValue,
|
||||
CAFile: "1",
|
||||
CertFile: "1",
|
||||
KeyFile: "1",
|
||||
ServerAutoJoin: &falseValue,
|
||||
ClientAutoJoin: &falseValue,
|
||||
ChecksUseAdvertise: &falseValue,
|
||||
},
|
||||
Autopilot: &config.AutopilotConfig{
|
||||
CleanupDeadServers: &falseValue,
|
||||
@@ -333,21 +334,22 @@ func TestConfig_Merge(t *testing.T) {
|
||||
TLSServerName: "2",
|
||||
},
|
||||
Consul: &config.ConsulConfig{
|
||||
ServerServiceName: "2",
|
||||
ClientServiceName: "2",
|
||||
AutoAdvertise: &trueValue,
|
||||
Addr: "2",
|
||||
Timeout: 2 * time.Second,
|
||||
Token: "2",
|
||||
Auth: "2",
|
||||
EnableSSL: &trueValue,
|
||||
VerifySSL: &trueValue,
|
||||
CAFile: "2",
|
||||
CertFile: "2",
|
||||
KeyFile: "2",
|
||||
ServerAutoJoin: &trueValue,
|
||||
ClientAutoJoin: &trueValue,
|
||||
ChecksUseAdvertise: &trueValue,
|
||||
ServerServiceName: "2",
|
||||
ClientServiceName: "2",
|
||||
AutoAdvertise: &trueValue,
|
||||
Addr: "2",
|
||||
AllowUnauthenticated: &trueValue,
|
||||
Timeout: 2 * time.Second,
|
||||
Token: "2",
|
||||
Auth: "2",
|
||||
EnableSSL: &trueValue,
|
||||
VerifySSL: &trueValue,
|
||||
CAFile: "2",
|
||||
CertFile: "2",
|
||||
KeyFile: "2",
|
||||
ServerAutoJoin: &trueValue,
|
||||
ClientAutoJoin: &trueValue,
|
||||
ChecksUseAdvertise: &trueValue,
|
||||
},
|
||||
Sentinel: &config.SentinelConfig{
|
||||
Imports: []*config.SentinelImport{
|
||||
|
||||
@@ -633,6 +633,7 @@ func ApiJobToStructJob(job *api.Job) *structs.Job {
|
||||
Datacenters: job.Datacenters,
|
||||
Payload: job.Payload,
|
||||
Meta: job.Meta,
|
||||
ConsulToken: *job.ConsulToken,
|
||||
VaultToken: *job.VaultToken,
|
||||
Constraints: ApiConstraintsToStructs(job.Constraints),
|
||||
Affinities: ApiAffinitiesToStructs(job.Affinities),
|
||||
|
||||
@@ -1714,7 +1714,8 @@ func TestJobs_ApiJobToStructsJob(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
VaultToken: helper.StringToPtr("token"),
|
||||
ConsulToken: helper.StringToPtr("abc123"),
|
||||
VaultToken: helper.StringToPtr("def456"),
|
||||
Status: helper.StringToPtr("status"),
|
||||
StatusDescription: helper.StringToPtr("status_desc"),
|
||||
Version: helper.Uint64ToPtr(10),
|
||||
@@ -2060,7 +2061,8 @@ func TestJobs_ApiJobToStructsJob(t *testing.T) {
|
||||
},
|
||||
},
|
||||
|
||||
VaultToken: "token",
|
||||
ConsulToken: "abc123",
|
||||
VaultToken: "def456",
|
||||
}
|
||||
|
||||
structsJob := ApiJobToStructJob(apiJob)
|
||||
|
||||
1
command/agent/testdata/basic.hcl
vendored
1
command/agent/testdata/basic.hcl
vendored
@@ -174,6 +174,7 @@ consul {
|
||||
client_service_name = "nomad-client"
|
||||
client_http_check_name = "nomad-client-http-health-check"
|
||||
address = "127.0.0.1:9500"
|
||||
allow_unauthenticated = true
|
||||
token = "token1"
|
||||
auth = "username:pass"
|
||||
ssl = true
|
||||
|
||||
1
command/agent/testdata/basic.json
vendored
1
command/agent/testdata/basic.json
vendored
@@ -111,6 +111,7 @@
|
||||
"consul": [
|
||||
{
|
||||
"address": "127.0.0.1:9500",
|
||||
"allow_unauthenticated": true,
|
||||
"auth": "username:pass",
|
||||
"auto_advertise": true,
|
||||
"ca_file": "/path/to/ca/file",
|
||||
|
||||
@@ -31,9 +31,13 @@ Revert Options:
|
||||
the evaluation ID will be printed to the screen, which can be used to
|
||||
examine the evaluation using the eval-status command.
|
||||
|
||||
-consul-token
|
||||
The Consul token used to verify that the caller has access to the Service
|
||||
Identity policies associated in the targeted version of the job.
|
||||
|
||||
-vault-token
|
||||
The Vault token used to verify that the caller has access to the Vault
|
||||
policies i the targeted version of the job.
|
||||
policies in the targeted version of the job.
|
||||
|
||||
-verbose
|
||||
Display full information.
|
||||
@@ -72,12 +76,13 @@ func (c *JobRevertCommand) Name() string { return "job revert" }
|
||||
|
||||
func (c *JobRevertCommand) Run(args []string) int {
|
||||
var detach, verbose bool
|
||||
var vaultToken string
|
||||
var consulToken, vaultToken string
|
||||
|
||||
flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
|
||||
flags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
flags.BoolVar(&detach, "detach", false, "")
|
||||
flags.BoolVar(&verbose, "verbose", false, "")
|
||||
flags.StringVar(&consulToken, "consul-token", "", "")
|
||||
flags.StringVar(&vaultToken, "vault-token", "", "")
|
||||
|
||||
if err := flags.Parse(args); err != nil {
|
||||
@@ -105,6 +110,12 @@ func (c *JobRevertCommand) Run(args []string) int {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Parse the Consul token
|
||||
if consulToken == "" {
|
||||
// Check the environment variable
|
||||
consulToken = os.Getenv("CONSUL_TOKEN")
|
||||
}
|
||||
|
||||
// Parse the Vault token
|
||||
if vaultToken == "" {
|
||||
// Check the environment variable
|
||||
@@ -138,7 +149,7 @@ func (c *JobRevertCommand) Run(args []string) int {
|
||||
}
|
||||
|
||||
// Prefix lookup matched a single job
|
||||
resp, _, err := client.Jobs().Revert(jobs[0].ID, revertVersion, nil, nil, vaultToken)
|
||||
resp, _, err := client.Jobs().Revert(jobs[0].ID, revertVersion, nil, nil, consulToken, vaultToken)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error retrieving job versions: %s", err))
|
||||
return 1
|
||||
|
||||
@@ -52,6 +52,10 @@ Alias: nomad run
|
||||
If the job has specified the region, the -region flag and NOMAD_REGION
|
||||
environment variable are overridden and the job's region is used.
|
||||
|
||||
The run command will set the consul_token of the job based on the following
|
||||
precedence, going from highest to lowest: the -consul-token flag, the
|
||||
$CONSUL_TOKEN environment variable and finally the value in the job file.
|
||||
|
||||
The run command will set the vault_token of the job based on the following
|
||||
precedence, going from highest to lowest: the -vault-token flag, the
|
||||
$VAULT_TOKEN environment variable and finally the value in the job file.
|
||||
@@ -82,6 +86,12 @@ Run Options:
|
||||
-policy-override
|
||||
Sets the flag to force override any soft mandatory Sentinel policies.
|
||||
|
||||
-consul-token
|
||||
If set, the passed Consul token is stored in the job before sending to the
|
||||
Nomad servers. This allows passing the Consul token without storing it in
|
||||
the job file. This overrides the token found in $CONSUL_TOKEN environment
|
||||
variable and that found in the job.
|
||||
|
||||
-vault-token
|
||||
If set, the passed Vault token is stored in the job before sending to the
|
||||
Nomad servers. This allows passing the Vault token without storing it in
|
||||
@@ -104,6 +114,7 @@ func (c *JobRunCommand) AutocompleteFlags() complete.Flags {
|
||||
"-check-index": complete.PredictNothing,
|
||||
"-detach": complete.PredictNothing,
|
||||
"-verbose": complete.PredictNothing,
|
||||
"-consul-token": complete.PredictNothing,
|
||||
"-vault-token": complete.PredictAnything,
|
||||
"-output": complete.PredictNothing,
|
||||
"-policy-override": complete.PredictNothing,
|
||||
@@ -118,7 +129,7 @@ func (c *JobRunCommand) Name() string { return "job run" }
|
||||
|
||||
func (c *JobRunCommand) Run(args []string) int {
|
||||
var detach, verbose, output, override bool
|
||||
var checkIndexStr, vaultToken string
|
||||
var checkIndexStr, consulToken, vaultToken string
|
||||
|
||||
flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
|
||||
flags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
@@ -127,6 +138,7 @@ func (c *JobRunCommand) Run(args []string) int {
|
||||
flags.BoolVar(&output, "output", false, "")
|
||||
flags.BoolVar(&override, "policy-override", false, "")
|
||||
flags.StringVar(&checkIndexStr, "check-index", "", "")
|
||||
flags.StringVar(&consulToken, "consul-token", "", "")
|
||||
flags.StringVar(&vaultToken, "vault-token", "", "")
|
||||
|
||||
if err := flags.Parse(args); err != nil {
|
||||
@@ -175,6 +187,16 @@ func (c *JobRunCommand) Run(args []string) int {
|
||||
periodic := job.IsPeriodic()
|
||||
paramjob := job.IsParameterized()
|
||||
|
||||
// Parse the Consul token
|
||||
if consulToken == "" {
|
||||
// Check the environment variable
|
||||
consulToken = os.Getenv("CONSUL_TOKEN")
|
||||
}
|
||||
|
||||
if consulToken != "" {
|
||||
job.ConsulToken = helper.StringToPtr(consulToken)
|
||||
}
|
||||
|
||||
// Parse the Vault token
|
||||
if vaultToken == "" {
|
||||
// Check the environment variable
|
||||
|
||||
@@ -79,6 +79,7 @@ func parseJob(result *api.Job, list *ast.ObjectList) error {
|
||||
"update",
|
||||
"vault",
|
||||
"vault_token",
|
||||
"consul_token",
|
||||
}
|
||||
if err := helper.CheckHCLKeys(listVal, valid); err != nil {
|
||||
return multierror.Prefix(err, "job:")
|
||||
|
||||
@@ -31,6 +31,7 @@ func TestParse(t *testing.T) {
|
||||
Datacenters: []string{"us2", "eu1"},
|
||||
Region: helper.StringToPtr("fooregion"),
|
||||
Namespace: helper.StringToPtr("foonamespace"),
|
||||
ConsulToken: helper.StringToPtr("abc"),
|
||||
VaultToken: helper.StringToPtr("foo"),
|
||||
|
||||
Meta: map[string]string{
|
||||
|
||||
@@ -4,6 +4,7 @@ job "binstore-storagelocker" {
|
||||
priority = 50
|
||||
all_at_once = true
|
||||
datacenters = ["us2", "eu1"]
|
||||
consul_token = "abc"
|
||||
vault_token = "foo"
|
||||
|
||||
meta {
|
||||
|
||||
@@ -5,6 +5,7 @@ job "binstore-storagelocker" {
|
||||
priority = 52
|
||||
all_at_once = true
|
||||
datacenters = ["us2", "eu1"]
|
||||
consul_token = "abc"
|
||||
vault_token = "foo"
|
||||
|
||||
meta {
|
||||
|
||||
@@ -4,6 +4,7 @@ job "binstore-storagelocker" {
|
||||
priority = 50
|
||||
all_at_once = true
|
||||
datacenters = ["us2", "eu1"]
|
||||
consul_token = "abc"
|
||||
vault_token = "foo"
|
||||
|
||||
meta {
|
||||
|
||||
@@ -4,6 +4,7 @@ job "binstore-storagelocker" {
|
||||
priority = 50
|
||||
all_at_once = true
|
||||
datacenters = ["us2", "eu1"]
|
||||
consul_token = "abc"
|
||||
vault_token = "foo"
|
||||
|
||||
meta {
|
||||
|
||||
@@ -4,6 +4,7 @@ job "binstore-storagelocker" {
|
||||
priority = 50
|
||||
all_at_once = true
|
||||
datacenters = ["us2", "eu1"]
|
||||
consul_token = "abc"
|
||||
vault_token = "foo"
|
||||
|
||||
meta {
|
||||
|
||||
@@ -72,6 +72,11 @@ type ConsulConfig struct {
|
||||
// the agent's default token
|
||||
Token string `hcl:"token"`
|
||||
|
||||
// AllowUnauthenticated allows users to submit jobs requiring Consul
|
||||
// Service Identity tokens without providing a Consul token proving they
|
||||
// have access to such policies.
|
||||
AllowUnauthenticated *bool `hcl:"allow_unauthenticated"`
|
||||
|
||||
// Auth is the information to use for http access to Consul agent
|
||||
Auth string `hcl:"auth"`
|
||||
|
||||
@@ -115,17 +120,18 @@ type ConsulConfig struct {
|
||||
func DefaultConsulConfig() *ConsulConfig {
|
||||
def := consul.DefaultConfig()
|
||||
return &ConsulConfig{
|
||||
ServerServiceName: "nomad",
|
||||
ServerHTTPCheckName: "Nomad Server HTTP Check",
|
||||
ServerSerfCheckName: "Nomad Server Serf Check",
|
||||
ServerRPCCheckName: "Nomad Server RPC Check",
|
||||
ClientServiceName: "nomad-client",
|
||||
ClientHTTPCheckName: "Nomad Client HTTP Check",
|
||||
AutoAdvertise: helper.BoolToPtr(true),
|
||||
ChecksUseAdvertise: helper.BoolToPtr(false),
|
||||
ServerAutoJoin: helper.BoolToPtr(true),
|
||||
ClientAutoJoin: helper.BoolToPtr(true),
|
||||
Timeout: 5 * time.Second,
|
||||
ServerServiceName: "nomad",
|
||||
ServerHTTPCheckName: "Nomad Server HTTP Check",
|
||||
ServerSerfCheckName: "Nomad Server Serf Check",
|
||||
ServerRPCCheckName: "Nomad Server RPC Check",
|
||||
ClientServiceName: "nomad-client",
|
||||
ClientHTTPCheckName: "Nomad Client HTTP Check",
|
||||
AutoAdvertise: helper.BoolToPtr(true),
|
||||
ChecksUseAdvertise: helper.BoolToPtr(false),
|
||||
ServerAutoJoin: helper.BoolToPtr(true),
|
||||
ClientAutoJoin: helper.BoolToPtr(true),
|
||||
AllowUnauthenticated: helper.BoolToPtr(true),
|
||||
Timeout: 5 * time.Second,
|
||||
|
||||
// From Consul api package defaults
|
||||
Addr: def.Address,
|
||||
@@ -135,6 +141,12 @@ func DefaultConsulConfig() *ConsulConfig {
|
||||
}
|
||||
}
|
||||
|
||||
// AllowsUnauthenticated returns whether the config allows unauthenticated
|
||||
// creation of Consul Service Identity tokens for Consul Connect enabled Tasks.
|
||||
func (a *ConsulConfig) AllowsUnauthenticated() bool {
|
||||
return a.AllowUnauthenticated != nil && *a.AllowUnauthenticated
|
||||
}
|
||||
|
||||
// Merge merges two Consul Configurations together.
|
||||
func (a *ConsulConfig) Merge(b *ConsulConfig) *ConsulConfig {
|
||||
result := a.Copy()
|
||||
@@ -203,6 +215,9 @@ func (a *ConsulConfig) Merge(b *ConsulConfig) *ConsulConfig {
|
||||
if b.ChecksUseAdvertise != nil {
|
||||
result.ChecksUseAdvertise = helper.BoolToPtr(*b.ChecksUseAdvertise)
|
||||
}
|
||||
if b.AllowUnauthenticated != nil {
|
||||
result.AllowUnauthenticated = helper.BoolToPtr(*b.AllowUnauthenticated)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -289,6 +304,9 @@ func (c *ConsulConfig) Copy() *ConsulConfig {
|
||||
if nc.ClientAutoJoin != nil {
|
||||
nc.ClientAutoJoin = helper.BoolToPtr(*nc.ClientAutoJoin)
|
||||
}
|
||||
if nc.AllowUnauthenticated != nil {
|
||||
nc.AllowUnauthenticated = helper.BoolToPtr(*nc.AllowUnauthenticated)
|
||||
}
|
||||
|
||||
return nc
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
consulapi "github.com/hashicorp/consul/api"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -27,6 +28,94 @@ func TestMain(m *testing.M) {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func TestConsulConfig_Merge(t *testing.T) {
|
||||
yes, no := true, false
|
||||
|
||||
c1 := &ConsulConfig{
|
||||
ServerServiceName: "1",
|
||||
ServerHTTPCheckName: "1",
|
||||
ServerSerfCheckName: "1",
|
||||
ServerRPCCheckName: "1",
|
||||
ClientServiceName: "1",
|
||||
ClientHTTPCheckName: "1",
|
||||
Tags: []string{"a", "1"},
|
||||
AutoAdvertise: &no,
|
||||
ChecksUseAdvertise: &no,
|
||||
Addr: "1",
|
||||
GRPCAddr: "1",
|
||||
Timeout: time.Duration(1),
|
||||
TimeoutHCL: "1",
|
||||
Token: "1",
|
||||
AllowUnauthenticated: &no,
|
||||
Auth: "1",
|
||||
EnableSSL: &no,
|
||||
VerifySSL: &no,
|
||||
CAFile: "1",
|
||||
CertFile: "1",
|
||||
KeyFile: "1",
|
||||
ServerAutoJoin: &no,
|
||||
ClientAutoJoin: &no,
|
||||
ExtraKeysHCL: []string{"a", "1"},
|
||||
}
|
||||
|
||||
c2 := &ConsulConfig{
|
||||
ServerServiceName: "2",
|
||||
ServerHTTPCheckName: "2",
|
||||
ServerSerfCheckName: "2",
|
||||
ServerRPCCheckName: "2",
|
||||
ClientServiceName: "2",
|
||||
ClientHTTPCheckName: "2",
|
||||
Tags: []string{"b", "2"},
|
||||
AutoAdvertise: &yes,
|
||||
ChecksUseAdvertise: &yes,
|
||||
Addr: "2",
|
||||
GRPCAddr: "2",
|
||||
Timeout: time.Duration(2),
|
||||
TimeoutHCL: "2",
|
||||
Token: "2",
|
||||
AllowUnauthenticated: &yes,
|
||||
Auth: "2",
|
||||
EnableSSL: &yes,
|
||||
VerifySSL: &yes,
|
||||
CAFile: "2",
|
||||
CertFile: "2",
|
||||
KeyFile: "2",
|
||||
ServerAutoJoin: &yes,
|
||||
ClientAutoJoin: &yes,
|
||||
ExtraKeysHCL: []string{"b", "2"},
|
||||
}
|
||||
|
||||
exp := &ConsulConfig{
|
||||
ServerServiceName: "2",
|
||||
ServerHTTPCheckName: "2",
|
||||
ServerSerfCheckName: "2",
|
||||
ServerRPCCheckName: "2",
|
||||
ClientServiceName: "2",
|
||||
ClientHTTPCheckName: "2",
|
||||
Tags: []string{"a", "1", "b", "2"},
|
||||
AutoAdvertise: &yes,
|
||||
ChecksUseAdvertise: &yes,
|
||||
Addr: "2",
|
||||
GRPCAddr: "2",
|
||||
Timeout: time.Duration(2),
|
||||
TimeoutHCL: "2",
|
||||
Token: "2",
|
||||
AllowUnauthenticated: &yes,
|
||||
Auth: "2",
|
||||
EnableSSL: &yes,
|
||||
VerifySSL: &yes,
|
||||
CAFile: "2",
|
||||
CertFile: "2",
|
||||
KeyFile: "2",
|
||||
ServerAutoJoin: &yes,
|
||||
ClientAutoJoin: &yes,
|
||||
ExtraKeysHCL: []string{"a", "1"}, // not merged
|
||||
}
|
||||
|
||||
result := c1.Merge(c2)
|
||||
require.Equal(t, exp, result)
|
||||
}
|
||||
|
||||
// TestConsulConfig_Defaults asserts Consul defaults are copied from their
|
||||
// upstream API package defaults.
|
||||
func TestConsulConfig_Defaults(t *testing.T) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package config
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/nomad/helper"
|
||||
vault "github.com/hashicorp/vault/api"
|
||||
)
|
||||
|
||||
@@ -84,11 +85,9 @@ type VaultConfig struct {
|
||||
// `vault` configuration.
|
||||
func DefaultVaultConfig() *VaultConfig {
|
||||
return &VaultConfig{
|
||||
Addr: "https://vault.service.consul:8200",
|
||||
ConnectionRetryIntv: DefaultVaultConnectRetryIntv,
|
||||
AllowUnauthenticated: func(b bool) *bool {
|
||||
return &b
|
||||
}(true),
|
||||
Addr: "https://vault.service.consul:8200",
|
||||
ConnectionRetryIntv: DefaultVaultConnectRetryIntv,
|
||||
AllowUnauthenticated: helper.BoolToPtr(true),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -641,6 +641,12 @@ type JobRevertRequest struct {
|
||||
// version before reverting.
|
||||
EnforcePriorVersion *uint64
|
||||
|
||||
// ConsulToken is the Consul token that proves the submitter of the job revert
|
||||
// has access to the Service Identity policies associated with the job's
|
||||
// Consul Connect enabled services. This field is only used to transfer the
|
||||
// token and is not stored after the Job revert.
|
||||
ConsulToken string
|
||||
|
||||
// VaultToken is the Vault token that proves the submitter of the job revert
|
||||
// has access to any Vault policies specified in the targeted job version. This
|
||||
// field is only used to transfer the token and is not stored after the Job
|
||||
@@ -3403,6 +3409,12 @@ type Job struct {
|
||||
// job. This is opaque to Nomad.
|
||||
Meta map[string]string
|
||||
|
||||
// ConsulToken is the Consul token that proves the submitter of the job has
|
||||
// access to the Service Identity policies associated with the job's
|
||||
// Consul Connect enabled services. This field is only used to transfer the
|
||||
// token and is not stored after Job submission.
|
||||
ConsulToken string
|
||||
|
||||
// VaultToken is the Vault token that proves the submitter of the job has
|
||||
// access to the specified Vault policies. This field is only used to
|
||||
// transfer the token and is not stored after Job submission.
|
||||
|
||||
@@ -1302,6 +1302,9 @@ The table below shows this endpoint's support for
|
||||
job's version. This is checked and acts as a check-and-set value before
|
||||
reverting to the specified job.
|
||||
|
||||
- `ConsulToken` `(string:"")` - Optional value specifying the [consul token](/docs/commands/job/revert.html)
|
||||
used for Consul [service identity polity authentication checking](/docs/configuration/consul.html#allow_unauthenticated).
|
||||
|
||||
- `VaultToken` `(string: "")` - Optional value specifying the [vault token](/docs/commands/job/revert.html)
|
||||
used for Vault [policy authentication checking](/docs/configuration/vault.html#allow_unauthenticated).
|
||||
|
||||
|
||||
@@ -12,12 +12,19 @@ The `job revert` command is used to revert a job to a prior version of the
|
||||
job. The available versions to revert to can be found using [`job history`]
|
||||
command.
|
||||
|
||||
The revert command will use a Consul token with the following preference:
|
||||
first the `-consul-token` flag, then the `$CONSUL_TOKEN` environment variable.
|
||||
Because the consul token used to [run] the targeted job version was not
|
||||
persisted, it must be provided to revert if the targeted job version includes
|
||||
Consul Connect enabled services and the Nomad servers were configured to require
|
||||
[consul service identity] authentication.
|
||||
|
||||
The revert command will use a Vault token with the following preference:
|
||||
first the `-vault-token` flag, then the `$VAULT_TOKEN` environment variable.
|
||||
Because the vault token used to [run] the targeted job version was not
|
||||
persisted, it must be provided to revert if the targeted job version includes
|
||||
Vault policies and the Nomad servers were configured to
|
||||
[require authentication].
|
||||
Vault policies and the Nomad servers were configured to require [vault policy]
|
||||
authentication.
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -38,6 +45,10 @@ job to revert to.
|
||||
will be output, which can be used to examine the evaluation using the
|
||||
[eval status] command.
|
||||
|
||||
- `-consul-token`: If set, the passed Consul token is sent along with the revert
|
||||
request to the Nomad servers. This overrides the token found in the
|
||||
$CONSUL_TOKEN environment variable.
|
||||
|
||||
- `-vault-token`: If set, the passed Vault token is sent along with the revert
|
||||
request to the Nomad servers. This overrides the token found in the
|
||||
$VAULT_TOKEN environment variable.
|
||||
@@ -106,5 +117,6 @@ Submit Date = 07/25/17 21:27:18 UTC
|
||||
|
||||
[`job history`]: /docs/commands/job/history.html
|
||||
[eval status]: /docs/commands/eval-status.html
|
||||
[require authentication]: /docs/configuration/vault.html#allow_unauthenticated
|
||||
[consul service identity]: /docs/configuration/consul.html#allow_unauthenticated
|
||||
[vault policy]: /docs/configuration/vault.html#allow_unauthenticated
|
||||
[run]: /docs/commands/job/run.html
|
||||
|
||||
@@ -39,6 +39,10 @@ client connection issues or internal errors, are indicated by exit code 1.
|
||||
If the job has specified the region, the -region flag and NOMAD_REGION
|
||||
environment variable are overridden and the job's region is used.
|
||||
|
||||
The run command will set the `consul_token` of the job based on the following
|
||||
precedence, going from highest to lowest: the `-consul-token` flag, the
|
||||
`$CONSUL_TOKEN` environment variable and finally the value in the job file.
|
||||
|
||||
The run command will set the `vault_token` of the job based on the following
|
||||
precedence, going from highest to lowest: the `-vault-token` flag, the
|
||||
`$VAULT_TOKEN` environment variable and finally the value in the job file.
|
||||
@@ -66,6 +70,11 @@ precedence, going from highest to lowest: the `-vault-token` flag, the
|
||||
- `-policy-override`: Sets the flag to force override any soft mandatory
|
||||
Sentinel policies.
|
||||
|
||||
- `-consul-token`: If set, the passed Consul token is stored in the job before
|
||||
sending to the Nomad servers. This allows passing the Consul token without
|
||||
storing it in the job file. This overrides the token found in the $CONSUL_TOKEN
|
||||
environment variable and that found in the job.
|
||||
|
||||
- `-vault-token`: If set, the passed Vault token is stored in the job before
|
||||
sending to the Nomad servers. This allows passing the Vault token without
|
||||
storing it in the job file. This overrides the token found in the $VAULT_TOKEN
|
||||
|
||||
@@ -54,6 +54,12 @@ configuring Nomad to talk to Consul via DNS such as consul.service.consul
|
||||
format: `unix:///tmp/consul/consul.sock`. Will default to the
|
||||
`CONSUL_HTTP_ADDR` environment variable if set.
|
||||
|
||||
- `allow_unauthenticated` `(bool: true)` - Specifies if users submitting jobs to
|
||||
the Nomad server should be required to provide their own Consul token, proving
|
||||
they have access to the service identity policies required by the Consul Connect
|
||||
enabled services listed in the job. This option should be
|
||||
disabled in an untrusted environment.
|
||||
|
||||
- `auth` `(string: "")` - Specifies the HTTP Basic Authentication information to
|
||||
use for access to the Consul Agent, given in the format `username:password`.
|
||||
|
||||
|
||||
@@ -137,6 +137,16 @@ job "docs" {
|
||||
accidentally. Users should set the `VAULT_TOKEN` environment variable when
|
||||
running the job instead.
|
||||
|
||||
- `consul_token` `(string: "")` - Specifies the Consul token that proves the
|
||||
submitter of the job has access to the Service Identity policies associated
|
||||
with the job's Consul Connect enabled services. This field is only used to
|
||||
transfer the token and is not stored after job submission.
|
||||
|
||||
!> It is **strongly discouraged** to place the token as a configuration
|
||||
parameter like this, since the token could be checked into source control
|
||||
accidentally. Users should set the `CONSUL_TOKEN` environment variable when
|
||||
running the job instead.
|
||||
|
||||
## `job` Examples
|
||||
|
||||
The following examples only show the `job` stanzas. Remember that the
|
||||
|
||||
Reference in New Issue
Block a user