Skip to content

Commit

Permalink
Disable the sys/raw endpoint by default (#3329)
Browse files Browse the repository at this point in the history
* disable raw endpoint by default

* adding docs

* config option raw -> raw_storage_endpoint

* docs updates

* adding listing on raw endpoint

* reworking tests for enabled raw endpoints

* root protecting base raw endpoint
  • Loading branch information
chrishoffman authored Sep 15, 2017
1 parent 2c6e642 commit 4a8c33c
Show file tree
Hide file tree
Showing 14 changed files with 179 additions and 49 deletions.
1 change: 1 addition & 0 deletions command/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ func (c *ServerCommand) Run(args []string) int {
ClusterName: config.ClusterName,
CacheSize: config.CacheSize,
PluginDirectory: config.PluginDirectory,
EnableRaw: config.EnableRawEndpoint,
}
if dev {
coreConfig.DevToken = devRootTokenID
Expand Down
23 changes: 19 additions & 4 deletions command/server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,17 @@ type Config struct {
ClusterCipherSuites string `hcl:"cluster_cipher_suites"`

PluginDirectory string `hcl:"plugin_directory"`

EnableRawEndpoint bool `hcl:"-"`
EnableRawEndpointRaw interface{} `hcl:"raw_storage_endpoint"`
}

// DevConfig is a Config that is used for dev mode of Vault.
func DevConfig(ha, transactional bool) *Config {
ret := &Config{
DisableCache: false,
DisableMlock: true,
DisableCache: false,
DisableMlock: true,
EnableRawEndpoint: true,

Storage: &Storage{
Type: "inmem",
Expand Down Expand Up @@ -288,6 +292,11 @@ func (c *Config) Merge(c2 *Config) *Config {
result.EnableUI = c2.EnableUI
}

result.EnableRawEndpoint = c.EnableRawEndpoint
if c2.EnableRawEndpoint {
result.EnableRawEndpoint = c2.EnableRawEndpoint
}

result.PluginDirectory = c.PluginDirectory
if c2.PluginDirectory != "" {
result.PluginDirectory = c2.PluginDirectory
Expand All @@ -306,9 +315,8 @@ func LoadConfig(path string, logger log.Logger) (*Config, error) {

if fi.IsDir() {
return LoadConfigDir(path, logger)
} else {
return LoadConfigFile(path, logger)
}
return LoadConfigFile(path, logger)
}

// LoadConfigFile loads the configuration from the given file.
Expand Down Expand Up @@ -363,6 +371,12 @@ func ParseConfig(d string, logger log.Logger) (*Config, error) {
}
}

if result.EnableRawEndpointRaw != nil {
if result.EnableRawEndpoint, err = parseutil.ParseBool(result.EnableRawEndpointRaw); err != nil {
return nil, err
}
}

list, ok := obj.Node.(*ast.ObjectList)
if !ok {
return nil, fmt.Errorf("error parsing: file doesn't contain a root object")
Expand All @@ -385,6 +399,7 @@ func ParseConfig(d string, logger log.Logger) (*Config, error) {
"cluster_name",
"cluster_cipher_suites",
"plugin_directory",
"raw_storage_endpoint",
}
if err := checkHCLKeys(list, valid); err != nil {
return nil, err
Expand Down
10 changes: 10 additions & 0 deletions command/server/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ func TestLoadConfigFile(t *testing.T) {
EnableUI: true,
EnableUIRaw: true,

EnableRawEndpoint: true,
EnableRawEndpointRaw: true,

MaxLeaseTTL: 10 * time.Hour,
MaxLeaseTTLRaw: "10h",
DefaultLeaseTTL: 10 * time.Hour,
Expand Down Expand Up @@ -129,6 +132,9 @@ func TestLoadConfigFile_json(t *testing.T) {
DisableMlockRaw: interface{}(nil),
EnableUI: true,
EnableUIRaw: true,

EnableRawEndpoint: true,
EnableRawEndpointRaw: true,
}
if !reflect.DeepEqual(config, expected) {
t.Fatalf("expected \n\n%#v\n\n to be \n\n%#v\n\n", config, expected)
Expand Down Expand Up @@ -178,6 +184,8 @@ func TestLoadConfigFile_json2(t *testing.T) {

EnableUI: true,

EnableRawEndpoint: true,

Telemetry: &Telemetry{
StatsiteAddr: "foo",
StatsdAddr: "bar",
Expand Down Expand Up @@ -232,6 +240,8 @@ func TestLoadConfigDir(t *testing.T) {

EnableUI: true,

EnableRawEndpoint: true,

Telemetry: &Telemetry{
StatsiteAddr: "qux",
StatsdAddr: "baz",
Expand Down
1 change: 1 addition & 0 deletions command/server/test-fixtures/config-dir/baz.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ telemetry {
disable_hostname = true
}
ui=true
raw_storage_endpoint=true
default_lease_ttl = "10h"
cluster_name = "testcluster"
1 change: 1 addition & 0 deletions command/server/test-fixtures/config.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ telemetry {
max_lease_ttl = "10h"
default_lease_ttl = "10h"
cluster_name = "testcluster"
raw_storage_endpoint = true
3 changes: 2 additions & 1 deletion command/server/test-fixtures/config.hcl.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
"max_lease_ttl": "10h",
"default_lease_ttl": "10h",
"cluster_name":"testcluster",
"ui":true
"ui":true,
"raw_storage_endpoint":true
}
1 change: 1 addition & 0 deletions command/server/test-fixtures/config2.hcl.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"ui":true,
"raw_storage_endpoint":true,
"listener":[
{
"tcp":{
Expand Down
7 changes: 7 additions & 0 deletions vault/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,9 @@ type Core struct {
// uiEnabled indicates whether Vault Web UI is enabled or not
uiEnabled bool

// rawEnabled indicates whether the Raw endpoint is enabled
rawEnabled bool

// pluginDirectory is the location vault will look for plugin binaries
pluginDirectory string

Expand Down Expand Up @@ -402,6 +405,9 @@ type CoreConfig struct {

EnableUI bool `json:"ui" structs:"ui" mapstructure:"ui"`

// Enable the raw endpoint
EnableRaw bool `json:"enable_raw" structs:"enable_raw" mapstructure:"enable_raw"`

PluginDirectory string `json:"plugin_directory" structs:"plugin_directory" mapstructure:"plugin_directory"`

ReloadFuncs *map[string][]reload.ReloadFunc
Expand Down Expand Up @@ -462,6 +468,7 @@ func NewCore(conf *CoreConfig) (*Core, error) {
clusterListenerShutdownSuccessCh: make(chan struct{}),
clusterPeerClusterAddrsCache: cache.New(3*heartbeatInterval, time.Second),
enableMlock: !conf.DisableMlock,
rawEnabled: conf.EnableRaw,
}

if conf.ClusterCipherSuites != "" {
Expand Down
67 changes: 47 additions & 20 deletions vault/logical_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var (
// protectedPaths cannot be accessed via the raw APIs.
// This is both for security and to prevent disrupting Vault.
protectedPaths = []string{
"core",
keyringPath,
}

replicationPaths = func(b *SystemBackend) []*framework.Path {
Expand Down Expand Up @@ -59,6 +59,7 @@ func NewSystemBackend(core *Core) *SystemBackend {
"remount",
"audit",
"audit/*",
"raw",
"raw/*",
"replication/primary/secondary-token",
"replication/reindex",
Expand Down Expand Up @@ -652,25 +653,6 @@ func NewSystemBackend(core *Core) *SystemBackend {
HelpDescription: strings.TrimSpace(sysHelp["audit"][1]),
},

&framework.Path{
Pattern: "raw/(?P<path>.+)",

Fields: map[string]*framework.FieldSchema{
"path": &framework.FieldSchema{
Type: framework.TypeString,
},
"value": &framework.FieldSchema{
Type: framework.TypeString,
},
},

Callbacks: map[logical.Operation]framework.OperationFunc{
logical.ReadOperation: b.handleRawRead,
logical.UpdateOperation: b.handleRawWrite,
logical.DeleteOperation: b.handleRawDelete,
},
},

&framework.Path{
Pattern: "key-status$",

Expand Down Expand Up @@ -871,6 +853,28 @@ func NewSystemBackend(core *Core) *SystemBackend {

b.Backend.Paths = append(b.Backend.Paths, replicationPaths(b)...)

if core.rawEnabled {
b.Backend.Paths = append(b.Backend.Paths, &framework.Path{
Pattern: "(raw/?$|raw/(?P<path>.+))",

Fields: map[string]*framework.FieldSchema{
"path": &framework.FieldSchema{
Type: framework.TypeString,
},
"value": &framework.FieldSchema{
Type: framework.TypeString,
},
},

Callbacks: map[logical.Operation]framework.OperationFunc{
logical.ReadOperation: b.handleRawRead,
logical.UpdateOperation: b.handleRawWrite,
logical.DeleteOperation: b.handleRawDelete,
logical.ListOperation: b.handleRawList,
},
})
}

b.Backend.Invalidate = b.invalidate

return b
Expand Down Expand Up @@ -2143,6 +2147,29 @@ func (b *SystemBackend) handleRawDelete(
return nil, nil
}

// handleRawList is used to list directly from the barrier
func (b *SystemBackend) handleRawList(
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
path := data.Get("path").(string)
if path != "" && !strings.HasSuffix(path, "/") {
path = path + "/"
}

// Prevent access of protected paths
for _, p := range protectedPaths {
if strings.HasPrefix(path, p) {
err := fmt.Sprintf("cannot list '%s'", path)
return logical.ErrorResponse(err), logical.ErrInvalidRequest
}
}

keys, err := b.Core.barrier.List(path)
if err != nil {
return handleError(err)
}
return logical.ListResponse(keys), nil
}

// handleKeyStatus returns status information about the backend key
func (b *SystemBackend) handleKeyStatus(
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
Expand Down
42 changes: 22 additions & 20 deletions vault/logical_system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func TestSystemBackend_RootPaths(t *testing.T) {
"remount",
"audit",
"audit/*",
"raw",
"raw/*",
"replication/primary/secondary-token",
"replication/reindex",
Expand Down Expand Up @@ -1447,7 +1448,7 @@ func TestSystemBackend_disableAudit(t *testing.T) {
}

func TestSystemBackend_rawRead_Protected(t *testing.T) {
b := testSystemBackend(t)
b := testSystemBackendRaw(t)

req := logical.TestRequest(t, logical.ReadOperation, "raw/"+keyringPath)
_, err := b.HandleRequest(req)
Expand All @@ -1457,7 +1458,7 @@ func TestSystemBackend_rawRead_Protected(t *testing.T) {
}

func TestSystemBackend_rawWrite_Protected(t *testing.T) {
b := testSystemBackend(t)
b := testSystemBackendRaw(t)

req := logical.TestRequest(t, logical.UpdateOperation, "raw/"+keyringPath)
_, err := b.HandleRequest(req)
Expand All @@ -1467,7 +1468,7 @@ func TestSystemBackend_rawWrite_Protected(t *testing.T) {
}

func TestSystemBackend_rawReadWrite(t *testing.T) {
c, b, _ := testCoreSystemBackend(t)
c, b, _ := testCoreSystemBackendRaw(t)

req := logical.TestRequest(t, logical.UpdateOperation, "raw/sys/policy/test")
req.Data["value"] = `path "secret/" { policy = "read" }`
Expand Down Expand Up @@ -1503,7 +1504,7 @@ func TestSystemBackend_rawReadWrite(t *testing.T) {
}

func TestSystemBackend_rawDelete_Protected(t *testing.T) {
b := testSystemBackend(t)
b := testSystemBackendRaw(t)

req := logical.TestRequest(t, logical.DeleteOperation, "raw/"+keyringPath)
_, err := b.HandleRequest(req)
Expand All @@ -1513,7 +1514,7 @@ func TestSystemBackend_rawDelete_Protected(t *testing.T) {
}

func TestSystemBackend_rawDelete(t *testing.T) {
c, b, _ := testCoreSystemBackend(t)
c, b, _ := testCoreSystemBackendRaw(t)

// set the policy!
p := &Policy{Name: "test"}
Expand Down Expand Up @@ -1589,25 +1590,25 @@ func TestSystemBackend_rotate(t *testing.T) {

func testSystemBackend(t *testing.T) logical.Backend {
c, _, _ := TestCoreUnsealed(t)
bc := &logical.BackendConfig{
Logger: c.logger,
System: logical.StaticSystemView{
DefaultLeaseTTLVal: time.Hour * 24,
MaxLeaseTTLVal: time.Hour * 24 * 32,
},
}

b := NewSystemBackend(c)
err := b.Backend.Setup(bc)
if err != nil {
t.Fatal(err)
}
return testSystemBackendInternal(t, c)
}

return b
func testSystemBackendRaw(t *testing.T) logical.Backend {
c, _, _ := TestCoreUnsealedRaw(t)
return testSystemBackendInternal(t, c)
}

func testCoreSystemBackend(t *testing.T) (*Core, logical.Backend, string) {
c, _, root := TestCoreUnsealed(t)
return c, testSystemBackendInternal(t, c), root
}

func testCoreSystemBackendRaw(t *testing.T) (*Core, logical.Backend, string) {
c, _, root := TestCoreUnsealedRaw(t)
return c, testSystemBackendInternal(t, c), root
}

func testSystemBackendInternal(t *testing.T, c *Core) logical.Backend {
bc := &logical.BackendConfig{
Logger: c.logger,
System: logical.StaticSystemView{
Expand All @@ -1621,7 +1622,8 @@ func testCoreSystemBackend(t *testing.T) (*Core, logical.Backend, string) {
if err != nil {
t.Fatal(err)
}
return c, b, root

return b
}

func TestSystemBackend_PluginCatalog_CRUD(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion vault/seal_testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func (d *TestSeal) SetRecoveryKey(key []byte) error {

func testCoreUnsealedWithConfigs(t *testing.T, barrierConf, recoveryConf *SealConfig) (*Core, [][]byte, [][]byte, string) {
seal := &TestSeal{}
core := TestCoreWithSeal(t, seal)
core := TestCoreWithSeal(t, seal, false)
result, err := core.Initialize(&InitParams{
BarrierConfig: barrierConf,
RecoveryConfig: recoveryConf,
Expand Down
Loading

0 comments on commit 4a8c33c

Please sign in to comment.