Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
# Conflicts:
#	dialoptions.go
  • Loading branch information
hueypark committed May 28, 2023
2 parents 2678efb + 9b9b364 commit 8199eeb
Show file tree
Hide file tree
Showing 166 changed files with 12,722 additions and 4,005 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ jobs:
steps:
# Setup the environment.
- name: Setup Go
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: '1.20'
- name: Checkout repo
uses: actions/checkout@v2
uses: actions/checkout@v3

# Run the vet checks.
- name: vet
Expand Down Expand Up @@ -89,12 +89,12 @@ jobs:
run: echo "${{ matrix.grpcenv }}" >> $GITHUB_ENV

- name: Setup Go
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.goversion }}

- name: Checkout repo
uses: actions/checkout@v2
uses: actions/checkout@v3

# Only run vet for 'vet' runs.
- name: Run vet.sh
Expand Down
29 changes: 29 additions & 0 deletions attributes/attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
// later release.
package attributes

import (
"fmt"
"strings"
)

// Attributes is an immutable struct for storing and retrieving generic
// key/value pairs. Keys must be hashable, and users should define their own
// types for keys. Values should not be modified after they are added to an
Expand Down Expand Up @@ -99,3 +104,27 @@ func (a *Attributes) Equal(o *Attributes) bool {
}
return true
}

// String prints the attribute map. If any key or values throughout the map
// implement fmt.Stringer, it calls that method and appends.
func (a *Attributes) String() string {
var sb strings.Builder
sb.WriteString("{")
first := true
for k, v := range a.m {
var key, val string
if str, ok := k.(interface{ String() string }); ok {
key = str.String()
}
if str, ok := v.(interface{ String() string }); ok {
val = str.String()
}
if !first {
sb.WriteString(", ")
}
sb.WriteString(fmt.Sprintf("%q: %q, ", key, val))
first = false
}
sb.WriteString("}")
return sb.String()
}
47 changes: 24 additions & 23 deletions authz/audit_logger.go → authz/audit/audit_logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
*
*/

package authz
// Package audit contains interfaces for audit logging during authorization.
package audit

