Skip to content

Commit aa8c137

Browse files
authored
authz: add audit logging APIs (#6158)
1 parent b91b884 commit aa8c137

File tree

1 file changed

+126
-0
lines changed

1 file changed

+126
-0
lines changed

authz/audit_logger.go

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

0 commit comments

Comments
 (0)