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 }