nomad: enforce ACLs on job submit
This commit is contained in:
parent
6f5150a227
commit
ac6283c31f
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/hashicorp/consul/lib"
|
||||
"github.com/hashicorp/go-memdb"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/hashicorp/nomad/acl"
|
||||
"github.com/hashicorp/nomad/client/driver"
|
||||
"github.com/hashicorp/nomad/helper"
|
||||
"github.com/hashicorp/nomad/nomad/state"
|
||||
|
@ -71,6 +72,13 @@ func (j *Job) Register(args *structs.JobRegisterRequest, reply *structs.JobRegis
|
|||
// Set the warning message
|
||||
reply.Warnings = structs.MergeMultierrorWarnings(warnings, canonicalizeWarnings)
|
||||
|
||||
// Check job submission permissions
|
||||
if aclObj, err := j.srv.resolveToken(args.SecretID); err != nil {
|
||||
return err
|
||||
} else if aclObj != nil && !aclObj.AllowNamespaceOperation(structs.DefaultNamespace, acl.NamespaceCapabilitySubmitJob) {
|
||||
return structs.ErrPermissionDenied
|
||||
}
|
||||
|
||||
// Lookup the job
|
||||
snap, err := j.srv.fsm.State().Snapshot()
|
||||
if err != nil {
|
||||
|
|
|
@ -93,6 +93,49 @@ func TestJobEndpoint_Register(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestJobEndpoint_Register_ACL(t *testing.T) {
|
||||
t.Parallel()
|
||||
s1, root := testACLServer(t, func(c *Config) {
|
||||
c.NumSchedulers = 0 // Prevent automatic dequeue
|
||||
})
|
||||
defer s1.Shutdown()
|
||||
codec := rpcClient(t, s1)
|
||||
testutil.WaitForLeader(t, s1.RPC)
|
||||
|
||||
// Create the register request
|
||||
job := mock.Job()
|
||||
req := &structs.JobRegisterRequest{
|
||||
Job: job,
|
||||
WriteRequest: structs.WriteRequest{Region: "global"},
|
||||
}
|
||||
|
||||
// Try without a token, expect failure
|
||||
var resp structs.JobRegisterResponse
|
||||
if err := msgpackrpc.CallWithCodec(codec, "Job.Register", req, &resp); err == nil {
|
||||
t.Fatalf("expected error")
|
||||
}
|
||||
|
||||
// Try with a token
|
||||
req.SecretID = root.SecretID
|
||||
if err := msgpackrpc.CallWithCodec(codec, "Job.Register", req, &resp); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if resp.Index == 0 {
|
||||
t.Fatalf("bad index: %d", resp.Index)
|
||||
}
|
||||
|
||||
// Check for the node in the FSM
|
||||
state := s1.fsm.State()
|
||||
ws := memdb.NewWatchSet()
|
||||
out, err := state.JobByID(ws, job.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if out == nil {
|
||||
t.Fatalf("expected job")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJobEndpoint_Register_InvalidDriverConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
s1 := testServer(t, func(c *Config) {
|
||||
|
|
|
@ -108,6 +108,9 @@ const (
|
|||
// ACLClientToken and ACLManagementToken are the only types of tokens
|
||||
ACLClientToken = "client"
|
||||
ACLManagementToken = "management"
|
||||
|
||||
// DefaultNamespace is the default namespace.
|
||||
DefaultNamespace = "default"
|
||||
)
|
||||
|
||||
// Context defines the scope in which a search for Nomad object operates, and
|
||||
|
|
Loading…
Reference in New Issue