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 audit contains interfaces for audit logging during authorization. 20 package audit 21 22 import ( 23 "encoding/json" 24 "sync" 25 ) 26 27 // loggerBuilderRegistry holds a map of audit logger builders and a mutex 28 // to facilitate thread-safe reading/writing operations. 29 type loggerBuilderRegistry struct { 30 mu sync.Mutex 31 builders map[string]LoggerBuilder 32 } 33 34 var ( 35 registry = loggerBuilderRegistry{ 36 builders: make(map[string]LoggerBuilder), 37 } 38 ) 39 40 // RegisterLoggerBuilder registers the builder in a global map 41 // using b.Name() as the key. 42 // 43 // This should only be called during initialization time (i.e. in an init() 44 // function). If multiple builders are registered with the same name, 45 // the one registered last will take effect. 46 func RegisterLoggerBuilder(b LoggerBuilder) { 47 registry.mu.Lock() 48 defer registry.mu.Unlock() 49 registry.builders[b.Name()] = b 50 } 51 52 // GetLoggerBuilder returns a builder with the given name. 53 // It returns nil if the builder is not found in the registry. 54 func GetLoggerBuilder(name string) LoggerBuilder { 55 registry.mu.Lock() 56 defer registry.mu.Unlock() 57 return registry.builders[name] 58 } 59 60 // Event contains information passed to the audit logger as part of an 61 // audit logging event. 62 type Event struct { 63 // FullMethodName is the full method name of the audited RPC, in the format 64 // of "/pkg.Service/Method". For example, "/helloworld.Greeter/SayHello". 65 FullMethodName string 66 // Principal is the identity of the caller. Currently it will only be 67 // available in certificate-based TLS authentication. 68 Principal string 69 // PolicyName is the authorization policy name or the xDS RBAC filter name. 70 PolicyName string 71 // MatchedRule is the matched rule or policy name in the xDS RBAC filter. 72 // It will be empty if there is no match. 73 MatchedRule string 74 // Authorized indicates whether the audited RPC is authorized or not. 75 Authorized bool 76 } 77 78 // LoggerConfig represents an opaque data structure holding an audit 79 // logger configuration. Concrete types representing configuration of specific 80 // audit loggers must embed this interface to implement it. 81 type LoggerConfig interface { 82 loggerConfig() 83 } 84 85 // Logger is the interface to be implemented by audit loggers. 86 // 87 // An audit logger is a logger instance that can be configured via the 88 // authorization policy API or xDS HTTP RBAC filters. When the authorization 89 // decision meets the condition for audit, all the configured audit loggers' 90 // Log() method will be invoked to log that event. 91 // 92 // Please refer to 93 // https://github.com/grpc/proposal/blob/master/A59-audit-logging.md for more 94 // details about audit logging. 95 type Logger interface { 96 // Log performs audit logging for the provided audit event. 97 // 98 // This method is invoked in the RPC path and therefore implementations 99 // must not block. 100 Log(*Event) 101 } 102 103 // LoggerBuilder is the interface to be implemented by audit logger 104 // builders that are used at runtime to configure and instantiate audit loggers. 105 // 106 // Users who want to implement their own audit logging logic should 107 // implement this interface, along with the Logger interface, and register 108 // it by calling RegisterLoggerBuilder() at init time. 109 // 110 // Please refer to 111 // https://github.com/grpc/proposal/blob/master/A59-audit-logging.md for more 112 // details about audit logging. 113 type LoggerBuilder interface { 114 // ParseLoggerConfig parses the given JSON bytes into a structured 115 // logger config this builder can use to build an audit logger. 116 ParseLoggerConfig(config json.RawMessage) (LoggerConfig, error) 117 // Build builds an audit logger with the given logger config. 118 // This will only be called with valid configs returned from 119 // ParseLoggerConfig() and any runtime issues such as failing to 120 // create a file should be handled by the logger implementation instead of 121 // failing the logger instantiation. So implementers need to make sure it 122 // can return a logger without error at this stage. 123 Build(LoggerConfig) Logger 124 // Name returns the name of logger built by this builder. 125 // This is used to register and pick the builder. 126 Name() string 127 } 128