123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- /*
- * 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 rbac
- import (
- "encoding/json"
- "fmt"
- "strings"
- v1xdsudpatypepb "github.com/cncf/xds/go/udpa/type/v1"
- v3xdsxdstypepb "github.com/cncf/xds/go/xds/type/v3"
- v3rbacpb "github.com/envoyproxy/go-control-plane/envoy/config/rbac/v3"
- v3auditloggersstreampb "github.com/envoyproxy/go-control-plane/envoy/extensions/rbac/audit_loggers/stream/v3"
- "google.golang.org/grpc/authz/audit"
- "google.golang.org/grpc/authz/audit/stdout"
- "google.golang.org/protobuf/encoding/protojson"
- "google.golang.org/protobuf/types/known/anypb"
- "google.golang.org/protobuf/types/known/structpb"
- )
- func buildLogger(loggerConfig *v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig) (audit.Logger, error) {
- if loggerConfig.GetAuditLogger().GetTypedConfig() == nil {
- return nil, fmt.Errorf("missing required field: TypedConfig")
- }
- customConfig, loggerName, err := getCustomConfig(loggerConfig.AuditLogger.TypedConfig)
- if err != nil {
- return nil, err
- }
- if loggerName == "" {
- return nil, fmt.Errorf("field TypedConfig.TypeURL cannot be an empty string")
- }
- factory := audit.GetLoggerBuilder(loggerName)
- if factory == nil {
- if loggerConfig.IsOptional {
- return nil, nil
- }
- return nil, fmt.Errorf("no builder registered for %v", loggerName)
- }
- auditLoggerConfig, err := factory.ParseLoggerConfig(customConfig)
- if err != nil {
- return nil, fmt.Errorf("custom config could not be parsed by registered factory. error: %v", err)
- }
- auditLogger := factory.Build(auditLoggerConfig)
- return auditLogger, nil
- }
- func getCustomConfig(config *anypb.Any) (json.RawMessage, string, error) {
- any, err := config.UnmarshalNew()
- if err != nil {
- return nil, "", err
- }
- switch m := any.(type) {
- case *v1xdsudpatypepb.TypedStruct:
- return convertCustomConfig(m.TypeUrl, m.Value)
- case *v3xdsxdstypepb.TypedStruct:
- return convertCustomConfig(m.TypeUrl, m.Value)
- case *v3auditloggersstreampb.StdoutAuditLog:
- return convertStdoutConfig(m)
- }
- return nil, "", fmt.Errorf("custom config not implemented for type [%v]", config.GetTypeUrl())
- }
- func convertStdoutConfig(config *v3auditloggersstreampb.StdoutAuditLog) (json.RawMessage, string, error) {
- json, err := protojson.Marshal(config)
- return json, stdout.Name, err
- }
- func convertCustomConfig(typeURL string, s *structpb.Struct) (json.RawMessage, string, error) {
- // The gRPC policy name will be the "type name" part of the value of the
- // type_url field in the TypedStruct. We get this by using the part after
- // the last / character. Can assume a valid type_url from the control plane.
- urls := strings.Split(typeURL, "/")
- if len(urls) == 0 {
- return nil, "", fmt.Errorf("error converting custom audit logger %v for %v: typeURL must have a url-like format with the typeName being the value after the last /", typeURL, s)
- }
- name := urls[len(urls)-1]
- rawJSON := []byte("{}")
- var err error
- if s != nil {
- rawJSON, err = json.Marshal(s)
- if err != nil {
- return nil, "", fmt.Errorf("error converting custom audit logger %v for %v: %v", typeURL, s, err)
- }
- }
- return rawJSON, name, nil
- }
|