google.golang.org/grpc@v1.72.2/authz/grpc_authz_end2end_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_test 20 21 import ( 22 "context" 23 "crypto/tls" 24 "crypto/x509" 25 "io" 26 "os" 27 "testing" 28 "time" 29 30 "google.golang.org/grpc" 31 "google.golang.org/grpc/authz" 32 "google.golang.org/grpc/codes" 33 "google.golang.org/grpc/credentials" 34 "google.golang.org/grpc/credentials/insecure" 35 "google.golang.org/grpc/internal/grpctest" 36 "google.golang.org/grpc/internal/stubserver" 37 "google.golang.org/grpc/metadata" 38 "google.golang.org/grpc/status" 39 "google.golang.org/grpc/testdata" 40 41 testgrpc "google.golang.org/grpc/interop/grpc_testing" 42 testpb "google.golang.org/grpc/interop/grpc_testing" 43 ) 44 45 type s struct { 46 grpctest.Tester 47 } 48 49 func Test(t *testing.T) { 50 grpctest.RunSubTests(t, s{}) 51 } 52 53 var authzTests = map[string]struct { 54 authzPolicy string 55 md metadata.MD 56 wantStatus *status.Status 57 }{ 58 "DeniesRPCMatchInDenyNoMatchInAllow": { 59 authzPolicy: `{ 60 "name": "authz", 61 "allow_rules": 62 [ 63 { 64 "name": "allow_StreamingOutputCall", 65 "request": { 66 "paths": 67 [ 68 "/grpc.testing.TestService/StreamingOutputCall" 69 ] 70 } 71 } 72 ], 73 "deny_rules": 74 [ 75 { 76 "name": "deny_TestServiceCalls", 77 "request": { 78 "paths": 79 [ 80 "/grpc.testing.TestService/*" 81 ], 82 "headers": 83 [ 84 { 85 "key": "key-abc", 86 "values": 87 [ 88 "val-abc", 89 "val-def" 90 ] 91 } 92 ] 93 } 94 } 95 ] 96 }`, 97 md: metadata.Pairs("key-abc", "val-abc"), 98 wantStatus: status.New(codes.PermissionDenied, "unauthorized RPC request rejected"), 99 }, 100 "DeniesRPCMatchInDenyAndAllow": { 101 authzPolicy: `{ 102 "name": "authz", 103 "allow_rules": 104 [ 105 { 106 "name": "allow_all", 107 "request": { 108 "paths": 109 [ 110 "*" 111 ] 112 } 113 } 114 ], 115 "deny_rules": 116 [ 117 { 118 "name": "deny_all", 119 "request": { 120 "paths": 121 [ 122 "*" 123 ] 124 } 125 } 126 ] 127 }`, 128 wantStatus: status.New(codes.PermissionDenied, "unauthorized RPC request rejected"), 129 }, 130 "AllowsRPCNoMatchInDenyMatchInAllow": { 131 authzPolicy: `{ 132 "name": "authz", 133 "allow_rules": 134 [ 135 { 136 "name": "allow_all" 137 } 138 ], 139 "deny_rules": 140 [ 141 { 142 "name": "deny_TestServiceCalls", 143 "request": { 144 "paths": 145 [ 146 "/grpc.testing.TestService/UnaryCall", 147 "/grpc.testing.TestService/StreamingInputCall" 148 ], 149 "headers": 150 [ 151 { 152 "key": "key-abc", 153 "values": 154 [ 155 "val-abc", 156 "val-def" 157 ] 158 } 159 ] 160 } 161 } 162 ] 163 }`, 164 md: metadata.Pairs("key-xyz", "val-xyz"), 165 wantStatus: status.New(codes.OK, ""), 166 }, 167 "DeniesRPCNoMatchInDenyAndAllow": { 168 authzPolicy: `{ 169 "name": "authz", 170 "allow_rules": 171 [ 172 { 173 "name": "allow_some_user", 174 "source": { 175 "principals": 176 [ 177 "some_user" 178 ] 179 } 180 } 181 ], 182 "deny_rules": 183 [ 184 { 185 "name": "deny_StreamingOutputCall", 186 "request": { 187 "paths": 188 [ 189 "/grpc.testing.TestService/StreamingOutputCall" 190 ] 191 } 192 } 193 ] 194 }`, 195 wantStatus: status.New(codes.PermissionDenied, "unauthorized RPC request rejected"), 196 }, 197 "AllowsRPCEmptyDenyMatchInAllow": { 198 authzPolicy: `{ 199 "name": "authz", 200 "allow_rules": 201 [ 202 { 203 "name": "allow_UnaryCall", 204 "request": 205 { 206 "paths": 207 [ 208 "/grpc.testing.TestService/UnaryCall" 209 ] 210 } 211 }, 212 { 213 "name": "allow_StreamingInputCall", 214 "request": 215 { 216 "paths": 217 [ 218 "/grpc.testing.TestService/StreamingInputCall" 219 ] 220 } 221 } 222 ] 223 }`, 224 wantStatus: status.New(codes.OK, ""), 225 }, 226 "DeniesRPCEmptyDenyNoMatchInAllow": { 227 authzPolicy: `{ 228 "name": "authz", 229 "allow_rules": 230 [ 231 { 232 "name": "allow_StreamingOutputCall", 233 "request": 234 { 235 "paths": 236 [ 237 "/grpc.testing.TestService/StreamingOutputCall" 238 ] 239 } 240 } 241 ] 242 }`, 243 wantStatus: status.New(codes.PermissionDenied, "unauthorized RPC request rejected"), 244 }, 245 "DeniesRPCRequestWithPrincipalsFieldOnUnauthenticatedConnection": { 246 authzPolicy: `{ 247 "name": "authz", 248 "allow_rules": 249 [ 250 { 251 "name": "allow_authenticated", 252 "source": { 253 "principals": ["*", ""] 254 } 255 } 256 ] 257 }`, 258 wantStatus: status.New(codes.PermissionDenied, "unauthorized RPC request rejected"), 259 }, 260 "DeniesRPCRequestNoMatchInAllowFailsPresenceMatch": { 261 authzPolicy: `{ 262 "name": "authz", 263 "allow_rules": 264 [ 265 { 266 "name": "allow_TestServiceCalls", 267 "request": { 268 "paths": 269 [ 270 "/grpc.testing.TestService/*" 271 ], 272 "headers": 273 [ 274 { 275 "key": "key-abc", 276 "values": 277 [ 278 "*" 279 ] 280 } 281 ] 282 } 283 } 284 ] 285 }`, 286 md: metadata.Pairs("key-abc", ""), 287 wantStatus: status.New(codes.PermissionDenied, "unauthorized RPC request rejected"), 288 }, 289 } 290 291 func (s) TestStaticPolicyEnd2End(t *testing.T) { 292 for name, test := range authzTests { 293 t.Run(name, func(t *testing.T) { 294 // Start a gRPC server with gRPC authz unary and stream server interceptors. 295 i, _ := authz.NewStatic(test.authzPolicy) 296 297 stub := &stubserver.StubServer{ 298 UnaryCallF: func(ctx context.Context, req *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { 299 return &testpb.SimpleResponse{}, nil 300 }, 301 StreamingInputCallF: func(stream testgrpc.TestService_StreamingInputCallServer) error { 302 for { 303 _, err := stream.Recv() 304 if err == io.EOF { 305 return stream.SendAndClose(&testpb.StreamingInputCallResponse{}) 306 } 307 if err != nil { 308 return err 309 } 310 } 311 }, 312 S: grpc.NewServer(grpc.ChainUnaryInterceptor(i.UnaryInterceptor), grpc.ChainStreamInterceptor(i.StreamInterceptor)), 313 } 314 stubserver.StartTestService(t, stub) 315 defer stub.Stop() 316 317 // Establish a connection to the server. 318 cc, err := grpc.NewClient(stub.Address, grpc.WithTransportCredentials(insecure.NewCredentials())) 319 if err != nil { 320 t.Fatalf("grpc.NewClient(%v) failed: %v", stub.Address, err) 321 } 322 defer cc.Close() 323 client := testgrpc.NewTestServiceClient(cc) 324 325 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 326 defer cancel() 327 ctx = metadata.NewOutgoingContext(ctx, test.md) 328 329 // Verifying authorization decision for Unary RPC. 330 _, err = client.UnaryCall(ctx, &testpb.SimpleRequest{}) 331 if got := status.Convert(err); got.Code() != test.wantStatus.Code() || got.Message() != test.wantStatus.Message() { 332 t.Fatalf("[UnaryCall] error want:{%v} got:{%v}", test.wantStatus.Err(), got.Err()) 333 } 334 335 // Verifying authorization decision for Streaming RPC. 336 stream, err := client.StreamingInputCall(ctx) 337 if err != nil { 338 t.Fatalf("failed StreamingInputCall err: %v", err) 339 } 340 req := &testpb.StreamingInputCallRequest{ 341 Payload: &testpb.Payload{ 342 Body: []byte("hi"), 343 }, 344 } 345 if err := stream.Send(req); err != nil && err != io.EOF { 346 t.Fatalf("failed stream.Send err: %v", err) 347 } 348 _, err = stream.CloseAndRecv() 349 if got := status.Convert(err); got.Code() != test.wantStatus.Code() || got.Message() != test.wantStatus.Message() { 350 t.Fatalf("[StreamingCall] error want:{%v} got:{%v}", test.wantStatus.Err(), got.Err()) 351 } 352 }) 353 } 354 } 355 356 func (s) TestAllowsRPCRequestWithPrincipalsFieldOnTLSAuthenticatedConnection(t *testing.T) { 357 authzPolicy := `{ 358 "name": "authz", 359 "allow_rules": 360 [ 361 { 362 "name": "allow_authenticated", 363 "source": { 364 "principals": ["*", ""] 365 } 366 } 367 ] 368 }` 369 // Start a gRPC server with gRPC authz unary server interceptor. 370 i, _ := authz.NewStatic(authzPolicy) 371 creds, err := credentials.NewServerTLSFromFile(testdata.Path("x509/server1_cert.pem"), testdata.Path("x509/server1_key.pem")) 372 if err != nil { 373 t.Fatalf("failed to generate credentials: %v", err) 374 } 375 376 stub := &stubserver.StubServer{ 377 UnaryCallF: func(ctx context.Context, req *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { 378 return &testpb.SimpleResponse{}, nil 379 }, 380 S: grpc.NewServer(grpc.Creds(creds), grpc.ChainUnaryInterceptor(i.UnaryInterceptor)), 381 } 382 stubserver.StartTestService(t, stub) 383 defer stub.S.Stop() 384 385 // Establish a connection to the server. 386 creds, err = credentials.NewClientTLSFromFile(testdata.Path("x509/server_ca_cert.pem"), "x.test.example.com") 387 if err != nil { 388 t.Fatalf("failed to load credentials: %v", err) 389 } 390 cc, err := grpc.NewClient(stub.Address, grpc.WithTransportCredentials(creds)) 391 if err != nil { 392 t.Fatalf("grpc.NewClient(%v) failed: %v", stub.Address, err) 393 } 394 defer cc.Close() 395 client := testgrpc.NewTestServiceClient(cc) 396 397 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 398 defer cancel() 399 400 // Verifying authorization decision. 401 if _, err = client.UnaryCall(ctx, &testpb.SimpleRequest{}); err != nil { 402 t.Fatalf("client.UnaryCall(_, _) = %v; want nil", err) 403 } 404 } 405 406 func (s) TestAllowsRPCRequestWithPrincipalsFieldOnMTLSAuthenticatedConnection(t *testing.T) { 407 authzPolicy := `{ 408 "name": "authz", 409 "allow_rules": 410 [ 411 { 412 "name": "allow_authenticated", 413 "source": { 414 "principals": ["*", ""] 415 } 416 } 417 ] 418 }` 419 // Start a gRPC server with gRPC authz unary server interceptor. 420 i, _ := authz.NewStatic(authzPolicy) 421 cert, err := tls.LoadX509KeyPair(testdata.Path("x509/server1_cert.pem"), testdata.Path("x509/server1_key.pem")) 422 if err != nil { 423 t.Fatalf("tls.LoadX509KeyPair(x509/server1_cert.pem, x509/server1_key.pem) failed: %v", err) 424 } 425 ca, err := os.ReadFile(testdata.Path("x509/client_ca_cert.pem")) 426 if err != nil { 427 t.Fatalf("os.ReadFile(x509/client_ca_cert.pem) failed: %v", err) 428 } 429 certPool := x509.NewCertPool() 430 if !certPool.AppendCertsFromPEM(ca) { 431 t.Fatal("failed to append certificates") 432 } 433 creds := credentials.NewTLS(&tls.Config{ 434 ClientAuth: tls.RequireAndVerifyClientCert, 435 Certificates: []tls.Certificate{cert}, 436 ClientCAs: certPool, 437 }) 438 stub := &stubserver.StubServer{ 439 UnaryCallF: func(ctx context.Context, req *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { 440 return &testpb.SimpleResponse{}, nil 441 }, 442 S: grpc.NewServer(grpc.Creds(creds), grpc.ChainUnaryInterceptor(i.UnaryInterceptor)), 443 } 444 stubserver.StartTestService(t, stub) 445 defer stub.Stop() 446 447 // Establish a connection to the server. 448 cert, err = tls.LoadX509KeyPair(testdata.Path("x509/client1_cert.pem"), testdata.Path("x509/client1_key.pem")) 449 if err != nil { 450 t.Fatalf("tls.LoadX509KeyPair(x509/client1_cert.pem, x509/client1_key.pem) failed: %v", err) 451 } 452 ca, err = os.ReadFile(testdata.Path("x509/server_ca_cert.pem")) 453 if err != nil { 454 t.Fatalf("os.ReadFile(x509/server_ca_cert.pem) failed: %v", err) 455 } 456 roots := x509.NewCertPool() 457 if !roots.AppendCertsFromPEM(ca) { 458 t.Fatal("failed to append certificates") 459 } 460 creds = credentials.NewTLS(&tls.Config{ 461 Certificates: []tls.Certificate{cert}, 462 RootCAs: roots, 463 ServerName: "x.test.example.com", 464 }) 465 cc, err := grpc.NewClient(stub.Address, grpc.WithTransportCredentials(creds)) 466 if err != nil { 467 t.Fatalf("grpc.NewClient(%v) failed: %v", stub.Address, err) 468 } 469 defer cc.Close() 470 client := testgrpc.NewTestServiceClient(cc) 471 472 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 473 defer cancel() 474 475 // Verifying authorization decision. 476 if _, err = client.UnaryCall(ctx, &testpb.SimpleRequest{}); err != nil { 477 t.Fatalf("client.UnaryCall(_, _) = %v; want nil", err) 478 } 479 } 480 481 func (s) TestFileWatcherEnd2End(t *testing.T) { 482 for name, test := range authzTests { 483 t.Run(name, func(t *testing.T) { 484 file := createTmpPolicyFile(t, name, []byte(test.authzPolicy)) 485 i, _ := authz.NewFileWatcher(file, 1*time.Second) 486 defer i.Close() 487 488 stub := &stubserver.StubServer{ 489 UnaryCallF: func(ctx context.Context, req *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { 490 return &testpb.SimpleResponse{}, nil 491 }, 492 StreamingInputCallF: func(stream testgrpc.TestService_StreamingInputCallServer) error { 493 for { 494 _, err := stream.Recv() 495 if err == io.EOF { 496 return stream.SendAndClose(&testpb.StreamingInputCallResponse{}) 497 } 498 if err != nil { 499 return err 500 } 501 } 502 }, 503 // Start a gRPC server with gRPC authz unary and stream server interceptors. 504 S: grpc.NewServer(grpc.ChainUnaryInterceptor(i.UnaryInterceptor), grpc.ChainStreamInterceptor(i.StreamInterceptor)), 505 } 506 stubserver.StartTestService(t, stub) 507 defer stub.Stop() 508 509 // Establish a connection to the server. 510 cc, err := grpc.NewClient(stub.Address, grpc.WithTransportCredentials(insecure.NewCredentials())) 511 if err != nil { 512 t.Fatalf("grpc.NewClient(%v) failed: %v", stub.Address, err) 513 } 514 defer cc.Close() 515 client := testgrpc.NewTestServiceClient(cc) 516 517 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 518 defer cancel() 519 ctx = metadata.NewOutgoingContext(ctx, test.md) 520 521 // Verifying authorization decision for Unary RPC. 522 _, err = client.UnaryCall(ctx, &testpb.SimpleRequest{}) 523 if got := status.Convert(err); got.Code() != test.wantStatus.Code() || got.Message() != test.wantStatus.Message() { 524 t.Fatalf("[UnaryCall] error want:{%v} got:{%v}", test.wantStatus.Err(), got.Err()) 525 } 526 527 // Verifying authorization decision for Streaming RPC. 528 stream, err := client.StreamingInputCall(ctx) 529 if err != nil { 530 t.Fatalf("failed StreamingInputCall : %v", err) 531 } 532 req := &testpb.StreamingInputCallRequest{ 533 Payload: &testpb.Payload{ 534 Body: []byte("hi"), 535 }, 536 } 537 if err := stream.Send(req); err != nil && err != io.EOF { 538 t.Fatalf("failed stream.Send : %v", err) 539 } 540 _, err = stream.CloseAndRecv() 541 if got := status.Convert(err); got.Code() != test.wantStatus.Code() || got.Message() != test.wantStatus.Message() { 542 t.Fatalf("[StreamingCall] error want:{%v} got:{%v}", test.wantStatus.Err(), got.Err()) 543 } 544 }) 545 } 546 } 547 548 func retryUntil(ctx context.Context, tsc testgrpc.TestServiceClient, want *status.Status) (lastErr error) { 549 for ctx.Err() == nil { 550 _, lastErr = tsc.UnaryCall(ctx, &testpb.SimpleRequest{}) 551 if s := status.Convert(lastErr); s.Code() == want.Code() && s.Message() == want.Message() { 552 return nil 553 } 554 time.Sleep(20 * time.Millisecond) 555 } 556 return lastErr 557 } 558 559 func (s) TestFileWatcher_ValidPolicyRefresh(t *testing.T) { 560 valid1 := authzTests["DeniesRPCMatchInDenyAndAllow"] 561 file := createTmpPolicyFile(t, "valid_policy_refresh", []byte(valid1.authzPolicy)) 562 i, _ := authz.NewFileWatcher(file, 100*time.Millisecond) 563 defer i.Close() 564 565 stub := &stubserver.StubServer{ 566 UnaryCallF: func(ctx context.Context, req *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { 567 return &testpb.SimpleResponse{}, nil 568 }, 569 // Start a gRPC server with gRPC authz unary server interceptor. 570 S: grpc.NewServer(grpc.ChainUnaryInterceptor(i.UnaryInterceptor)), 571 } 572 stubserver.StartTestService(t, stub) 573 defer stub.Stop() 574 575 // Establish a connection to the server. 576 cc, err := grpc.NewClient(stub.Address, grpc.WithTransportCredentials(insecure.NewCredentials())) 577 if err != nil { 578 t.Fatalf("grpc.NewClient(%v) failed: %v", stub.Address, err) 579 } 580 defer cc.Close() 581 client := testgrpc.NewTestServiceClient(cc) 582 583 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 584 defer cancel() 585 586 // Verifying authorization decision. 587 _, err = client.UnaryCall(ctx, &testpb.SimpleRequest{}) 588 if got := status.Convert(err); got.Code() != valid1.wantStatus.Code() || got.Message() != valid1.wantStatus.Message() { 589 t.Fatalf("client.UnaryCall(_, _) = %v; want = %v", got.Err(), valid1.wantStatus.Err()) 590 } 591 592 // Rewrite the file with a different valid authorization policy. 593 valid2 := authzTests["AllowsRPCEmptyDenyMatchInAllow"] 594 if err := os.WriteFile(file, []byte(valid2.authzPolicy), os.ModePerm); err != nil { 595 t.Fatalf("os.WriteFile(%q) failed: %v", file, err) 596 } 597 598 // Verifying authorization decision. 599 if got := retryUntil(ctx, client, valid2.wantStatus); got != nil { 600 t.Fatalf("client.UnaryCall(_, _) = %v; want = %v", got, valid2.wantStatus.Err()) 601 } 602 } 603 604 func (s) TestFileWatcher_InvalidPolicySkipReload(t *testing.T) { 605 valid := authzTests["DeniesRPCMatchInDenyAndAllow"] 606 file := createTmpPolicyFile(t, "invalid_policy_skip_reload", []byte(valid.authzPolicy)) 607 i, _ := authz.NewFileWatcher(file, 20*time.Millisecond) 608 defer i.Close() 609 610 stub := &stubserver.StubServer{ 611 UnaryCallF: func(ctx context.Context, req *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { 612 return &testpb.SimpleResponse{}, nil 613 }, 614 // Start a gRPC server with gRPC authz unary server interceptors. 615 S: grpc.NewServer(grpc.ChainUnaryInterceptor(i.UnaryInterceptor)), 616 } 617 stubserver.StartTestService(t, stub) 618 defer stub.Stop() 619 620 // Establish a connection to the server. 621 cc, err := grpc.NewClient(stub.Address, grpc.WithTransportCredentials(insecure.NewCredentials())) 622 if err != nil { 623 t.Fatalf("grpc.NewClient(%v) failed: %v", stub.Address, err) 624 } 625 defer cc.Close() 626 client := testgrpc.NewTestServiceClient(cc) 627 628 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 629 defer cancel() 630 631 // Verifying authorization decision. 632 _, err = client.UnaryCall(ctx, &testpb.SimpleRequest{}) 633 if got := status.Convert(err); got.Code() != valid.wantStatus.Code() || got.Message() != valid.wantStatus.Message() { 634 t.Fatalf("client.UnaryCall(_, _) = %v; want = %v", got.Err(), valid.wantStatus.Err()) 635 } 636 637 // Skips the invalid policy update, and continues to use the valid policy. 638 if err := os.WriteFile(file, []byte("{}"), os.ModePerm); err != nil { 639 t.Fatalf("os.WriteFile(%q) failed: %v", file, err) 640 } 641 642 // Wait 40 ms for background go routine to read updated files. 643 time.Sleep(40 * time.Millisecond) 644 645 // Verifying authorization decision. 646 _, err = client.UnaryCall(ctx, &testpb.SimpleRequest{}) 647 if got := status.Convert(err); got.Code() != valid.wantStatus.Code() || got.Message() != valid.wantStatus.Message() { 648 t.Fatalf("client.UnaryCall(_, _) = %v; want = %v", got.Err(), valid.wantStatus.Err()) 649 } 650 } 651 652 func (s) TestFileWatcher_RecoversFromReloadFailure(t *testing.T) { 653 valid1 := authzTests["DeniesRPCMatchInDenyAndAllow"] 654 file := createTmpPolicyFile(t, "recovers_from_reload_failure", []byte(valid1.authzPolicy)) 655 i, _ := authz.NewFileWatcher(file, 100*time.Millisecond) 656 defer i.Close() 657 658 stub := &stubserver.StubServer{ 659 UnaryCallF: func(ctx context.Context, req *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { 660 return &testpb.SimpleResponse{}, nil 661 }, 662 S: grpc.NewServer(grpc.ChainUnaryInterceptor(i.UnaryInterceptor)), 663 } 664 stubserver.StartTestService(t, stub) 665 defer stub.Stop() 666 667 // Establish a connection to the server. 668 cc, err := grpc.NewClient(stub.Address, grpc.WithTransportCredentials(insecure.NewCredentials())) 669 if err != nil { 670 t.Fatalf("grpc.NewClient(%v) failed: %v", stub.Address, err) 671 } 672 defer cc.Close() 673 client := testgrpc.NewTestServiceClient(cc) 674 675 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 676 defer cancel() 677 678 // Verifying authorization decision. 679 _, err = client.UnaryCall(ctx, &testpb.SimpleRequest{}) 680 if got := status.Convert(err); got.Code() != valid1.wantStatus.Code() || got.Message() != valid1.wantStatus.Message() { 681 t.Fatalf("client.UnaryCall(_, _) = %v; want = %v", got.Err(), valid1.wantStatus.Err()) 682 } 683 684 // Skips the invalid policy update, and continues to use the valid policy. 685 if err := os.WriteFile(file, []byte("{}"), os.ModePerm); err != nil { 686 t.Fatalf("os.WriteFile(%q) failed: %v", file, err) 687 } 688 689 // Wait 120 ms for background go routine to read updated files. 690 time.Sleep(120 * time.Millisecond) 691 692 // Verifying authorization decision. 693 _, err = client.UnaryCall(ctx, &testpb.SimpleRequest{}) 694 if got := status.Convert(err); got.Code() != valid1.wantStatus.Code() || got.Message() != valid1.wantStatus.Message() { 695 t.Fatalf("client.UnaryCall(_, _) = %v; want = %v", got.Err(), valid1.wantStatus.Err()) 696 } 697 698 // Rewrite the file with a different valid authorization policy. 699 valid2 := authzTests["AllowsRPCEmptyDenyMatchInAllow"] 700 if err := os.WriteFile(file, []byte(valid2.authzPolicy), os.ModePerm); err != nil { 701 t.Fatalf("os.WriteFile(%q) failed: %v", file, err) 702 } 703 704 // Verifying authorization decision. 705 if got := retryUntil(ctx, client, valid2.wantStatus); got != nil { 706 t.Fatalf("client.UnaryCall(_, _) = %v; want = %v", got, valid2.wantStatus.Err()) 707 } 708 }