import (
"encoding/json"
Expand All @@ -27,38 +28,38 @@ import (
// to facilitate thread-safe reading/writing operations.
type loggerBuilderRegistry struct {
mu sync.Mutex
builders map[string]AuditLoggerBuilder
builders map[string]LoggerBuilder
}

var (
registry = loggerBuilderRegistry{
builders: make(map[string]AuditLoggerBuilder),
builders: make(map[string]LoggerBuilder),
}
)

// RegisterAuditLoggerBuilder registers the builder in a global map
// RegisterLoggerBuilder registers the builder in a global map
// using b.Name() as the key.
//
// This should only be called during initialization time (i.e. in an init()
// function). If multiple builders are registered with the same name,
// the one registered last will take effect.
func RegisterAuditLoggerBuilder(b AuditLoggerBuilder) {
func RegisterLoggerBuilder(b LoggerBuilder) {
registry.mu.Lock()
defer registry.mu.Unlock()
registry.builders[b.Name()] = b
}

// GetAuditLoggerBuilder returns a builder with the given name.
// GetLoggerBuilder returns a builder with the given name.
// It returns nil if the builder is not found in the registry.
func GetAuditLoggerBuilder(name string) AuditLoggerBuilder {
func GetLoggerBuilder(name string) LoggerBuilder {
registry.mu.Lock()
defer registry.mu.Unlock()
return registry.builders[name]
}

// AuditEvent contains information passed to the audit logger as part of an
// Event contains information passed to the audit logger as part of an
// audit logging event.
type AuditEvent struct {
type Event struct {
// FullMethodName is the full method name of the audited RPC, in the format
// of "/pkg.Service/Method". For example, "/helloworld.Greeter/SayHello".
FullMethodName string
Expand All @@ -74,14 +75,14 @@ type AuditEvent struct {
Authorized bool
}

// AuditLoggerConfig represents an opaque data structure holding an audit
// LoggerConfig represents an opaque data structure holding an audit
// logger configuration. Concrete types representing configuration of specific
// audit loggers must embed this interface to implement it.
type AuditLoggerConfig interface {
auditLoggerConfig()
type LoggerConfig interface {
loggerConfig()
}

// AuditLogger is the interface to be implemented by audit loggers.
// Logger is the interface to be implemented by audit loggers.
//
// An audit logger is a logger instance that can be configured via the
// authorization policy API or xDS HTTP RBAC filters. When the authorization
Expand All @@ -91,35 +92,35 @@ type AuditLoggerConfig interface {
// TODO(lwge): Change the link to the merged gRFC once it's ready.
// Please refer to https://github.com/grpc/proposal/pull/346 for more details
// about audit logging.
type AuditLogger interface {
type Logger interface {
// Log performs audit logging for the provided audit event.
//
// This method is invoked in the RPC path and therefore implementations
// must not block.
Log(*AuditEvent)
Log(*Event)
}

// AuditLoggerBuilder is the interface to be implemented by audit logger
// LoggerBuilder is the interface to be implemented by audit logger
// builders that are used at runtime to configure and instantiate audit loggers.
//
// Users who want to implement their own audit logging logic should
// implement this interface, along with the AuditLogger interface, and register
// it by calling RegisterAuditLoggerBuilder() at init time.
// implement this interface, along with the Logger interface, and register
// it by calling RegisterLoggerBuilder() at init time.
//
// TODO(lwge): Change the link to the merged gRFC once it's ready.
// Please refer to https://github.com/grpc/proposal/pull/346 for more details
// about audit logging.
type AuditLoggerBuilder interface {
// ParseAuditLoggerConfig parses the given JSON bytes into a structured
type LoggerBuilder interface {
// ParseLoggerConfig parses the given JSON bytes into a structured
// logger config this builder can use to build an audit logger.
ParseAuditLoggerConfig(config json.RawMessage) (AuditLoggerConfig, error)
ParseLoggerConfig(config json.RawMessage) (LoggerConfig, error)
// Build builds an audit logger with the given logger config.
// This will only be called with valid configs returned from
// ParseAuditLoggerConfig() and any runtime issues such as failing to
// ParseLoggerConfig() and any runtime issues such as failing to
// create a file should be handled by the logger implementation instead of
// failing the logger instantiation. So implementers need to make sure it
// can return a logger without error at this stage.
Build(AuditLoggerConfig) AuditLogger
Build(LoggerConfig) Logger
// Name returns the name of logger built by this builder.
// This is used to register and pick the builder.
Name() string
Expand Down
110 changes: 110 additions & 0 deletions authz/audit/stdout/stdout_logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
*
* Copyright 2023 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

// Package stdout defines an stdout audit logger.
package stdout

import (
"encoding/json"
"log"
"os"
"time"

"google.golang.org/grpc/authz/audit"
"google.golang.org/grpc/grpclog"
)

var grpcLogger = grpclog.Component("authz-audit")

// Name is the string to identify this logger type in the registry
const Name = "stdout_logger"

func init() {
audit.RegisterLoggerBuilder(&loggerBuilder{
goLogger: log.New(os.Stdout, "", 0),
})
}

type event struct {
FullMethodName string `json:"rpc_method"`
Principal string `json:"principal"`
PolicyName string `json:"policy_name"`
MatchedRule string `json:"matched_rule"`
Authorized bool `json:"authorized"`
Timestamp string `json:"timestamp"` // Time when the audit event is logged via Log method
}

// logger implements the audit.logger interface by logging to standard output.
type logger struct {
goLogger *log.Logger
}

// Log marshals the audit.Event to json and prints it to standard output.
func (l *logger) Log(event *audit.Event) {
jsonContainer := map[string]interface{}{
"grpc_audit_log": convertEvent(event),
}
jsonBytes, err := json.Marshal(jsonContainer)
if err != nil {
grpcLogger.Errorf("failed to marshal AuditEvent data to JSON: %v", err)
return
}
l.goLogger.Println(string(jsonBytes))
}

// loggerConfig represents the configuration for the stdout logger.
// It is currently empty and implements the audit.Logger interface by embedding it.
type loggerConfig struct {
audit.LoggerConfig
}

type loggerBuilder struct {
goLogger *log.Logger
}

func (loggerBuilder) Name() string {
return Name
}

// Build returns a new instance of the stdout logger.
// Passed in configuration is ignored as the stdout logger does not
// expect any configuration to be provided.
func (lb *loggerBuilder) Build(audit.LoggerConfig) audit.Logger {
return &logger{
goLogger: lb.goLogger,
}
}

// ParseLoggerConfig is a no-op since the stdout logger does not accept any configuration.
func (*loggerBuilder) ParseLoggerConfig(config json.RawMessage) (audit.LoggerConfig, error) {
if len(config) != 0 && string(config) != "{}" {
grpcLogger.Warningf("Stdout logger doesn't support custom configs. Ignoring:\n%s", string(config))
}
return &loggerConfig{}, nil
}

func convertEvent(auditEvent *audit.Event) *event {
return &event{
FullMethodName: auditEvent.FullMethodName,
Principal: auditEvent.Principal,
PolicyName: auditEvent.PolicyName,
MatchedRule: auditEvent.MatchedRule,
Authorized: auditEvent.Authorized,
Timestamp: time.Now().Format(time.RFC3339Nano),
}
}
Loading

0 comments on commit 8199eeb

Please sign in to comment.