Merge pull request #1207 from hashicorp/audit-hash-accessor

Audit backends optionally hashing token accessor
This commit is contained in:
Vishal Nayak 2016-03-14 11:31:28 -04:00
commit a74c7cf444
6 changed files with 221 additions and 56 deletions

View file

@ -29,8 +29,10 @@ func Hash(salter *salt.Salt, raw interface{}) error {
return nil return nil
} }
if s.ClientToken != "" { if s.ClientToken != "" {
token := fn(s.ClientToken) s.ClientToken = fn(s.ClientToken)
s.ClientToken = token }
if s.Accessor != "" {
s.Accessor = fn(s.Accessor)
} }
case *logical.Request: case *logical.Request:
@ -44,8 +46,7 @@ func Hash(salter *salt.Salt, raw interface{}) error {
} }
if s.ClientToken != "" { if s.ClientToken != "" {
token := fn(s.ClientToken) s.ClientToken = fn(s.ClientToken)
s.ClientToken = token
} }
data, err := HashStructure(s.Data, fn) data, err := HashStructure(s.Data, fn)

View file

@ -15,7 +15,7 @@ import (
func Factory(conf *audit.BackendConfig) (audit.Backend, error) { func Factory(conf *audit.BackendConfig) (audit.Backend, error) {
if conf.Salt == nil { if conf.Salt == nil {
return nil, fmt.Errorf("Nil salt passed in") return nil, fmt.Errorf("nil salt")
} }
path, ok := conf.Config["path"] path, ok := conf.Config["path"]
@ -23,6 +23,16 @@ func Factory(conf *audit.BackendConfig) (audit.Backend, error) {
return nil, fmt.Errorf("path is required") return nil, fmt.Errorf("path is required")
} }
// Check if hashing of accessor is disabled
hashAccessor := true
if hashAccessorRaw, ok := conf.Config["hash_accessor"]; ok {
value, err := strconv.ParseBool(hashAccessorRaw)
if err != nil {
return nil, err
}
hashAccessor = value
}
// Check if raw logging is enabled // Check if raw logging is enabled
logRaw := false logRaw := false
if raw, ok := conf.Config["log_raw"]; ok { if raw, ok := conf.Config["log_raw"]; ok {
@ -34,9 +44,10 @@ func Factory(conf *audit.BackendConfig) (audit.Backend, error) {
} }
b := &Backend{ b := &Backend{
path: path, path: path,
logRaw: logRaw, logRaw: logRaw,
salt: conf.Salt, hashAccessor: hashAccessor,
salt: conf.Salt,
} }
// Ensure that the file can be successfully opened for writing; // Ensure that the file can be successfully opened for writing;
@ -55,9 +66,10 @@ func Factory(conf *audit.BackendConfig) (audit.Backend, error) {
// It doesn't do anything more at the moment to assist with rotation // It doesn't do anything more at the moment to assist with rotation
// or reset the write cursor, this should be done in the future. // or reset the write cursor, this should be done in the future.
type Backend struct { type Backend struct {
path string path string
logRaw bool logRaw bool
salt *salt.Salt hashAccessor bool
salt *salt.Salt
once sync.Once once sync.Once
f *os.File f *os.File
@ -103,6 +115,7 @@ func (b *Backend) LogRequest(auth *logical.Auth, req *logical.Request, outerErr
if err := audit.Hash(b.salt, req); err != nil { if err := audit.Hash(b.salt, req); err != nil {
return err return err
} }
} }
var format audit.FormatJSON var format audit.FormatJSON
@ -149,15 +162,34 @@ func (b *Backend) LogResponse(
resp = cp.(*logical.Response) resp = cp.(*logical.Response)
// Hash any sensitive information // Hash any sensitive information
// Cache and restore accessor in the auth
var accessor string
if !b.hashAccessor && auth != nil && auth.Accessor != "" {
accessor = auth.Accessor
}
if err := audit.Hash(b.salt, auth); err != nil { if err := audit.Hash(b.salt, auth); err != nil {
return err return err
} }
if accessor != "" {
auth.Accessor = accessor
}
if err := audit.Hash(b.salt, req); err != nil { if err := audit.Hash(b.salt, req); err != nil {
return err return err
} }
// Cache and restore accessor in the response
accessor = ""
if !b.hashAccessor && resp != nil && resp.Auth != nil && resp.Auth.Accessor != "" {
accessor = resp.Auth.Accessor
}
if err := audit.Hash(b.salt, resp); err != nil { if err := audit.Hash(b.salt, resp); err != nil {
return err return err
} }
if accessor != "" {
resp.Auth.Accessor = accessor
}
} }
var format audit.FormatJSON var format audit.FormatJSON

View file

@ -29,6 +29,16 @@ func Factory(conf *audit.BackendConfig) (audit.Backend, error) {
tag = "vault" tag = "vault"
} }
// Check if hashing of accessor is disabled
hashAccessor := true
if hashAccessorRaw, ok := conf.Config["hash_accessor"]; ok {
value, err := strconv.ParseBool(hashAccessorRaw)
if err != nil {
return nil, err
}
hashAccessor = value
}
// Check if raw logging is enabled // Check if raw logging is enabled
logRaw := false logRaw := false
if raw, ok := conf.Config["log_raw"]; ok { if raw, ok := conf.Config["log_raw"]; ok {
@ -46,18 +56,20 @@ func Factory(conf *audit.BackendConfig) (audit.Backend, error) {
} }
b := &Backend{ b := &Backend{
logger: logger, logger: logger,
logRaw: logRaw, logRaw: logRaw,
salt: conf.Salt, hashAccessor: hashAccessor,
salt: conf.Salt,
} }
return b, nil return b, nil
} }
// Backend is the audit backend for the syslog-based audit store. // Backend is the audit backend for the syslog-based audit store.
type Backend struct { type Backend struct {
logger gsyslog.Syslogger logger gsyslog.Syslogger
logRaw bool logRaw bool
salt *salt.Salt hashAccessor bool
salt *salt.Salt
} }
func (b *Backend) GetHash(data string) string { func (b *Backend) GetHash(data string) string {
@ -145,15 +157,34 @@ func (b *Backend) LogResponse(auth *logical.Auth, req *logical.Request,
resp = cp.(*logical.Response) resp = cp.(*logical.Response)
// Hash any sensitive information // Hash any sensitive information
// Cache and restore accessor in the auth
var accessor string
if !b.hashAccessor && auth != nil && auth.Accessor != "" {
accessor = auth.Accessor
}
if err := audit.Hash(b.salt, auth); err != nil { if err := audit.Hash(b.salt, auth); err != nil {
return err return err
} }
if accessor != "" {
auth.Accessor = accessor
}
if err := audit.Hash(b.salt, req); err != nil { if err := audit.Hash(b.salt, req); err != nil {
return err return err
} }
// Cache and restore accessor in the response
accessor = ""
if !b.hashAccessor && resp != nil && resp.Auth != nil && resp.Auth.Accessor != "" {
accessor = resp.Auth.Accessor
}
if err := audit.Hash(b.salt, resp); err != nil { if err := audit.Hash(b.salt, resp); err != nil {
return err return err
} }
if accessor != "" {
resp.Auth.Accessor = accessor
}
} }
// Encode the entry as JSON // Encode the entry as JSON

View file

@ -8,29 +8,59 @@ description: |-
# Audit Backend: File # Audit Backend: File
Name: `file` The `file` audit backend writes audit logs to a file. This is a very simple audit
backend: it appends logs to a file. It does not currently assist with any log rotation.
The "file" audit backend writes audit logs to a file.
This is a very simple audit backend: it appends logs to a file. It does
not currently assist with any log rotation.
## Options
When enabling this backend, the following options are accepted:
* `path` (required) - The path to where the file will be written. If
this path exists, the audit backend will append to it.
* `log_raw` (optional) Should security sensitive information be logged raw. Defaults to "false".
## Format ## Format
Each line in the audit log is a JSON object. The "type" field specifies Each line in the audit log is a JSON object. The `type` field specifies what type of
what type of object it is. Currently, only two types exist: "request" and object it is. Currently, only two types exist: `request` and `response`. The line contains
"response". all of the information for any given request and response. By default, all the sensitive
information is first hashed before logging in the audit logs.
The line contains all of the information for any given request and response. ## Enabling
If `log_raw` if false, as is default, all sensitive information is first hashed #### Via the CLI
before logging. If explicitly enabled, all values are logged raw without hashing.
Audit `file` backend can be enabled by the following command.
```
$ vault audit-enable file path=/var/log/vault_audit.log
```
Any number of `file` audit logs can be created by enabling it with different `id`s.
```
$ vault audit-enable -id="vault_audit_1" file path=/home/user/vault_audit.log
```
Note the difference between `audit-enable` command options and the `file` backend
configuration options. Use `vault audit-enable -help` to see the command options.
Following are the configuration options available for the backend.
<dl class="api">
<dt>Backend configuration options</dt>
<dd>
<ul>
<li>
<span class="param">path</span>
<span class="param-flags">required</span>
The path to where the audit log will be written. If this
path exists, the audit backend will append to it.
</li>
<li>
<span class="param">log_raw</span>
<span class="param-flags">optional</span>
A boolean, if set, logs the security sensitive information without
hashing, in the raw format. Defaults to `false`.
</li>
<li>
<span class="param">hash_accessor</span>
<span class="param-flags">optional</span>
A boolean, if set, skips the hashing of token accessor. This option
is useful only when `log_raw` is `false`.
</li>
</ul>
</dd>
</dl>

View file

@ -67,3 +67,41 @@ Vault will not respond to requests if audit backends are blocked because
audit logs are critically important and ignoring blocked requests opens audit logs are critically important and ignoring blocked requests opens
an avenue for attack. Be absolutely certain that your audit backends cannot an avenue for attack. Be absolutely certain that your audit backends cannot
block. block.
## API
### /sys/audit/[path]
#### POST
<dl class="api">
<dt>Description</dt>
<dd>
Enables audit backend at the specified path.
</dd>
<dt>Method</dt>
<dd>POST</dd>
<dd>
<ul>
<li>
<span class="param">type</span>
<span class="param-flags">required</span>
The path to where the audit log will be written. If this
path exists, the audit backend will append to it.
</li>
<li>
<span class="param">description</span>
<span class="param-flags">optional</span>
A boolean, if set, logs the security sensitive information without
hashing, in the raw format. Defaults to `false`.
</li>
<li>
<span class="param">options</span>
<span class="param-flags">optional</span>
Configuration options of the backend in JSON format.
Refer to `syslog` and `file` audit backend options.
</li>
</ul>
</dd>
</dl>

View file

@ -8,30 +8,63 @@ description: |-
# Audit Backend: Syslog # Audit Backend: Syslog
Name: `syslog` The `syslog` audit backend writes audit logs to syslog.
The "syslog" audit backend writes audit logs to syslog. It currently does not support a configurable syslog destination, and always
sends to the local agent. This backend is only supported on Unix systems,
It currently does not support a configurable syslog destination, and
always sends to the local agent. This backend is only supported on Unix systems,
and should not be enabled if any standby Vault instances do not support it. and should not be enabled if any standby Vault instances do not support it.
## Options
When enabling this backend, the following options are accepted:
* `facility` (optional) - The syslog facility to use. Defaults to "AUTH".
* `tag` (optional) - The syslog tag to use. Defaults to "vault".
* `log_raw` (optional) Should security sensitive information be logged raw. Defaults to "false".
## Format ## Format
Each line in the audit log is a JSON object. The "type" field specifies Each line in the audit log is a JSON object. The `type` field specifies what type of
what type of object it is. Currently, only two types exist: "request" and object it is. Currently, only two types exist: `request` and `response`. The line contains
"response". all of the information for any given request and response. By default, all the sensitive
information is first hashed before logging in the audit logs.
The line contains all of the information for any given request and response. ## Enabling
If `log_raw` if false, as is default, all sensitive information is first hashed #### Via the CLI
before logging. If explicitly enabled, all values are logged raw without hashing.
Audit `syslog` backend can be enabled by the following command.
```
$ vault audit-enable syslog
```
Backend configuration options can also be provided from command-line.
```
$ vault audit-enable syslog tag="vault" facility="AUTH"
```
Following are the configuration options available for the backend.
<dl class="api">
<dt>Backend configuration options</dt>
<dd>
<ul>
<li>
<span class="param">facility</span>
<span class="param-flags">optional</span>
The syslog facility to use. Defaults to `AUTH`.
</li>
<li>
<span class="param">tag</span>
<span class="param-flags">optional</span>
The syslog tag to use. Defaults to `vault`.
</li>
<li>
<span class="param">log_raw</span>
<span class="param-flags">optional</span>
A boolean, if set, logs the security sensitive information without
hashing, in the raw format. Defaults to `false`.
</li>
<li>
<span class="param">hash_accessor</span>
<span class="param-flags">optional</span>
A boolean, if set, skips the hashing of token accessor. This option
is useful only when `log_raw` is `false`.
</li>
</ul>
</dd>
</dl>