Commit eab5e060 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #48605 from CaoShuFeng/json_log

Automatic merge from submit-queue (batch tested with PRs 48583, 48605, 48601) support json output for log backend of advanced audit **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes # **Special notes for your reviewer**: **Release note**: ``` Add json format support for advanced audit in apiserver. Use --audit-log-format=json to emit json to log backend. ```
parents 9c86d747 bc94370e
......@@ -23,11 +23,14 @@ go_test(
deps = [
"//vendor/k8s.io/api/authentication/v1:go_default_library",
"//vendor/k8s.io/api/batch/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/audit/v1alpha1:go_default_library",
"//vendor/k8s.io/apiserver/pkg/audit:go_default_library",
"//vendor/k8s.io/apiserver/pkg/audit/policy:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
......@@ -35,6 +38,7 @@ go_test(
"//vendor/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//vendor/k8s.io/apiserver/plugin/pkg/audit/log:go_default_library",
"//vendor/k8s.io/apiserver/plugin/pkg/audit/webhook:go_default_library",
],
)
......
......@@ -63,6 +63,7 @@ type AuditLogOptions struct {
MaxAge int
MaxBackups int
MaxSize int
Format string
}
// AuditWebhookOptions control the webhook configuration for audit events.
......@@ -78,6 +79,7 @@ type AuditWebhookOptions struct {
func NewAuditOptions() *AuditOptions {
return &AuditOptions{
WebhookOptions: AuditWebhookOptions{Mode: pluginwebhook.ModeBatch},
LogOptions: AuditLogOptions{Format: pluginlog.FormatLegacy},
}
}
......@@ -104,6 +106,18 @@ func (o *AuditOptions) Validate() []error {
if !validMode {
allErrors = append(allErrors, fmt.Errorf("invalid audit webhook mode %s, allowed modes are %q", o.WebhookOptions.Mode, strings.Join(pluginwebhook.AllowedModes, ",")))
}
// check log format
validFormat := false
for _, f := range pluginlog.AllowedFormats {
if f == o.LogOptions.Format {
validFormat = true
break
}
}
if !validFormat {
allErrors = append(allErrors, fmt.Errorf("invalid audit log format %s, allowed formats are %q", o.LogOptions.Format, strings.Join(pluginlog.AllowedFormats, ",")))
}
}
return allErrors
}
......@@ -161,6 +175,10 @@ func (o *AuditLogOptions) AddFlags(fs *pflag.FlagSet) {
"The maximum number of old audit log files to retain.")
fs.IntVar(&o.MaxSize, "audit-log-maxsize", o.MaxSize,
"The maximum size in megabytes of the audit log file before it gets rotated.")
fs.StringVar(&o.Format, "audit-log-format", o.Format,
"Format of saved audits. \"legacy\" indicates 1-line text format for each event."+
" \"json\" indicates structured json format. Requires the 'AdvancedAuditing' feature"+
" gate. Known formats are "+strings.Join(pluginlog.AllowedFormats, ",")+".")
}
func (o *AuditLogOptions) getWriter() io.Writer {
......@@ -182,7 +200,7 @@ func (o *AuditLogOptions) getWriter() io.Writer {
func (o *AuditLogOptions) advancedApplyTo(c *server.Config) error {
if w := o.getWriter(); w != nil {
c.AuditBackend = appendBackend(c.AuditBackend, pluginlog.NewBackend(w))
c.AuditBackend = appendBackend(c.AuditBackend, pluginlog.NewBackend(w, o.Format))
}
return nil
}
......
......@@ -12,7 +12,9 @@ go_library(
srcs = ["backend.go"],
tags = ["automanaged"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/audit/v1alpha1:go_default_library",
"//vendor/k8s.io/apiserver/pkg/audit:go_default_library",
],
)
......@@ -19,20 +19,38 @@ package log
import (
"fmt"
"io"
"strings"
"k8s.io/apimachinery/pkg/runtime"
auditinternal "k8s.io/apiserver/pkg/apis/audit"
auditv1alpha1 "k8s.io/apiserver/pkg/apis/audit/v1alpha1"
"k8s.io/apiserver/pkg/audit"
)
const (
// FormatLegacy saves event in 1-line text format.
FormatLegacy = "legacy"
// FormatJson saves event in structured json format.
FormatJson = "json"
)
// AllowedFormats are the formats known by log backend.
var AllowedFormats = []string{
FormatLegacy,
FormatJson,
}
type backend struct {
out io.Writer
out io.Writer
format string
}
var _ audit.Backend = &backend{}
func NewBackend(out io.Writer) *backend {
func NewBackend(out io.Writer, format string) *backend {
return &backend{
out: out,
out: out,
format: format,
}
}
......@@ -43,8 +61,23 @@ func (b *backend) ProcessEvents(events ...*auditinternal.Event) {
}
func (b *backend) logEvent(ev *auditinternal.Event) {
line := audit.EventString(ev)
if _, err := fmt.Fprintln(b.out, line); err != nil {
line := ""
switch b.format {
case FormatLegacy:
line = audit.EventString(ev) + "\n"
case FormatJson:
bs, err := runtime.Encode(audit.Codecs.LegacyCodec(auditv1alpha1.SchemeGroupVersion), ev)
if err != nil {
audit.HandlePluginError("log", err, ev)
return
}
line = string(bs[:])
default:
audit.HandlePluginError("log", fmt.Errorf("log format %q is not in list of known formats (%s)",
b.format, strings.Join(AllowedFormats, ",")), ev)
return
}
if _, err := fmt.Fprint(b.out, line); err != nil {
audit.HandlePluginError("log", err, ev)
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment