google.golang.org/grpc@v1.62.1/authz/rbac_translator_test.go (about) 1 /* 2 * 3 * Copyright 2021 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 "strings" 23 "testing" 24 25 v1xdsudpatypepb "github.com/cncf/xds/go/udpa/type/v1" 26 "github.com/google/go-cmp/cmp" 27 "google.golang.org/protobuf/testing/protocmp" 28 "google.golang.org/protobuf/types/known/anypb" 29 "google.golang.org/protobuf/types/known/structpb" 30 31 v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" 32 v3rbacpb "github.com/envoyproxy/go-control-plane/envoy/config/rbac/v3" 33 v3routepb "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" 34 v3matcherpb "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" 35 ) 36 37 func TestTranslatePolicy(t *testing.T) { 38 tests := map[string]struct { 39 authzPolicy string 40 wantErr string 41 wantPolicies []*v3rbacpb.RBAC 42 wantPolicyName string 43 }{ 44 "valid policy": { 45 authzPolicy: `{ 46 "name": "authz", 47 "deny_rules": [ 48 { 49 "name": "deny_policy_1", 50 "source": { 51 "principals":[ 52 "spiffe://foo.abc", 53 "spiffe://bar*", 54 "*baz", 55 "spiffe://abc.*.com" 56 ] 57 } 58 }], 59 "allow_rules": [ 60 { 61 "name": "allow_policy_1", 62 "source": { 63 "principals":["*"] 64 }, 65 "request": { 66 "paths": ["path-foo*"] 67 } 68 }, 69 { 70 "name": "allow_policy_2", 71 "request": { 72 "paths": [ 73 "path-bar", 74 "*baz" 75 ], 76 "headers": [ 77 { 78 "key": "key-1", 79 "values": ["foo", "*bar"] 80 }, 81 { 82 "key": "key-2", 83 "values": ["baz*"] 84 } 85 ] 86 } 87 }] 88 }`, 89 wantPolicies: []*v3rbacpb.RBAC{ 90 { 91 Action: v3rbacpb.RBAC_DENY, 92 Policies: map[string]*v3rbacpb.Policy{ 93 "authz_deny_policy_1": { 94 Principals: []*v3rbacpb.Principal{ 95 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 96 Ids: []*v3rbacpb.Principal{ 97 {Identifier: &v3rbacpb.Principal_Authenticated_{ 98 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 99 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "spiffe://foo.abc"}, 100 }}, 101 }}, 102 {Identifier: &v3rbacpb.Principal_Authenticated_{ 103 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 104 MatchPattern: &v3matcherpb.StringMatcher_Prefix{Prefix: "spiffe://bar"}, 105 }}, 106 }}, 107 {Identifier: &v3rbacpb.Principal_Authenticated_{ 108 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 109 MatchPattern: &v3matcherpb.StringMatcher_Suffix{Suffix: "baz"}, 110 }}, 111 }}, 112 {Identifier: &v3rbacpb.Principal_Authenticated_{ 113 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 114 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "spiffe://abc.*.com"}, 115 }}, 116 }}, 117 }, 118 }}}, 119 }, 120 Permissions: []*v3rbacpb.Permission{ 121 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 122 }, 123 }, 124 }, 125 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{}, 126 }, 127 { 128 Action: v3rbacpb.RBAC_ALLOW, 129 Policies: map[string]*v3rbacpb.Policy{ 130 "authz_allow_policy_1": { 131 Principals: []*v3rbacpb.Principal{ 132 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 133 Ids: []*v3rbacpb.Principal{ 134 {Identifier: &v3rbacpb.Principal_Authenticated_{ 135 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 136 MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}}, 137 }}, 138 }}, 139 }, 140 }}}, 141 }, 142 Permissions: []*v3rbacpb.Permission{ 143 {Rule: &v3rbacpb.Permission_AndRules{AndRules: &v3rbacpb.Permission_Set{ 144 Rules: []*v3rbacpb.Permission{ 145 {Rule: &v3rbacpb.Permission_OrRules{OrRules: &v3rbacpb.Permission_Set{ 146 Rules: []*v3rbacpb.Permission{ 147 {Rule: &v3rbacpb.Permission_UrlPath{ 148 UrlPath: &v3matcherpb.PathMatcher{Rule: &v3matcherpb.PathMatcher_Path{Path: &v3matcherpb.StringMatcher{ 149 MatchPattern: &v3matcherpb.StringMatcher_Prefix{Prefix: "path-foo"}, 150 }}}, 151 }}, 152 }, 153 }}}, 154 }, 155 }}}, 156 }, 157 }, 158 "authz_allow_policy_2": { 159 Principals: []*v3rbacpb.Principal{ 160 {Identifier: &v3rbacpb.Principal_Any{Any: true}}, 161 }, 162 Permissions: []*v3rbacpb.Permission{ 163 {Rule: &v3rbacpb.Permission_AndRules{AndRules: &v3rbacpb.Permission_Set{ 164 Rules: []*v3rbacpb.Permission{ 165 {Rule: &v3rbacpb.Permission_OrRules{OrRules: &v3rbacpb.Permission_Set{ 166 Rules: []*v3rbacpb.Permission{ 167 {Rule: &v3rbacpb.Permission_UrlPath{ 168 UrlPath: &v3matcherpb.PathMatcher{Rule: &v3matcherpb.PathMatcher_Path{Path: &v3matcherpb.StringMatcher{ 169 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "path-bar"}, 170 }}}, 171 }}, 172 {Rule: &v3rbacpb.Permission_UrlPath{ 173 UrlPath: &v3matcherpb.PathMatcher{Rule: &v3matcherpb.PathMatcher_Path{Path: &v3matcherpb.StringMatcher{ 174 MatchPattern: &v3matcherpb.StringMatcher_Suffix{Suffix: "baz"}, 175 }}}, 176 }}, 177 }, 178 }}}, 179 {Rule: &v3rbacpb.Permission_AndRules{AndRules: &v3rbacpb.Permission_Set{ 180 Rules: []*v3rbacpb.Permission{ 181 {Rule: &v3rbacpb.Permission_OrRules{OrRules: &v3rbacpb.Permission_Set{ 182 Rules: []*v3rbacpb.Permission{ 183 {Rule: &v3rbacpb.Permission_Header{ 184 Header: &v3routepb.HeaderMatcher{ 185 Name: "key-1", HeaderMatchSpecifier: &v3routepb.HeaderMatcher_ExactMatch{ExactMatch: "foo"}, 186 }, 187 }}, 188 {Rule: &v3rbacpb.Permission_Header{ 189 Header: &v3routepb.HeaderMatcher{ 190 Name: "key-1", HeaderMatchSpecifier: &v3routepb.HeaderMatcher_SuffixMatch{SuffixMatch: "bar"}, 191 }, 192 }}, 193 }, 194 }}}, 195 {Rule: &v3rbacpb.Permission_OrRules{OrRules: &v3rbacpb.Permission_Set{ 196 Rules: []*v3rbacpb.Permission{ 197 {Rule: &v3rbacpb.Permission_Header{ 198 Header: &v3routepb.HeaderMatcher{ 199 Name: "key-2", HeaderMatchSpecifier: &v3routepb.HeaderMatcher_PrefixMatch{PrefixMatch: "baz"}, 200 }, 201 }}, 202 }, 203 }}}, 204 }, 205 }}}, 206 }, 207 }}}, 208 }, 209 }, 210 }, 211 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{}, 212 }, 213 }, 214 wantPolicyName: "authz", 215 }, 216 "allow authenticated": { 217 authzPolicy: `{ 218 "name": "authz", 219 "allow_rules": [ 220 { 221 "name": "allow_authenticated", 222 "source": { 223 "principals":["*", ""] 224 } 225 }] 226 }`, 227 wantPolicies: []*v3rbacpb.RBAC{ 228 { 229 Action: v3rbacpb.RBAC_ALLOW, 230 Policies: map[string]*v3rbacpb.Policy{ 231 "authz_allow_authenticated": { 232 Principals: []*v3rbacpb.Principal{ 233 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 234 Ids: []*v3rbacpb.Principal{ 235 {Identifier: &v3rbacpb.Principal_Authenticated_{ 236 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 237 MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}}, 238 }}, 239 }}, 240 {Identifier: &v3rbacpb.Principal_Authenticated_{ 241 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 242 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""}, 243 }}, 244 }}, 245 }, 246 }}}, 247 }, 248 Permissions: []*v3rbacpb.Permission{ 249 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 250 }, 251 }, 252 }, 253 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{}, 254 }, 255 }, 256 }, 257 "audit_logging_ALLOW empty config": { 258 authzPolicy: `{ 259 "name": "authz", 260 "allow_rules": [ 261 { 262 "name": "allow_authenticated", 263 "source": { 264 "principals":["*", ""] 265 } 266 }], 267 "deny_rules": [ 268 { 269 "name": "deny_policy_1", 270 "source": { 271 "principals":[ 272 "spiffe://foo.abc" 273 ] 274 } 275 }], 276 "audit_logging_options": { 277 "audit_condition": "ON_ALLOW", 278 "audit_loggers": [ 279 { 280 "name": "stdout_logger", 281 "config": {}, 282 "is_optional": false 283 } 284 ] 285 } 286 }`, 287 wantPolicies: []*v3rbacpb.RBAC{ 288 { 289 Action: v3rbacpb.RBAC_DENY, 290 Policies: map[string]*v3rbacpb.Policy{ 291 "authz_deny_policy_1": { 292 Principals: []*v3rbacpb.Principal{ 293 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 294 Ids: []*v3rbacpb.Principal{ 295 {Identifier: &v3rbacpb.Principal_Authenticated_{ 296 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 297 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "spiffe://foo.abc"}, 298 }}, 299 }}, 300 }, 301 }}}, 302 }, 303 Permissions: []*v3rbacpb.Permission{ 304 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 305 }, 306 }, 307 }, 308 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{ 309 AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE, 310 LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{ 311 {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]any{}, "stdout_logger")}, 312 IsOptional: false, 313 }, 314 }, 315 }, 316 }, 317 { 318 Action: v3rbacpb.RBAC_ALLOW, 319 Policies: map[string]*v3rbacpb.Policy{ 320 "authz_allow_authenticated": { 321 Principals: []*v3rbacpb.Principal{ 322 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 323 Ids: []*v3rbacpb.Principal{ 324 {Identifier: &v3rbacpb.Principal_Authenticated_{ 325 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 326 MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}}, 327 }}, 328 }}, 329 {Identifier: &v3rbacpb.Principal_Authenticated_{ 330 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 331 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""}, 332 }}, 333 }}, 334 }, 335 }}}, 336 }, 337 Permissions: []*v3rbacpb.Permission{ 338 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 339 }, 340 }, 341 }, 342 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{ 343 AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_ON_ALLOW, 344 LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{ 345 {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]any{}, "stdout_logger")}, 346 IsOptional: false, 347 }, 348 }, 349 }, 350 }, 351 }, 352 }, 353 "audit_logging_DENY_AND_ALLOW": { 354 authzPolicy: `{ 355 "name": "authz", 356 "allow_rules": [ 357 { 358 "name": "allow_authenticated", 359 "source": { 360 "principals":["*", ""] 361 } 362 }], 363 "deny_rules": [ 364 { 365 "name": "deny_policy_1", 366 "source": { 367 "principals":[ 368 "spiffe://foo.abc" 369 ] 370 } 371 }], 372 "audit_logging_options": { 373 "audit_condition": "ON_DENY_AND_ALLOW", 374 "audit_loggers": [ 375 { 376 "name": "stdout_logger", 377 "config": {}, 378 "is_optional": false 379 } 380 ] 381 } 382 }`, 383 wantPolicies: []*v3rbacpb.RBAC{ 384 { 385 Action: v3rbacpb.RBAC_DENY, 386 Policies: map[string]*v3rbacpb.Policy{ 387 "authz_deny_policy_1": { 388 Principals: []*v3rbacpb.Principal{ 389 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 390 Ids: []*v3rbacpb.Principal{ 391 {Identifier: &v3rbacpb.Principal_Authenticated_{ 392 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 393 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "spiffe://foo.abc"}, 394 }}, 395 }}, 396 }, 397 }}}, 398 }, 399 Permissions: []*v3rbacpb.Permission{ 400 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 401 }, 402 }, 403 }, 404 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{ 405 AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_ON_DENY, 406 LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{ 407 {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]any{}, "stdout_logger")}, 408 IsOptional: false, 409 }, 410 }, 411 }, 412 }, 413 { 414 Action: v3rbacpb.RBAC_ALLOW, 415 Policies: map[string]*v3rbacpb.Policy{ 416 "authz_allow_authenticated": { 417 Principals: []*v3rbacpb.Principal{ 418 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 419 Ids: []*v3rbacpb.Principal{ 420 {Identifier: &v3rbacpb.Principal_Authenticated_{ 421 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 422 MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}}, 423 }}, 424 }}, 425 {Identifier: &v3rbacpb.Principal_Authenticated_{ 426 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 427 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""}, 428 }}, 429 }}, 430 }, 431 }}}, 432 }, 433 Permissions: []*v3rbacpb.Permission{ 434 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 435 }, 436 }, 437 }, 438 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{ 439 AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_ON_DENY_AND_ALLOW, 440 LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{ 441 {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]any{}, "stdout_logger")}, 442 IsOptional: false, 443 }, 444 }, 445 }, 446 }, 447 }, 448 }, 449 "audit_logging_NONE": { 450 authzPolicy: `{ 451 "name": "authz", 452 "allow_rules": [ 453 { 454 "name": "allow_authenticated", 455 "source": { 456 "principals":["*", ""] 457 } 458 }], 459 "deny_rules": [ 460 { 461 "name": "deny_policy_1", 462 "source": { 463 "principals":[ 464 "spiffe://foo.abc" 465 ] 466 } 467 }], 468 "audit_logging_options": { 469 "audit_condition": "NONE", 470 "audit_loggers": [ 471 { 472 "name": "stdout_logger", 473 "config": {}, 474 "is_optional": false 475 } 476 ] 477 } 478 }`, 479 wantPolicies: []*v3rbacpb.RBAC{ 480 { 481 Action: v3rbacpb.RBAC_DENY, 482 Policies: map[string]*v3rbacpb.Policy{ 483 "authz_deny_policy_1": { 484 Principals: []*v3rbacpb.Principal{ 485 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 486 Ids: []*v3rbacpb.Principal{ 487 {Identifier: &v3rbacpb.Principal_Authenticated_{ 488 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 489 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "spiffe://foo.abc"}, 490 }}, 491 }}, 492 }, 493 }}}, 494 }, 495 Permissions: []*v3rbacpb.Permission{ 496 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 497 }, 498 }, 499 }, 500 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{ 501 AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE, 502 LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{ 503 {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]any{}, "stdout_logger")}, 504 IsOptional: false, 505 }, 506 }, 507 }, 508 }, 509 { 510 Action: v3rbacpb.RBAC_ALLOW, 511 Policies: map[string]*v3rbacpb.Policy{ 512 "authz_allow_authenticated": { 513 Principals: []*v3rbacpb.Principal{ 514 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 515 Ids: []*v3rbacpb.Principal{ 516 {Identifier: &v3rbacpb.Principal_Authenticated_{ 517 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 518 MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}}, 519 }}, 520 }}, 521 {Identifier: &v3rbacpb.Principal_Authenticated_{ 522 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 523 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""}, 524 }}, 525 }}, 526 }, 527 }}}, 528 }, 529 Permissions: []*v3rbacpb.Permission{ 530 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 531 }, 532 }, 533 }, 534 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{ 535 AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE, 536 LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{ 537 {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]any{}, "stdout_logger")}, 538 IsOptional: false, 539 }, 540 }, 541 }, 542 }, 543 }, 544 }, 545 "audit_logging_custom_config simple": { 546 authzPolicy: `{ 547 "name": "authz", 548 "allow_rules": [ 549 { 550 "name": "allow_authenticated", 551 "source": { 552 "principals":["*", ""] 553 } 554 }], 555 "deny_rules": [ 556 { 557 "name": "deny_policy_1", 558 "source": { 559 "principals":[ 560 "spiffe://foo.abc" 561 ] 562 } 563 }], 564 "audit_logging_options": { 565 "audit_condition": "NONE", 566 "audit_loggers": [ 567 { 568 "name": "stdout_logger", 569 "config": {"abc":123, "xyz":"123"}, 570 "is_optional": false 571 } 572 ] 573 } 574 }`, 575 wantPolicies: []*v3rbacpb.RBAC{ 576 { 577 Action: v3rbacpb.RBAC_DENY, 578 Policies: map[string]*v3rbacpb.Policy{ 579 "authz_deny_policy_1": { 580 Principals: []*v3rbacpb.Principal{ 581 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 582 Ids: []*v3rbacpb.Principal{ 583 {Identifier: &v3rbacpb.Principal_Authenticated_{ 584 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 585 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "spiffe://foo.abc"}, 586 }}, 587 }}, 588 }, 589 }}}, 590 }, 591 Permissions: []*v3rbacpb.Permission{ 592 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 593 }, 594 }, 595 }, 596 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{ 597 AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE, 598 LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{ 599 {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]any{"abc": 123, "xyz": "123"}, "stdout_logger")}, 600 IsOptional: false, 601 }, 602 }, 603 }, 604 }, 605 { 606 Action: v3rbacpb.RBAC_ALLOW, 607 Policies: map[string]*v3rbacpb.Policy{ 608 "authz_allow_authenticated": { 609 Principals: []*v3rbacpb.Principal{ 610 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 611 Ids: []*v3rbacpb.Principal{ 612 {Identifier: &v3rbacpb.Principal_Authenticated_{ 613 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 614 MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}}, 615 }}, 616 }}, 617 {Identifier: &v3rbacpb.Principal_Authenticated_{ 618 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 619 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""}, 620 }}, 621 }}, 622 }, 623 }}}, 624 }, 625 Permissions: []*v3rbacpb.Permission{ 626 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 627 }, 628 }, 629 }, 630 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{ 631 AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE, 632 LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{ 633 {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]any{"abc": 123, "xyz": "123"}, "stdout_logger")}, 634 IsOptional: false, 635 }, 636 }, 637 }, 638 }, 639 }, 640 }, 641 "audit_logging_custom_config nested": { 642 authzPolicy: `{ 643 "name": "authz", 644 "allow_rules": [ 645 { 646 "name": "allow_authenticated", 647 "source": { 648 "principals":["*", ""] 649 } 650 }], 651 "audit_logging_options": { 652 "audit_condition": "NONE", 653 "audit_loggers": [ 654 { 655 "name": "stdout_logger", 656 "config": {"abc":123, "xyz":{"abc":123}}, 657 "is_optional": false 658 } 659 ] 660 } 661 }`, 662 wantPolicies: []*v3rbacpb.RBAC{ 663 { 664 Action: v3rbacpb.RBAC_ALLOW, 665 Policies: map[string]*v3rbacpb.Policy{ 666 "authz_allow_authenticated": { 667 Principals: []*v3rbacpb.Principal{ 668 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 669 Ids: []*v3rbacpb.Principal{ 670 {Identifier: &v3rbacpb.Principal_Authenticated_{ 671 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 672 MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}}, 673 }}, 674 }}, 675 {Identifier: &v3rbacpb.Principal_Authenticated_{ 676 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 677 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""}, 678 }}, 679 }}, 680 }, 681 }}}, 682 }, 683 Permissions: []*v3rbacpb.Permission{ 684 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 685 }, 686 }, 687 }, 688 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{ 689 AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE, 690 LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{ 691 {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]any{"abc": 123, "xyz": map[string]any{"abc": 123}}, "stdout_logger")}, 692 IsOptional: false, 693 }, 694 }, 695 }, 696 }, 697 }, 698 }, 699 "missing audit logger config": { 700 authzPolicy: `{ 701 "name": "authz", 702 "allow_rules": [ 703 { 704 "name": "allow_authenticated", 705 "source": { 706 "principals":["*", ""] 707 } 708 }], 709 "audit_logging_options": { 710 "audit_condition": "NONE" 711 } 712 }`, 713 wantPolicies: []*v3rbacpb.RBAC{ 714 { 715 Action: v3rbacpb.RBAC_ALLOW, 716 Policies: map[string]*v3rbacpb.Policy{ 717 "authz_allow_authenticated": { 718 Principals: []*v3rbacpb.Principal{ 719 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 720 Ids: []*v3rbacpb.Principal{ 721 {Identifier: &v3rbacpb.Principal_Authenticated_{ 722 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 723 MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}}, 724 }}, 725 }}, 726 {Identifier: &v3rbacpb.Principal_Authenticated_{ 727 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 728 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""}, 729 }}, 730 }}, 731 }, 732 }}}, 733 }, 734 Permissions: []*v3rbacpb.Permission{ 735 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 736 }, 737 }, 738 }, 739 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{ 740 AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE, 741 LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{}, 742 }, 743 }, 744 }, 745 }, 746 "missing audit condition": { 747 authzPolicy: `{ 748 "name": "authz", 749 "allow_rules": [ 750 { 751 "name": "allow_authenticated", 752 "source": { 753 "principals":["*", ""] 754 } 755 }], 756 "audit_logging_options": { 757 "audit_loggers": [ 758 { 759 "name": "stdout_logger", 760 "config": {}, 761 "is_optional": false 762 } 763 ] 764 } 765 }`, 766 wantPolicies: []*v3rbacpb.RBAC{ 767 { 768 Action: v3rbacpb.RBAC_ALLOW, 769 Policies: map[string]*v3rbacpb.Policy{ 770 "authz_allow_authenticated": { 771 Principals: []*v3rbacpb.Principal{ 772 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 773 Ids: []*v3rbacpb.Principal{ 774 {Identifier: &v3rbacpb.Principal_Authenticated_{ 775 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 776 MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}}, 777 }}, 778 }}, 779 {Identifier: &v3rbacpb.Principal_Authenticated_{ 780 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 781 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""}, 782 }}, 783 }}, 784 }, 785 }}}, 786 }, 787 Permissions: []*v3rbacpb.Permission{ 788 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 789 }, 790 }, 791 }, 792 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{ 793 AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE, 794 LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{ 795 {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]any{}, "stdout_logger")}, 796 IsOptional: false, 797 }, 798 }, 799 }, 800 }, 801 }, 802 }, 803 "missing custom config audit logger": { 804 authzPolicy: `{ 805 "name": "authz", 806 "allow_rules": [ 807 { 808 "name": "allow_authenticated", 809 "source": { 810 "principals":["*", ""] 811 } 812 }], 813 "deny_rules": [ 814 { 815 "name": "deny_policy_1", 816 "source": { 817 "principals":[ 818 "spiffe://foo.abc" 819 ] 820 } 821 }], 822 "audit_logging_options": { 823 "audit_condition": "ON_DENY", 824 "audit_loggers": [ 825 { 826 "name": "stdout_logger", 827 "is_optional": false 828 } 829 ] 830 } 831 }`, 832 wantPolicies: []*v3rbacpb.RBAC{ 833 { 834 Action: v3rbacpb.RBAC_DENY, 835 Policies: map[string]*v3rbacpb.Policy{ 836 "authz_deny_policy_1": { 837 Principals: []*v3rbacpb.Principal{ 838 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 839 Ids: []*v3rbacpb.Principal{ 840 {Identifier: &v3rbacpb.Principal_Authenticated_{ 841 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 842 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "spiffe://foo.abc"}, 843 }}, 844 }}, 845 }, 846 }}}, 847 }, 848 Permissions: []*v3rbacpb.Permission{ 849 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 850 }, 851 }, 852 }, 853 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{ 854 AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_ON_DENY, 855 LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{ 856 {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]any{}, "stdout_logger")}, 857 IsOptional: false, 858 }, 859 }, 860 }, 861 }, 862 { 863 Action: v3rbacpb.RBAC_ALLOW, 864 Policies: map[string]*v3rbacpb.Policy{ 865 "authz_allow_authenticated": { 866 Principals: []*v3rbacpb.Principal{ 867 {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{ 868 Ids: []*v3rbacpb.Principal{ 869 {Identifier: &v3rbacpb.Principal_Authenticated_{ 870 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 871 MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}}, 872 }}, 873 }}, 874 {Identifier: &v3rbacpb.Principal_Authenticated_{ 875 Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{ 876 MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""}, 877 }}, 878 }}, 879 }, 880 }}}, 881 }, 882 Permissions: []*v3rbacpb.Permission{ 883 {Rule: &v3rbacpb.Permission_Any{Any: true}}, 884 }, 885 }, 886 }, 887 AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{ 888 AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_ON_DENY, 889 LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{ 890 {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]any{}, "stdout_logger")}, 891 IsOptional: false, 892 }, 893 }, 894 }, 895 }, 896 }, 897 }, 898 "unknown field": { 899 authzPolicy: `{"random": 123}`, 900 wantErr: "failed to unmarshal policy", 901 }, 902 "missing name field": { 903 authzPolicy: `{}`, 904 wantErr: `"name" is not present`, 905 }, 906 "invalid field type": { 907 authzPolicy: `{"name": 123}`, 908 wantErr: "failed to unmarshal policy", 909 }, 910 "missing allow rules field": { 911 authzPolicy: `{"name": "authz-foo"}`, 912 wantErr: `"allow_rules" is not present`, 913 }, 914 "missing rule name field": { 915 authzPolicy: `{ 916 "name": "authz-foo", 917 "allow_rules": [{}] 918 }`, 919 wantErr: `"allow_rules" 0: "name" is not present`, 920 }, 921 "missing header key": { 922 authzPolicy: `{ 923 "name": "authz", 924 "allow_rules": [{ 925 "name": "allow_policy_1", 926 "request": {"headers":[{"key":"key-a", "values": ["value-a"]}, {}]} 927 }] 928 }`, 929 wantErr: `"allow_rules" 0: "headers" 1: "key" is not present`, 930 }, 931 "missing header values": { 932 authzPolicy: `{ 933 "name": "authz", 934 "allow_rules": [{ 935 "name": "allow_policy_1", 936 "request": {"headers":[{"key":"key-a"}]} 937 }] 938 }`, 939 wantErr: `"allow_rules" 0: "headers" 0: "values" is not present`, 940 }, 941 "unsupported header": { 942 authzPolicy: `{ 943 "name": "authz", 944 "allow_rules": [{ 945 "name": "allow_policy_1", 946 "request": {"headers":[{"key":":method", "values":["GET"]}]} 947 }] 948 }`, 949 wantErr: `"allow_rules" 0: "headers" 0: unsupported "key" :method`, 950 }, 951 "bad audit condition": { 952 authzPolicy: `{ 953 "name": "authz", 954 "allow_rules": [ 955 { 956 "name": "allow_authenticated", 957 "source": { 958 "principals":["*", ""] 959 } 960 }], 961 "audit_logging_options": { 962 "audit_condition": "ABC", 963 "audit_loggers": [ 964 { 965 "name": "stdout_logger", 966 "config": {}, 967 "is_optional": false 968 } 969 ] 970 } 971 }`, 972 wantErr: `failed to parse AuditCondition ABC`, 973 }, 974 "bad audit logger config": { 975 authzPolicy: `{ 976 "name": "authz", 977 "allow_rules": [ 978 { 979 "name": "allow_authenticated", 980 "source": { 981 "principals":["*", ""] 982 } 983 }], 984 "audit_logging_options": { 985 "audit_condition": "NONE", 986 "audit_loggers": [ 987 { 988 "name": "stdout_logger", 989 "config": "abc", 990 "is_optional": false 991 } 992 ] 993 } 994 }`, 995 wantErr: `failed to unmarshal policy`, 996 }, 997 "missing audit logger name": { 998 authzPolicy: `{ 999 "name": "authz", 1000 "allow_rules": [ 1001 { 1002 "name": "allow_authenticated", 1003 "source": { 1004 "principals":["*", ""] 1005 } 1006 }], 1007 "audit_logging_options": { 1008 "audit_condition": "NONE", 1009 "audit_loggers": [ 1010 { 1011 "name": "", 1012 "config": {}, 1013 "is_optional": false 1014 } 1015 ] 1016 } 1017 }`, 1018 wantErr: `missing required field: name`, 1019 }, 1020 } 1021 for name, test := range tests { 1022 t.Run(name, func(t *testing.T) { 1023 gotPolicies, gotPolicyName, gotErr := translatePolicy(test.authzPolicy) 1024 if gotErr != nil && !strings.HasPrefix(gotErr.Error(), test.wantErr) { 1025 t.Fatalf("unexpected error\nwant:%v\ngot:%v", test.wantErr, gotErr) 1026 } 1027 if diff := cmp.Diff(gotPolicies, test.wantPolicies, protocmp.Transform()); diff != "" { 1028 t.Fatalf("unexpected policy\ndiff (-want +got):\n%s", diff) 1029 } 1030 if test.wantPolicyName != "" && gotPolicyName != test.wantPolicyName { 1031 t.Fatalf("unexpected policy name\nwant:%v\ngot:%v", test.wantPolicyName, gotPolicyName) 1032 } 1033 }) 1034 } 1035 } 1036 1037 func anyPbHelper(t *testing.T, in map[string]any, name string) *anypb.Any { 1038 t.Helper() 1039 pb, err := structpb.NewStruct(in) 1040 typedStruct := &v1xdsudpatypepb.TypedStruct{ 1041 TypeUrl: typeURLPrefix + name, 1042 Value: pb, 1043 } 1044 if err != nil { 1045 t.Fatal(err) 1046 } 1047 customConfig, err := anypb.New(typedStruct) 1048 if err != nil { 1049 t.Fatal(err) 1050 } 1051 return customConfig 1052 }