mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 03:27:54 +00:00
Merge pull request #36 from hashicorp/f-syslog
Adding syslog audit provider
This commit is contained in:
@@ -22,6 +22,9 @@ func Hash(raw interface{}) error {
|
||||
|
||||
switch s := raw.(type) {
|
||||
case *logical.Auth:
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
if s.ClientToken != "" {
|
||||
token, err := fn(s.ClientToken)
|
||||
if err != nil {
|
||||
@@ -31,6 +34,9 @@ func Hash(raw interface{}) error {
|
||||
s.ClientToken = token
|
||||
}
|
||||
case *logical.Request:
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
if s.Auth != nil {
|
||||
if err := Hash(s.Auth); err != nil {
|
||||
return err
|
||||
@@ -44,6 +50,9 @@ func Hash(raw interface{}) error {
|
||||
|
||||
s.Data = data.(map[string]interface{})
|
||||
case *logical.Response:
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
if s.Auth != nil {
|
||||
if err := Hash(s.Auth); err != nil {
|
||||
return err
|
||||
|
||||
@@ -4,10 +4,12 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/vault/audit"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/mitchellh/copystructure"
|
||||
)
|
||||
|
||||
func Factory(conf map[string]string) (audit.Backend, error) {
|
||||
@@ -16,7 +18,21 @@ func Factory(conf map[string]string) (audit.Backend, error) {
|
||||
return nil, fmt.Errorf("path is required")
|
||||
}
|
||||
|
||||
return &Backend{Path: path}, nil
|
||||
// Check if raw logging is enabled
|
||||
logRaw := false
|
||||
if raw, ok := conf["log_raw"]; ok {
|
||||
b, err := strconv.ParseBool(raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logRaw = b
|
||||
}
|
||||
|
||||
b := &Backend{
|
||||
Path: path,
|
||||
LogRaw: logRaw,
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Backend is the audit backend for the file-based audit store.
|
||||
@@ -25,7 +41,8 @@ func Factory(conf map[string]string) (audit.Backend, error) {
|
||||
// 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.
|
||||
type Backend struct {
|
||||
Path string
|
||||
Path string
|
||||
LogRaw bool
|
||||
|
||||
once sync.Once
|
||||
f *os.File
|
||||
@@ -35,6 +52,28 @@ func (b *Backend) LogRequest(auth *logical.Auth, req *logical.Request) error {
|
||||
if err := b.open(); err != nil {
|
||||
return err
|
||||
}
|
||||
if !b.LogRaw {
|
||||
// Copy the structures
|
||||
cp, err := copystructure.Copy(auth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
auth = cp.(*logical.Auth)
|
||||
|
||||
cp, err = copystructure.Copy(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req = cp.(*logical.Request)
|
||||
|
||||
// Hash any sensitive information
|
||||
if err := audit.Hash(auth); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := audit.Hash(req); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var format audit.FormatJSON
|
||||
return format.FormatRequest(b.f, auth, req)
|
||||
@@ -48,6 +87,37 @@ func (b *Backend) LogResponse(
|
||||
if err := b.open(); err != nil {
|
||||
return err
|
||||
}
|
||||
if !b.LogRaw {
|
||||
// Copy the structure
|
||||
cp, err := copystructure.Copy(auth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
auth = cp.(*logical.Auth)
|
||||
|
||||
cp, err = copystructure.Copy(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req = cp.(*logical.Request)
|
||||
|
||||
cp, err = copystructure.Copy(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp = cp.(*logical.Response)
|
||||
|
||||
// Hash any sensitive information
|
||||
if err := audit.Hash(auth); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := audit.Hash(req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := audit.Hash(resp); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var format audit.FormatJSON
|
||||
return format.FormatResponse(b.f, auth, req, resp, err)
|
||||
|
||||
135
builtin/audit/syslog/backend.go
Normal file
135
builtin/audit/syslog/backend.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strconv"
|
||||
|
||||
"github.com/hashicorp/go-syslog"
|
||||
"github.com/hashicorp/vault/audit"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/mitchellh/copystructure"
|
||||
)
|
||||
|
||||
func Factory(conf map[string]string) (audit.Backend, error) {
|
||||
// Get facility or default to AUTH
|
||||
facility, ok := conf["facility"]
|
||||
if !ok {
|
||||
facility = "AUTH"
|
||||
}
|
||||
|
||||
// Get tag or default to 'vault'
|
||||
tag, ok := conf["tag"]
|
||||
if !ok {
|
||||
tag = "vault"
|
||||
}
|
||||
|
||||
// Check if raw logging is enabled
|
||||
logRaw := false
|
||||
if raw, ok := conf["log_raw"]; ok {
|
||||
b, err := strconv.ParseBool(raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logRaw = b
|
||||
}
|
||||
|
||||
// Get the logger
|
||||
logger, err := gsyslog.NewLogger(gsyslog.LOG_INFO, facility, tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b := &Backend{
|
||||
logger: logger,
|
||||
logRaw: logRaw,
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Backend is the audit backend for the syslog-based audit store.
|
||||
type Backend struct {
|
||||
logger gsyslog.Syslogger
|
||||
logRaw bool
|
||||
}
|
||||
|
||||
func (b *Backend) LogRequest(auth *logical.Auth, req *logical.Request) error {
|
||||
if !b.logRaw {
|
||||
// Copy the structures
|
||||
cp, err := copystructure.Copy(auth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
auth = cp.(*logical.Auth)
|
||||
|
||||
cp, err = copystructure.Copy(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req = cp.(*logical.Request)
|
||||
|
||||
// Hash any sensitive information
|
||||
if err := audit.Hash(auth); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := audit.Hash(req); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Encode the entry as JSON
|
||||
var buf bytes.Buffer
|
||||
var format audit.FormatJSON
|
||||
if err := format.FormatRequest(&buf, auth, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write out to syslog
|
||||
_, err := b.logger.Write(buf.Bytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func (b *Backend) LogResponse(auth *logical.Auth, req *logical.Request,
|
||||
resp *logical.Response, err error) error {
|
||||
if !b.logRaw {
|
||||
// Copy the structure
|
||||
cp, err := copystructure.Copy(auth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
auth = cp.(*logical.Auth)
|
||||
|
||||
cp, err = copystructure.Copy(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req = cp.(*logical.Request)
|
||||
|
||||
cp, err = copystructure.Copy(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp = cp.(*logical.Response)
|
||||
|
||||
// Hash any sensitive information
|
||||
if err := audit.Hash(auth); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := audit.Hash(req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := audit.Hash(resp); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Encode the entry as JSON
|
||||
var buf bytes.Buffer
|
||||
var format audit.FormatJSON
|
||||
if err := format.FormatResponse(&buf, auth, req, resp, err); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write otu to syslog
|
||||
_, err = b.logger.Write(buf.Bytes())
|
||||
return err
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"os"
|
||||
|
||||
auditFile "github.com/hashicorp/vault/builtin/audit/file"
|
||||
auditSyslog "github.com/hashicorp/vault/builtin/audit/syslog"
|
||||
|
||||
credAppId "github.com/hashicorp/vault/builtin/credential/app-id"
|
||||
credCert "github.com/hashicorp/vault/builtin/credential/cert"
|
||||
@@ -49,7 +50,8 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
|
||||
return &command.ServerCommand{
|
||||
Meta: meta,
|
||||
AuditBackends: map[string]audit.Factory{
|
||||
"file": auditFile.Factory,
|
||||
"file": auditFile.Factory,
|
||||
"syslog": auditSyslog.Factory,
|
||||
},
|
||||
CredentialBackends: map[string]logical.Factory{
|
||||
"cert": credCert.Factory,
|
||||
|
||||
@@ -21,6 +21,7 @@ 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
|
||||
|
||||
@@ -30,3 +31,6 @@ what type of object it is. Currently, only two types exist: "request" and
|
||||
|
||||
The line contains all of the information for any given request and response.
|
||||
|
||||
If `log_raw` if false, as is default, all sensitive information is first hashed
|
||||
before logging. If explicitly enabled, all values are logged raw without hashing.
|
||||
|
||||
|
||||
37
website/source/docs/audit/syslog.html.md
Normal file
37
website/source/docs/audit/syslog.html.md
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
layout: "docs"
|
||||
page_title: "Audit Backend: Syslog"
|
||||
sidebar_current: "docs-audit-syslog"
|
||||
description: |-
|
||||
The "syslog" audit backend writes audit logs to syslog.
|
||||
---
|
||||
|
||||
# Audit Backend: Syslog
|
||||
|
||||
Name: `syslog`
|
||||
|
||||
The "syslog" audit backend writes audit logs to syslog.
|
||||
|
||||
It currently does not support a configurable syslog desination, 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.
|
||||
|
||||
## 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
|
||||
|
||||
Each line in the audit log is a JSON object. The "type" field specifies
|
||||
what type of object it is. Currently, only two types exist: "request" and
|
||||
"response".
|
||||
|
||||
The line contains all of the information for any given request and response.
|
||||
|
||||
If `log_raw` if false, as is default, all sensitive information is first hashed
|
||||
before logging. If explicitly enabled, all values are logged raw without hashing.
|
||||
|
||||
@@ -154,6 +154,10 @@
|
||||
<ul class="nav">
|
||||
<li<%= sidebar_current("docs-audit-file") %>>
|
||||
<a href="/docs/audit/file.html">File</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-audit-syslog") %>>
|
||||
<a href="/docs/audit/syslog.html">Syslog</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
Reference in New Issue
Block a user