google.golang.org/grpc@v1.62.1/internal/xds/rbac/converter_test.go (about)

     1  /*
     2   * Copyright 2023 gRPC authors.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package rbac
    18  
    19  import (
    20  	"reflect"
    21  	"strings"
    22  	"testing"
    23  
    24  	v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
    25  	v3rbacpb "github.com/envoyproxy/go-control-plane/envoy/config/rbac/v3"
    26  	v3auditloggersstreampb "github.com/envoyproxy/go-control-plane/envoy/extensions/rbac/audit_loggers/stream/v3"
    27  	"google.golang.org/grpc/authz/audit"
    28  	"google.golang.org/grpc/authz/audit/stdout"
    29  	"google.golang.org/grpc/internal/testutils"
    30  	"google.golang.org/protobuf/types/known/anypb"
    31  )
    32  
    33  func (s) TestBuildLoggerErrors(t *testing.T) {
    34  	tests := []struct {
    35  		name           string
    36  		loggerConfig   *v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig
    37  		expectedLogger audit.Logger
    38  		expectedError  string
    39  	}{
    40  		{
    41  			name: "nil typed config",
    42  			loggerConfig: &v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
    43  				AuditLogger: &v3corepb.TypedExtensionConfig{
    44  					TypedConfig: nil,
    45  				},
    46  			},
    47  			expectedError: "missing required field: TypedConfig",
    48  		},
    49  		{
    50  			name: "Unsupported Type",
    51  			loggerConfig: &v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
    52  				AuditLogger: &v3corepb.TypedExtensionConfig{
    53  					Name:        "TestAuditLoggerBuffer",
    54  					TypedConfig: testutils.MarshalAny(t, &v3rbacpb.RBAC_AuditLoggingOptions{}),
    55  				},
    56  			},
    57  			expectedError: "custom config not implemented for type ",
    58  		},
    59  		{
    60  			name: "Empty name",
    61  			loggerConfig: &v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
    62  				AuditLogger: &v3corepb.TypedExtensionConfig{
    63  					Name:        "TestAuditLoggerBuffer",
    64  					TypedConfig: createUDPATypedStruct(t, map[string]any{}, ""),
    65  				},
    66  			},
    67  			expectedError: "field TypedConfig.TypeURL cannot be an empty string",
    68  		},
    69  		{
    70  			name: "No registered logger",
    71  			loggerConfig: &v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
    72  				AuditLogger: &v3corepb.TypedExtensionConfig{
    73  					Name:        "UnregisteredLogger",
    74  					TypedConfig: createUDPATypedStruct(t, map[string]any{}, "UnregisteredLogger"),
    75  				},
    76  				IsOptional: false,
    77  			},
    78  			expectedError: "no builder registered for UnregisteredLogger",
    79  		},
    80  		{
    81  			name: "fail to parse custom config",
    82  			loggerConfig: &v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
    83  				AuditLogger: &v3corepb.TypedExtensionConfig{
    84  					Name:        "TestAuditLoggerCustomConfig",
    85  					TypedConfig: createUDPATypedStruct(t, map[string]any{"abc": "BADVALUE", "xyz": "123"}, "fail to parse custom config_TestAuditLoggerCustomConfig")},
    86  				IsOptional: false,
    87  			},
    88  			expectedError: "custom config could not be parsed",
    89  		},
    90  		{
    91  			name: "no registered logger but optional passes",
    92  			loggerConfig: &v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
    93  				AuditLogger: &v3corepb.TypedExtensionConfig{
    94  					Name:        "UnregisteredLogger",
    95  					TypedConfig: createUDPATypedStruct(t, map[string]any{}, "no registered logger but optional passes_UnregisteredLogger"),
    96  				},
    97  				IsOptional: true,
    98  			},
    99  			expectedLogger: nil,
   100  		},
   101  	}
   102  	for _, test := range tests {
   103  		t.Run(test.name, func(t *testing.T) {
   104  			b := TestAuditLoggerCustomConfigBuilder{testName: test.name}
   105  			audit.RegisterLoggerBuilder(&b)
   106  			logger, err := buildLogger(test.loggerConfig)
   107  			if err != nil && !strings.HasPrefix(err.Error(), test.expectedError) {
   108  				t.Fatalf("expected error: %v. got error: %v", test.expectedError, err)
   109  			}
   110  			if logger != test.expectedLogger {
   111  				t.Fatalf("expected logger: %v. got logger: %v", test.expectedLogger, logger)
   112  			}
   113  
   114  		})
   115  	}
   116  }
   117  
   118  func (s) TestBuildLoggerKnownTypes(t *testing.T) {
   119  	tests := []struct {
   120  		name         string
   121  		loggerConfig *v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig
   122  		expectedType reflect.Type
   123  	}{
   124  		{
   125  			name: "stdout logger",
   126  			loggerConfig: &v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
   127  				AuditLogger: &v3corepb.TypedExtensionConfig{
   128  					Name:        stdout.Name,
   129  					TypedConfig: createStdoutPb(t),
   130  				},
   131  				IsOptional: false,
   132  			},
   133  			expectedType: reflect.TypeOf(audit.GetLoggerBuilder(stdout.Name).Build(nil)),
   134  		},
   135  		{
   136  			name: "stdout logger with generic TypedConfig",
   137  			loggerConfig: &v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
   138  				AuditLogger: &v3corepb.TypedExtensionConfig{
   139  					Name:        stdout.Name,
   140  					TypedConfig: createXDSTypedStruct(t, map[string]any{}, stdout.Name),
   141  				},
   142  				IsOptional: false,
   143  			},
   144  			expectedType: reflect.TypeOf(audit.GetLoggerBuilder(stdout.Name).Build(nil)),
   145  		},
   146  	}
   147  	for _, test := range tests {
   148  		t.Run(test.name, func(t *testing.T) {
   149  			logger, err := buildLogger(test.loggerConfig)
   150  			if err != nil {
   151  				t.Fatalf("expected success. got error: %v", err)
   152  			}
   153  			loggerType := reflect.TypeOf(logger)
   154  			if test.expectedType != loggerType {
   155  				t.Fatalf("logger not of expected type. want: %v got: %v", test.expectedType, loggerType)
   156  			}
   157  		})
   158  	}
   159  }
   160  
   161  // Builds stdout config for audit logger proto.
   162  func createStdoutPb(t *testing.T) *anypb.Any {
   163  	t.Helper()
   164  	pb := &v3auditloggersstreampb.StdoutAuditLog{}
   165  	customConfig, err := anypb.New(pb)
   166  	if err != nil {
   167  		t.Fatalf("createStdoutPb failed during anypb.New: %v", err)
   168  	}
   169  	return customConfig
   170  }