Merge pull request #1207 from hashicorp/audit-hash-accessor
Audit backends optionally hashing token accessor
This commit is contained in:
commit
a74c7cf444
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue