mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 10:12:35 +00:00
@@ -9,7 +9,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hashicorp/vault/sdk/helper/salt"
|
"github.com/hashicorp/vault/sdk/helper/salt"
|
||||||
"github.com/hashicorp/vault/sdk/logical"
|
"github.com/hashicorp/vault/sdk/logical"
|
||||||
@@ -20,91 +19,6 @@ var (
|
|||||||
_ Writer = (*EntryFormatterWriter)(nil)
|
_ Writer = (*EntryFormatterWriter)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Salter is an interface that provides a way to obtain a Salt for hashing.
|
|
||||||
type Salter interface {
|
|
||||||
// Salt returns a non-nil salt or an error.
|
|
||||||
Salt(context.Context) (*salt.Salt, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Formatter is an interface that is responsible for formatting a request/response into some format.
|
|
||||||
// It is recommended that you pass data through Hash prior to formatting it.
|
|
||||||
type Formatter interface {
|
|
||||||
// FormatRequest formats the logical.LogInput into an RequestEntry.
|
|
||||||
FormatRequest(context.Context, *logical.LogInput) (*RequestEntry, error)
|
|
||||||
// FormatResponse formats the logical.LogInput into an ResponseEntry.
|
|
||||||
FormatResponse(context.Context, *logical.LogInput) (*ResponseEntry, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writer is an interface that provides a way to write request and response audit entries.
|
|
||||||
// Formatters write their output to an io.Writer.
|
|
||||||
type Writer interface {
|
|
||||||
// WriteRequest writes the request entry to the writer or returns an error.
|
|
||||||
WriteRequest(io.Writer, *RequestEntry) error
|
|
||||||
// WriteResponse writes the response entry to the writer or returns an error.
|
|
||||||
WriteResponse(io.Writer, *ResponseEntry) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// EntryFormatter should be used to format audit entries.
|
|
||||||
type EntryFormatter struct {
|
|
||||||
salter Salter
|
|
||||||
config FormatterConfig
|
|
||||||
prefix string
|
|
||||||
}
|
|
||||||
|
|
||||||
// EntryFormatterWriter should be used to format and write out audit entries.
|
|
||||||
type EntryFormatterWriter struct {
|
|
||||||
Formatter
|
|
||||||
Writer
|
|
||||||
config FormatterConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormatterConfig is used to provide basic configuration to a formatter.
|
|
||||||
// Use NewFormatterConfig to initialize the FormatterConfig struct.
|
|
||||||
type FormatterConfig struct {
|
|
||||||
Raw bool
|
|
||||||
HMACAccessor bool
|
|
||||||
|
|
||||||
// Vault lacks pagination in its APIs. As a result, certain list operations can return **very** large responses.
|
|
||||||
// The user's chosen audit sinks may experience difficulty consuming audit records that swell to tens of megabytes
|
|
||||||
// of JSON. The responses of list operations are typically not very interesting, as they are mostly lists of keys,
|
|
||||||
// or, even when they include a "key_info" field, are not returning confidential information. They become even less
|
|
||||||
// interesting once HMAC-ed by the audit system.
|
|
||||||
//
|
|
||||||
// Some example Vault "list" operations that are prone to becoming very large in an active Vault installation are:
|
|
||||||
// auth/token/accessors/
|
|
||||||
// identity/entity/id/
|
|
||||||
// identity/entity-alias/id/
|
|
||||||
// pki/certs/
|
|
||||||
//
|
|
||||||
// This option exists to provide such users with the option to have response data elided from audit logs, only when
|
|
||||||
// the operation type is "list". For added safety, the elision only applies to the "keys" and "key_info" fields
|
|
||||||
// within the response data - these are conventionally the only fields present in a list response - see
|
|
||||||
// logical.ListResponse, and logical.ListResponseWithInfo. However, other fields are technically possible if a
|
|
||||||
// plugin author writes unusual code, and these will be preserved in the audit log even with this option enabled.
|
|
||||||
// The elision replaces the values of the "keys" and "key_info" fields with an integer count of the number of
|
|
||||||
// entries. This allows even the elided audit logs to still be useful for answering questions like
|
|
||||||
// "Was any data returned?" or "How many records were listed?".
|
|
||||||
ElideListResponses bool
|
|
||||||
|
|
||||||
// This should only ever be used in a testing context
|
|
||||||
OmitTime bool
|
|
||||||
|
|
||||||
// The required/target format for the audit entry (supported: JSONFormat and JSONxFormat).
|
|
||||||
RequiredFormat format
|
|
||||||
}
|
|
||||||
|
|
||||||
// nonPersistentSalt is used for obtaining a salt that is
|
|
||||||
type nonPersistentSalt struct{}
|
|
||||||
|
|
||||||
type auditEvent struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Version string `json:"version"`
|
|
||||||
Subtype subtype `json:"subtype"` // the subtype of the audit event.
|
|
||||||
Timestamp time.Time `json:"timestamp"`
|
|
||||||
Data *logical.LogInput `json:"data"`
|
|
||||||
RequiredFormat format `json:"format"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Salt returns a new salt with default configuration and no storage usage, and no error.
|
// Salt returns a new salt with default configuration and no storage usage, and no error.
|
||||||
func (s *nonPersistentSalt) Salt(_ context.Context) (*salt.Salt, error) {
|
func (s *nonPersistentSalt) Salt(_ context.Context) (*salt.Salt, error) {
|
||||||
return salt.NewNonpersistentSalt(), nil
|
return salt.NewNonpersistentSalt(), nil
|
||||||
@@ -175,119 +89,6 @@ func (f *EntryFormatterWriter) FormatAndWriteResponse(ctx context.Context, w io.
|
|||||||
return f.Writer.WriteResponse(w, respEntry)
|
return f.Writer.WriteResponse(w, respEntry)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestEntry is the structure of a request audit log entry in Audit.
|
|
||||||
type RequestEntry struct {
|
|
||||||
Time string `json:"time,omitempty"`
|
|
||||||
Type string `json:"type,omitempty"`
|
|
||||||
Auth *Auth `json:"auth,omitempty"`
|
|
||||||
Request *Request `json:"request,omitempty"`
|
|
||||||
Error string `json:"error,omitempty"`
|
|
||||||
ForwardedFrom string `json:"forwarded_from,omitempty"` // Populated in Enterprise when a request is forwarded
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResponseEntry is the structure of a response audit log entry in Audit.
|
|
||||||
type ResponseEntry struct {
|
|
||||||
Time string `json:"time,omitempty"`
|
|
||||||
Type string `json:"type,omitempty"`
|
|
||||||
Auth *Auth `json:"auth,omitempty"`
|
|
||||||
Request *Request `json:"request,omitempty"`
|
|
||||||
Response *Response `json:"response,omitempty"`
|
|
||||||
Error string `json:"error,omitempty"`
|
|
||||||
Forwarded bool `json:"forwarded,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Request struct {
|
|
||||||
ID string `json:"id,omitempty"`
|
|
||||||
ClientID string `json:"client_id,omitempty"`
|
|
||||||
ReplicationCluster string `json:"replication_cluster,omitempty"`
|
|
||||||
Operation logical.Operation `json:"operation,omitempty"`
|
|
||||||
MountPoint string `json:"mount_point,omitempty"`
|
|
||||||
MountType string `json:"mount_type,omitempty"`
|
|
||||||
MountAccessor string `json:"mount_accessor,omitempty"`
|
|
||||||
MountRunningVersion string `json:"mount_running_version,omitempty"`
|
|
||||||
MountRunningSha256 string `json:"mount_running_sha256,omitempty"`
|
|
||||||
MountClass string `json:"mount_class,omitempty"`
|
|
||||||
MountIsExternalPlugin bool `json:"mount_is_external_plugin,omitempty"`
|
|
||||||
ClientToken string `json:"client_token,omitempty"`
|
|
||||||
ClientTokenAccessor string `json:"client_token_accessor,omitempty"`
|
|
||||||
Namespace *Namespace `json:"namespace,omitempty"`
|
|
||||||
Path string `json:"path,omitempty"`
|
|
||||||
Data map[string]interface{} `json:"data,omitempty"`
|
|
||||||
PolicyOverride bool `json:"policy_override,omitempty"`
|
|
||||||
RemoteAddr string `json:"remote_address,omitempty"`
|
|
||||||
RemotePort int `json:"remote_port,omitempty"`
|
|
||||||
WrapTTL int `json:"wrap_ttl,omitempty"`
|
|
||||||
Headers map[string][]string `json:"headers,omitempty"`
|
|
||||||
ClientCertificateSerialNumber string `json:"client_certificate_serial_number,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Response struct {
|
|
||||||
Auth *Auth `json:"auth,omitempty"`
|
|
||||||
MountPoint string `json:"mount_point,omitempty"`
|
|
||||||
MountType string `json:"mount_type,omitempty"`
|
|
||||||
MountAccessor string `json:"mount_accessor,omitempty"`
|
|
||||||
MountRunningVersion string `json:"mount_running_plugin_version,omitempty"`
|
|
||||||
MountRunningSha256 string `json:"mount_running_sha256,omitempty"`
|
|
||||||
MountClass string `json:"mount_class,omitempty"`
|
|
||||||
MountIsExternalPlugin bool `json:"mount_is_external_plugin,omitempty"`
|
|
||||||
Secret *Secret `json:"secret,omitempty"`
|
|
||||||
Data map[string]interface{} `json:"data,omitempty"`
|
|
||||||
Warnings []string `json:"warnings,omitempty"`
|
|
||||||
Redirect string `json:"redirect,omitempty"`
|
|
||||||
WrapInfo *ResponseWrapInfo `json:"wrap_info,omitempty"`
|
|
||||||
Headers map[string][]string `json:"headers,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Auth struct {
|
|
||||||
ClientToken string `json:"client_token,omitempty"`
|
|
||||||
Accessor string `json:"accessor,omitempty"`
|
|
||||||
DisplayName string `json:"display_name,omitempty"`
|
|
||||||
Policies []string `json:"policies,omitempty"`
|
|
||||||
TokenPolicies []string `json:"token_policies,omitempty"`
|
|
||||||
IdentityPolicies []string `json:"identity_policies,omitempty"`
|
|
||||||
ExternalNamespacePolicies map[string][]string `json:"external_namespace_policies,omitempty"`
|
|
||||||
NoDefaultPolicy bool `json:"no_default_policy,omitempty"`
|
|
||||||
PolicyResults *PolicyResults `json:"policy_results,omitempty"`
|
|
||||||
Metadata map[string]string `json:"metadata,omitempty"`
|
|
||||||
NumUses int `json:"num_uses,omitempty"`
|
|
||||||
RemainingUses int `json:"remaining_uses,omitempty"`
|
|
||||||
EntityID string `json:"entity_id,omitempty"`
|
|
||||||
EntityCreated bool `json:"entity_created,omitempty"`
|
|
||||||
TokenType string `json:"token_type,omitempty"`
|
|
||||||
TokenTTL int64 `json:"token_ttl,omitempty"`
|
|
||||||
TokenIssueTime string `json:"token_issue_time,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PolicyResults struct {
|
|
||||||
Allowed bool `json:"allowed"`
|
|
||||||
GrantingPolicies []PolicyInfo `json:"granting_policies,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PolicyInfo struct {
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
NamespaceId string `json:"namespace_id,omitempty"`
|
|
||||||
NamespacePath string `json:"namespace_path,omitempty"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Secret struct {
|
|
||||||
LeaseID string `json:"lease_id,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResponseWrapInfo struct {
|
|
||||||
TTL int `json:"ttl,omitempty"`
|
|
||||||
Token string `json:"token,omitempty"`
|
|
||||||
Accessor string `json:"accessor,omitempty"`
|
|
||||||
CreationTime string `json:"creation_time,omitempty"`
|
|
||||||
CreationPath string `json:"creation_path,omitempty"`
|
|
||||||
WrappedAccessor string `json:"wrapped_accessor,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Namespace struct {
|
|
||||||
ID string `json:"id,omitempty"`
|
|
||||||
Path string `json:"path,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTemporaryFormatter creates a formatter not backed by a persistent salt
|
// NewTemporaryFormatter creates a formatter not backed by a persistent salt
|
||||||
func NewTemporaryFormatter(requiredFormat, prefix string) (*EntryFormatterWriter, error) {
|
func NewTemporaryFormatter(requiredFormat, prefix string) (*EntryFormatterWriter, error) {
|
||||||
cfg, err := NewFormatterConfig(WithFormat(requiredFormat))
|
cfg, err := NewFormatterConfig(WithFormat(requiredFormat))
|
||||||
|
|||||||
@@ -4,87 +4,11 @@
|
|||||||
package audit
|
package audit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/internal/observability/event"
|
"github.com/hashicorp/vault/internal/observability/event"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/sdk/helper/salt"
|
|
||||||
"github.com/hashicorp/vault/sdk/logical"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Audit subtypes.
|
|
||||||
const (
|
|
||||||
RequestType subtype = "AuditRequest"
|
|
||||||
ResponseType subtype = "AuditResponse"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Audit formats.
|
|
||||||
const (
|
|
||||||
JSONFormat format = "json"
|
|
||||||
JSONxFormat format = "jsonx"
|
|
||||||
)
|
|
||||||
|
|
||||||
// version defines the version of audit events.
|
|
||||||
const version = "v0.1"
|
|
||||||
|
|
||||||
// subtype defines the type of audit event.
|
|
||||||
type subtype string
|
|
||||||
|
|
||||||
// format defines types of format audit events support.
|
|
||||||
type format string
|
|
||||||
|
|
||||||
// Backend interface must be implemented for an audit
|
|
||||||
// mechanism to be made available. Audit backends can be enabled to
|
|
||||||
// sink information to different backends such as logs, file, databases,
|
|
||||||
// or other external services.
|
|
||||||
type Backend interface {
|
|
||||||
// LogRequest is used to synchronously log a request. This is done after the
|
|
||||||
// request is authorized but before the request is executed. The arguments
|
|
||||||
// MUST not be modified in anyway. They should be deep copied if this is
|
|
||||||
// a possibility.
|
|
||||||
LogRequest(context.Context, *logical.LogInput) error
|
|
||||||
|
|
||||||
// LogResponse is used to synchronously log a response. This is done after
|
|
||||||
// the request is processed but before the response is sent. The arguments
|
|
||||||
// MUST not be modified in anyway. They should be deep copied if this is
|
|
||||||
// a possibility.
|
|
||||||
LogResponse(context.Context, *logical.LogInput) error
|
|
||||||
|
|
||||||
// LogTestMessage is used to check an audit backend before adding it
|
|
||||||
// permanently. It should attempt to synchronously log the given test
|
|
||||||
// message, WITHOUT using the normal Salt (which would require a storage
|
|
||||||
// operation on creation, which is currently disallowed.)
|
|
||||||
LogTestMessage(context.Context, *logical.LogInput, map[string]string) error
|
|
||||||
|
|
||||||
// GetHash is used to return the given data with the backend's hash,
|
|
||||||
// so that a caller can determine if a value in the audit log matches
|
|
||||||
// an expected plaintext value
|
|
||||||
GetHash(context.Context, string) (string, error)
|
|
||||||
|
|
||||||
// Reload is called on SIGHUP for supporting backends.
|
|
||||||
Reload(context.Context) error
|
|
||||||
|
|
||||||
// Invalidate is called for path invalidation
|
|
||||||
Invalidate(context.Context)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BackendConfig contains configuration parameters used in the factory func to
|
|
||||||
// instantiate audit backends
|
|
||||||
type BackendConfig struct {
|
|
||||||
// The view to store the salt
|
|
||||||
SaltView logical.Storage
|
|
||||||
|
|
||||||
// The salt config that should be used for any secret obfuscation
|
|
||||||
SaltConfig *salt.Config
|
|
||||||
|
|
||||||
// Config is the opaque user configuration provided when mounting
|
|
||||||
Config map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Factory is the factory function to create an audit backend.
|
|
||||||
type Factory func(context.Context, *BackendConfig, bool) (Backend, error)
|
|
||||||
|
|
||||||
// newEvent should be used to create an audit event.
|
// newEvent should be used to create an audit event.
|
||||||
// subtype and format are needed for audit.
|
// subtype and format are needed for audit.
|
||||||
// It will generate an ID if no ID is supplied.
|
// It will generate an ID if no ID is supplied.
|
||||||
|
|||||||
@@ -9,22 +9,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Option is how options are passed as arguments.
|
|
||||||
type Option func(*options) error
|
|
||||||
|
|
||||||
// options are used to represent configuration for a audit related nodes.
|
|
||||||
type options struct {
|
|
||||||
withID string
|
|
||||||
withNow time.Time
|
|
||||||
withSubtype subtype
|
|
||||||
withFormat format
|
|
||||||
withPrefix string
|
|
||||||
withRaw bool
|
|
||||||
withElision bool
|
|
||||||
withOmitTime bool
|
|
||||||
withHMACAccessor bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// getDefaultOptions returns options with their default values.
|
// getDefaultOptions returns options with their default values.
|
||||||
func getDefaultOptions() options {
|
func getDefaultOptions() options {
|
||||||
return options{
|
return options{
|
||||||
|
|||||||
301
audit/types.go
Normal file
301
audit/types.go
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
// Copyright (c) HashiCorp, Inc.
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package audit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/sdk/helper/salt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/sdk/logical"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Audit subtypes.
|
||||||
|
const (
|
||||||
|
RequestType subtype = "AuditRequest"
|
||||||
|
ResponseType subtype = "AuditResponse"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Audit formats.
|
||||||
|
const (
|
||||||
|
JSONFormat format = "json"
|
||||||
|
JSONxFormat format = "jsonx"
|
||||||
|
)
|
||||||
|
|
||||||
|
// version defines the version of audit events.
|
||||||
|
const version = "v0.1"
|
||||||
|
|
||||||
|
// subtype defines the type of audit event.
|
||||||
|
type subtype string
|
||||||
|
|
||||||
|
// format defines types of format audit events support.
|
||||||
|
type format string
|
||||||
|
|
||||||
|
// auditEvent is the audit event.
|
||||||
|
type auditEvent struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Subtype subtype `json:"subtype"` // the subtype of the audit event.
|
||||||
|
Timestamp time.Time `json:"timestamp"`
|
||||||
|
Data *logical.LogInput `json:"data"`
|
||||||
|
RequiredFormat format `json:"format"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option is how options are passed as arguments.
|
||||||
|
type Option func(*options) error
|
||||||
|
|
||||||
|
// options are used to represent configuration for a audit related nodes.
|
||||||
|
type options struct {
|
||||||
|
withID string
|
||||||
|
withNow time.Time
|
||||||
|
withSubtype subtype
|
||||||
|
withFormat format
|
||||||
|
withPrefix string
|
||||||
|
withRaw bool
|
||||||
|
withElision bool
|
||||||
|
withOmitTime bool
|
||||||
|
withHMACAccessor bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Salter is an interface that provides a way to obtain a Salt for hashing.
|
||||||
|
type Salter interface {
|
||||||
|
// Salt returns a non-nil salt or an error.
|
||||||
|
Salt(context.Context) (*salt.Salt, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formatter is an interface that is responsible for formatting a request/response into some format.
|
||||||
|
// It is recommended that you pass data through Hash prior to formatting it.
|
||||||
|
type Formatter interface {
|
||||||
|
// FormatRequest formats the logical.LogInput into an RequestEntry.
|
||||||
|
FormatRequest(context.Context, *logical.LogInput) (*RequestEntry, error)
|
||||||
|
// FormatResponse formats the logical.LogInput into an ResponseEntry.
|
||||||
|
FormatResponse(context.Context, *logical.LogInput) (*ResponseEntry, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writer is an interface that provides a way to write request and response audit entries.
|
||||||
|
// Formatters write their output to an io.Writer.
|
||||||
|
type Writer interface {
|
||||||
|
// WriteRequest writes the request entry to the writer or returns an error.
|
||||||
|
WriteRequest(io.Writer, *RequestEntry) error // TODO: PW: Should we supply ctx in this interface
|
||||||
|
// WriteResponse writes the response entry to the writer or returns an error.
|
||||||
|
WriteResponse(io.Writer, *ResponseEntry) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// EntryFormatter should be used to format audit requests and responses.
|
||||||
|
type EntryFormatter struct {
|
||||||
|
salter Salter
|
||||||
|
config FormatterConfig
|
||||||
|
prefix string
|
||||||
|
}
|
||||||
|
|
||||||
|
// EntryFormatterWriter should be used to format and write out audit requests and responses.
|
||||||
|
type EntryFormatterWriter struct {
|
||||||
|
Formatter
|
||||||
|
Writer
|
||||||
|
config FormatterConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormatterConfig is used to provide basic configuration to a formatter.
|
||||||
|
// Use NewFormatterConfig to initialize the FormatterConfig struct.
|
||||||
|
type FormatterConfig struct {
|
||||||
|
Raw bool
|
||||||
|
HMACAccessor bool
|
||||||
|
|
||||||
|
// Vault lacks pagination in its APIs. As a result, certain list operations can return **very** large responses.
|
||||||
|
// The user's chosen audit sinks may experience difficulty consuming audit records that swell to tens of megabytes
|
||||||
|
// of JSON. The responses of list operations are typically not very interesting, as they are mostly lists of keys,
|
||||||
|
// or, even when they include a "key_info" field, are not returning confidential information. They become even less
|
||||||
|
// interesting once HMAC-ed by the audit system.
|
||||||
|
//
|
||||||
|
// Some example Vault "list" operations that are prone to becoming very large in an active Vault installation are:
|
||||||
|
// auth/token/accessors/
|
||||||
|
// identity/entity/id/
|
||||||
|
// identity/entity-alias/id/
|
||||||
|
// pki/certs/
|
||||||
|
//
|
||||||
|
// This option exists to provide such users with the option to have response data elided from audit logs, only when
|
||||||
|
// the operation type is "list". For added safety, the elision only applies to the "keys" and "key_info" fields
|
||||||
|
// within the response data - these are conventionally the only fields present in a list response - see
|
||||||
|
// logical.ListResponse, and logical.ListResponseWithInfo. However, other fields are technically possible if a
|
||||||
|
// plugin author writes unusual code, and these will be preserved in the audit log even with this option enabled.
|
||||||
|
// The elision replaces the values of the "keys" and "key_info" fields with an integer count of the number of
|
||||||
|
// entries. This allows even the elided audit logs to still be useful for answering questions like
|
||||||
|
// "Was any data returned?" or "How many records were listed?".
|
||||||
|
ElideListResponses bool
|
||||||
|
|
||||||
|
// This should only ever be used in a testing context
|
||||||
|
OmitTime bool
|
||||||
|
|
||||||
|
// The required/target format for the event (supported: JSONFormat and JSONxFormat).
|
||||||
|
RequiredFormat format
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestEntry is the structure of a request audit log entry.
|
||||||
|
type RequestEntry struct {
|
||||||
|
Time string `json:"time,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
Auth *Auth `json:"auth,omitempty"`
|
||||||
|
Request *Request `json:"request,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
ForwardedFrom string `json:"forwarded_from,omitempty"` // Populated in Enterprise when a request is forwarded
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResponseEntry is the structure of a response audit log entry.
|
||||||
|
type ResponseEntry struct {
|
||||||
|
Time string `json:"time,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
Auth *Auth `json:"auth,omitempty"`
|
||||||
|
Request *Request `json:"request,omitempty"`
|
||||||
|
Response *Response `json:"response,omitempty"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
Forwarded bool `json:"forwarded,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Request struct {
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
ClientID string `json:"client_id,omitempty"`
|
||||||
|
ReplicationCluster string `json:"replication_cluster,omitempty"`
|
||||||
|
Operation logical.Operation `json:"operation,omitempty"`
|
||||||
|
MountPoint string `json:"mount_point,omitempty"`
|
||||||
|
MountType string `json:"mount_type,omitempty"`
|
||||||
|
MountAccessor string `json:"mount_accessor,omitempty"`
|
||||||
|
MountRunningVersion string `json:"mount_running_version,omitempty"`
|
||||||
|
MountRunningSha256 string `json:"mount_running_sha256,omitempty"`
|
||||||
|
MountClass string `json:"mount_class,omitempty"`
|
||||||
|
MountIsExternalPlugin bool `json:"mount_is_external_plugin,omitempty"`
|
||||||
|
ClientToken string `json:"client_token,omitempty"`
|
||||||
|
ClientTokenAccessor string `json:"client_token_accessor,omitempty"`
|
||||||
|
Namespace *Namespace `json:"namespace,omitempty"`
|
||||||
|
Path string `json:"path,omitempty"`
|
||||||
|
Data map[string]interface{} `json:"data,omitempty"`
|
||||||
|
PolicyOverride bool `json:"policy_override,omitempty"`
|
||||||
|
RemoteAddr string `json:"remote_address,omitempty"`
|
||||||
|
RemotePort int `json:"remote_port,omitempty"`
|
||||||
|
WrapTTL int `json:"wrap_ttl,omitempty"`
|
||||||
|
Headers map[string][]string `json:"headers,omitempty"`
|
||||||
|
ClientCertificateSerialNumber string `json:"client_certificate_serial_number,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
Auth *Auth `json:"auth,omitempty"`
|
||||||
|
MountPoint string `json:"mount_point,omitempty"`
|
||||||
|
MountType string `json:"mount_type,omitempty"`
|
||||||
|
MountAccessor string `json:"mount_accessor,omitempty"`
|
||||||
|
MountRunningVersion string `json:"mount_running_plugin_version,omitempty"`
|
||||||
|
MountRunningSha256 string `json:"mount_running_sha256,omitempty"`
|
||||||
|
MountClass string `json:"mount_class,omitempty"`
|
||||||
|
MountIsExternalPlugin bool `json:"mount_is_external_plugin,omitempty"`
|
||||||
|
Secret *Secret `json:"secret,omitempty"`
|
||||||
|
Data map[string]interface{} `json:"data,omitempty"`
|
||||||
|
Warnings []string `json:"warnings,omitempty"`
|
||||||
|
Redirect string `json:"redirect,omitempty"`
|
||||||
|
WrapInfo *ResponseWrapInfo `json:"wrap_info,omitempty"`
|
||||||
|
Headers map[string][]string `json:"headers,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Auth struct {
|
||||||
|
ClientToken string `json:"client_token,omitempty"`
|
||||||
|
Accessor string `json:"accessor,omitempty"`
|
||||||
|
DisplayName string `json:"display_name,omitempty"`
|
||||||
|
Policies []string `json:"policies,omitempty"`
|
||||||
|
TokenPolicies []string `json:"token_policies,omitempty"`
|
||||||
|
IdentityPolicies []string `json:"identity_policies,omitempty"`
|
||||||
|
ExternalNamespacePolicies map[string][]string `json:"external_namespace_policies,omitempty"`
|
||||||
|
NoDefaultPolicy bool `json:"no_default_policy,omitempty"`
|
||||||
|
PolicyResults *PolicyResults `json:"policy_results,omitempty"`
|
||||||
|
Metadata map[string]string `json:"metadata,omitempty"`
|
||||||
|
NumUses int `json:"num_uses,omitempty"`
|
||||||
|
RemainingUses int `json:"remaining_uses,omitempty"`
|
||||||
|
EntityID string `json:"entity_id,omitempty"`
|
||||||
|
EntityCreated bool `json:"entity_created,omitempty"`
|
||||||
|
TokenType string `json:"token_type,omitempty"`
|
||||||
|
TokenTTL int64 `json:"token_ttl,omitempty"`
|
||||||
|
TokenIssueTime string `json:"token_issue_time,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PolicyResults struct {
|
||||||
|
Allowed bool `json:"allowed"`
|
||||||
|
GrantingPolicies []PolicyInfo `json:"granting_policies,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PolicyInfo struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
NamespaceId string `json:"namespace_id,omitempty"`
|
||||||
|
NamespacePath string `json:"namespace_path,omitempty"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Secret struct {
|
||||||
|
LeaseID string `json:"lease_id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResponseWrapInfo struct {
|
||||||
|
TTL int `json:"ttl,omitempty"`
|
||||||
|
Token string `json:"token,omitempty"`
|
||||||
|
Accessor string `json:"accessor,omitempty"`
|
||||||
|
CreationTime string `json:"creation_time,omitempty"`
|
||||||
|
CreationPath string `json:"creation_path,omitempty"`
|
||||||
|
WrappedAccessor string `json:"wrapped_accessor,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Namespace struct {
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
Path string `json:"path,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// nonPersistentSalt is used for obtaining a salt that is
|
||||||
|
type nonPersistentSalt struct{}
|
||||||
|
|
||||||
|
// Backend interface must be implemented for an audit
|
||||||
|
// mechanism to be made available. Audit backends can be enabled to
|
||||||
|
// sink information to different backends such as logs, file, databases,
|
||||||
|
// or other external services.
|
||||||
|
type Backend interface {
|
||||||
|
// LogRequest is used to synchronously log a request. This is done after the
|
||||||
|
// request is authorized but before the request is executed. The arguments
|
||||||
|
// MUST not be modified in any way. They should be deep copied if this is
|
||||||
|
// a possibility.
|
||||||
|
LogRequest(context.Context, *logical.LogInput) error
|
||||||
|
|
||||||
|
// LogResponse is used to synchronously log a response. This is done after
|
||||||
|
// the request is processed but before the response is sent. The arguments
|
||||||
|
// MUST not be modified in any way. They should be deep copied if this is
|
||||||
|
// a possibility.
|
||||||
|
LogResponse(context.Context, *logical.LogInput) error
|
||||||
|
|
||||||
|
// LogTestMessage is used to check an audit backend before adding it
|
||||||
|
// permanently. It should attempt to synchronously log the given test
|
||||||
|
// message, WITHOUT using the normal Salt (which would require a storage
|
||||||
|
// operation on creation, which is currently disallowed.)
|
||||||
|
LogTestMessage(context.Context, *logical.LogInput, map[string]string) error
|
||||||
|
|
||||||
|
// GetHash is used to return the given data with the backend's hash,
|
||||||
|
// so that a caller can determine if a value in the audit log matches
|
||||||
|
// an expected plaintext value
|
||||||
|
GetHash(context.Context, string) (string, error)
|
||||||
|
|
||||||
|
// Reload is called on SIGHUP for supporting backends.
|
||||||
|
Reload(context.Context) error
|
||||||
|
|
||||||
|
// Invalidate is called for path invalidation
|
||||||
|
Invalidate(context.Context)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BackendConfig contains configuration parameters used in the factory func to
|
||||||
|
// instantiate audit backends
|
||||||
|
type BackendConfig struct {
|
||||||
|
// The view to store the salt
|
||||||
|
SaltView logical.Storage
|
||||||
|
|
||||||
|
// The salt config that should be used for any secret obfuscation
|
||||||
|
SaltConfig *salt.Config
|
||||||
|
|
||||||
|
// Config is the opaque user configuration provided when mounting
|
||||||
|
Config map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Factory is the factory function to create an audit backend.
|
||||||
|
type Factory func(context.Context, *BackendConfig, bool) (Backend, error)
|
||||||
Reference in New Issue
Block a user