Merge pull request #3373 from hashicorp/f-403

Permission denied results in 403
This commit is contained in:
Alex Dadgar
2017-10-12 15:47:29 -07:00
committed by GitHub
5 changed files with 89 additions and 0 deletions

View File

@@ -69,6 +69,7 @@ func (c *Command) readConfig() *Config {
Ports: &Ports{},
Server: &ServerConfig{},
Vault: &config.VaultConfig{},
ACL: &ACLConfig{},
}
flags := flag.NewFlagSet("agent", flag.ContinueOnError)
@@ -166,6 +167,10 @@ func (c *Command) readConfig() *Config {
}), "vault-tls-skip-verify", "")
flags.StringVar(&cmdConfig.Vault.TLSServerName, "vault-tls-server-name", "", "")
// ACL options
flags.BoolVar(&cmdConfig.ACL.Enabled, "acl-enabled", false, "")
flags.StringVar(&cmdConfig.ACL.ReplicationToken, "acl-replication-token", "", "")
if err := flags.Parse(c.args); err != nil {
return nil
}
@@ -984,6 +989,16 @@ Client Options:
The default speed for network interfaces in MBits if the link speed can not
be determined dynamically.
ACL Options:
-acl-enabled
Specifies whether the agent should enable ACLs.
-acl-replication-token
The replication token for servers to use when replicating from the
authoratative region. The token must be a valid management token from the
authoratative region.
Consul Options:
-consul-address=<addr>

View File

@@ -301,7 +301,13 @@ func (s *HTTPServer) wrap(handler func(resp http.ResponseWriter, req *http.Reque
code := 500
if http, ok := err.(HTTPCodedError); ok {
code = http.Code()
} else {
switch err.Error() {
case structs.ErrPermissionDenied.Error(), structs.ErrTokenNotFound.Error():
code = 403
}
}
resp.WriteHeader(code)
resp.Write([]byte(err.Error()))
return

View File

@@ -20,6 +20,7 @@ import (
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/nomad/structs/config"
"github.com/hashicorp/nomad/testutil"
"github.com/stretchr/testify/assert"
"github.com/ugorji/go/codec"
)
@@ -218,6 +219,40 @@ func testPrettyPrint(pretty string, prettyFmt bool, t *testing.T) {
}
}
func TestPermissionDenied(t *testing.T) {
s := makeHTTPServer(t, func(c *Config) {
c.ACL.Enabled = true
})
defer s.Shutdown()
resp := httptest.NewRecorder()
handler := func(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
return nil, structs.ErrPermissionDenied
}
urlStr := "/v1/job/foo"
req, _ := http.NewRequest("GET", urlStr, nil)
s.Server.wrap(handler)(resp, req)
assert.Equal(t, resp.Code, 403)
}
func TestTokenNotFound(t *testing.T) {
s := makeHTTPServer(t, func(c *Config) {
c.ACL.Enabled = true
})
defer s.Shutdown()
resp := httptest.NewRecorder()
handler := func(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
return nil, structs.ErrTokenNotFound
}
urlStr := "/v1/job/foo"
req, _ := http.NewRequest("GET", urlStr, nil)
s.Server.wrap(handler)(resp, req)
assert.Equal(t, resp.Code, 403)
}
func TestParseWait(t *testing.T) {
t.Parallel()
resp := httptest.NewRecorder()

View File

@@ -211,6 +211,37 @@ func TestHTTP_JobsRegister_ACL(t *testing.T) {
})
}
// Test that permission denied gets a 403
func TestHTTP_JobsRegister_ACL_Bad(t *testing.T) {
t.Parallel()
httpACLTest(t, nil, func(s *TestAgent) {
// Create the job
job := api.MockJob()
args := api.JobRegisterRequest{
Job: job,
WriteRequest: api.WriteRequest{
Region: "global",
},
}
buf := encodeReq(args)
// Make the HTTP request
req, err := http.NewRequest("PUT", "/v1/jobs", buf)
if err != nil {
t.Fatalf("err: %v", err)
}
respW := httptest.NewRecorder()
// Make the request
obj, err := s.Server.JobsRequest(respW, req)
if err != nil {
t.Fatalf("err: %v", err)
}
assert.Nil(t, obj)
assert.Contains(t, err.Error(), "403")
})
}
func TestHTTP_JobsRegister_Defaulting(t *testing.T) {
t.Parallel()
httpTest(t, nil, func(s *TestAgent) {

View File

@@ -24,6 +24,8 @@ via CLI arguments. The `agent` command accepts the following arguments:
* `-alloc-dir=<path>`: Equivalent to the Client [alloc_dir](#alloc_dir) config
option.
* `-acl-enabled`: Equivalent to the ACL [enabled](/docs/agent/configuration/acl.html#enabled) config option.
* `-acl-replication-token`: Equivalent to the ACL [replication_token](/docs/agent/configuration/acl.html#replication_token) config option.
* `-bind=<address>`: Equivalent to the [bind_addr](#bind_addr) config option.
* `-bootstrap-expect=<num>`: Equivalent to the
[bootstrap_expect](#bootstrap_expect) config option.