google.golang.org/grpc@v1.62.1/authz/audit/stdout/stdout_logger.go (about) 1 /* 2 * 3 * Copyright 2023 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 // Package stdout defines an stdout audit logger. 20 package stdout 21 22 import ( 23 "encoding/json" 24 "log" 25 "os" 26 "time" 27 28 "google.golang.org/grpc/authz/audit" 29 "google.golang.org/grpc/grpclog" 30 ) 31 32 var grpcLogger = grpclog.Component("authz-audit") 33 34 // Name is the string to identify this logger type in the registry 35 const Name = "stdout_logger" 36 37 func init() { 38 audit.RegisterLoggerBuilder(&loggerBuilder{ 39 goLogger: log.New(os.Stdout, "", 0), 40 }) 41 } 42 43 type event struct { 44 FullMethodName string `json:"rpc_method"` 45 Principal string `json:"principal"` 46 PolicyName string `json:"policy_name"` 47 MatchedRule string `json:"matched_rule"` 48 Authorized bool `json:"authorized"` 49 Timestamp string `json:"timestamp"` // Time when the audit event is logged via Log method 50 } 51 52 // logger implements the audit.logger interface by logging to standard output. 53 type logger struct { 54 goLogger *log.Logger 55 } 56 57 // Log marshals the audit.Event to json and prints it to standard output. 58 func (l *logger) Log(event *audit.Event) { 59 jsonContainer := map[string]any{ 60 "grpc_audit_log": convertEvent(event), 61 } 62 jsonBytes, err := json.Marshal(jsonContainer) 63 if err != nil { 64 grpcLogger.Errorf("failed to marshal AuditEvent data to JSON: %v", err) 65 return 66 } 67 l.goLogger.Println(string(jsonBytes)) 68 } 69 70 // loggerConfig represents the configuration for the stdout logger. 71 // It is currently empty and implements the audit.Logger interface by embedding it. 72 type loggerConfig struct { 73 audit.LoggerConfig 74 } 75 76 type loggerBuilder struct { 77 goLogger *log.Logger 78 } 79 80 func (loggerBuilder) Name() string { 81 return Name 82 } 83 84 // Build returns a new instance of the stdout logger. 85 // Passed in configuration is ignored as the stdout logger does not 86 // expect any configuration to be provided. 87 func (lb *loggerBuilder) Build(audit.LoggerConfig) audit.Logger { 88 return &logger{ 89 goLogger: lb.goLogger, 90 } 91 } 92 93 // ParseLoggerConfig is a no-op since the stdout logger does not accept any configuration. 94 func (*loggerBuilder) ParseLoggerConfig(config json.RawMessage) (audit.LoggerConfig, error) { 95 if len(config) != 0 && string(config) != "{}" { 96 grpcLogger.Warningf("Stdout logger doesn't support custom configs. Ignoring:\n%s", string(config)) 97 } 98 return &loggerConfig{}, nil 99 } 100 101 func convertEvent(auditEvent *audit.Event) *event { 102 return &event{ 103 FullMethodName: auditEvent.FullMethodName, 104 Principal: auditEvent.Principal, 105 PolicyName: auditEvent.PolicyName, 106 MatchedRule: auditEvent.MatchedRule, 107 Authorized: auditEvent.Authorized, 108 Timestamp: time.Now().Format(time.RFC3339Nano), 109 } 110 }