|
18 | 18 | namespace Google\Cloud\Storage\Tests\System; |
19 | 19 |
|
20 | 20 | use Google\Cloud\Core\Exception\BadRequestException; |
| 21 | +use Google\Cloud\Core\Exception\ServiceException; |
21 | 22 | use Google\Cloud\Storage\Bucket; |
22 | 23 |
|
23 | 24 | /** |
@@ -577,4 +578,221 @@ public function encryptionEnforcementConfigs() |
577 | 578 | ] |
578 | 579 | ]; |
579 | 580 | } |
| 581 | + |
| 582 | + /** |
| 583 | + * @group storage-ipfilter |
| 584 | + */ |
| 585 | + public function testCreateBucketWithIpFilterDisabled() |
| 586 | + { |
| 587 | + $projectId = self::getProjectId(getenv('GOOGLE_CLOUD_PHP_TESTS_KEY_PATH')); |
| 588 | + |
| 589 | + $ipFilterConfig = [ |
| 590 | + 'mode' => 'Disabled', |
| 591 | + 'publicNetworkSource' => [ |
| 592 | + 'allowedIpCidrRanges' => ['1.2.3.0/24'] |
| 593 | + ], |
| 594 | + 'vpcNetworkSources' => [ |
| 595 | + [ |
| 596 | + 'network' => 'projects/' . $projectId . '/global/networks/default', |
| 597 | + 'allowedIpCidrRanges' => ['10.0.0.0/24'] |
| 598 | + ] |
| 599 | + ], |
| 600 | + 'allowCrossOrgVpcs' => true, |
| 601 | + 'allowAllServiceAgentAccess' => true |
| 602 | + ]; |
| 603 | + |
| 604 | + $bucketName = uniqid(self::TESTING_PREFIX); |
| 605 | + $bucket = self::createBucket( |
| 606 | + self::$client, |
| 607 | + $bucketName, |
| 608 | + ['ipFilter' => $ipFilterConfig] |
| 609 | + ); |
| 610 | + |
| 611 | + $info = $bucket->info(); |
| 612 | + $this->assertArrayHasKey('ipFilter', $info); |
| 613 | + $this->assertEquals('Disabled', $info['ipFilter']['mode']); |
| 614 | + $this->assertEquals(['1.2.3.0/24'], $info['ipFilter']['publicNetworkSource']['allowedIpCidrRanges']); |
| 615 | + $this->assertEquals( |
| 616 | + 'projects/' . $projectId . '/global/networks/default', |
| 617 | + $info['ipFilter']['vpcNetworkSources'][0]['network'] |
| 618 | + ); |
| 619 | + $this->assertEquals(['10.0.0.0/24'], $info['ipFilter']['vpcNetworkSources'][0]['allowedIpCidrRanges']); |
| 620 | + $this->assertTrue($info['ipFilter']['allowAllServiceAgentAccess']); |
| 621 | + $this->assertTrue($info['ipFilter']['allowCrossOrgVpcs']); |
| 622 | + |
| 623 | + return $bucket; |
| 624 | + } |
| 625 | + |
| 626 | + /** |
| 627 | + * @depends testCreateBucketWithIpFilterDisabled |
| 628 | + * @group storage-ipfilter |
| 629 | + */ |
| 630 | + public function testUpdateIpFilterDisabled(Bucket $bucket) |
| 631 | + { |
| 632 | + $ipFilterConfig = [ |
| 633 | + 'mode' => 'Disabled', |
| 634 | + 'publicNetworkSource' => [ |
| 635 | + 'allowedIpCidrRanges' => ['1.2.3.0/24', '5.6.7.0/24'] |
| 636 | + ], |
| 637 | + 'allowAllServiceAgentAccess' => false |
| 638 | + ]; |
| 639 | + |
| 640 | + $bucket->update(['ipFilter' => $ipFilterConfig]); |
| 641 | + $info = $bucket->reload(); |
| 642 | + |
| 643 | + $this->assertArrayHasKey('ipFilter', $info); |
| 644 | + $this->assertEquals('Disabled', $info['ipFilter']['mode']); |
| 645 | + $this->assertEquals( |
| 646 | + ['1.2.3.0/24', '5.6.7.0/24'], |
| 647 | + $info['ipFilter']['publicNetworkSource']['allowedIpCidrRanges'] |
| 648 | + ); |
| 649 | + $this->assertFalse($info['ipFilter']['allowAllServiceAgentAccess']); |
| 650 | + } |
| 651 | + |
| 652 | + /** |
| 653 | + * @group storage-ipfilter |
| 654 | + */ |
| 655 | + public function testCreateBucketWithInvalidIpFilterFails() |
| 656 | + { |
| 657 | + $this->expectException(BadRequestException::class); |
| 658 | + |
| 659 | + $ipFilterConfig = [ |
| 660 | + 'mode' => 'Disabled', |
| 661 | + 'publicNetworkSource' => [ |
| 662 | + // Host bits must be zero for /24 range, so 1.2.3.4/24 is invalid |
| 663 | + 'allowedIpCidrRanges' => ['1.2.3.4/24'] |
| 664 | + ], |
| 665 | + 'allowAllServiceAgentAccess' => true |
| 666 | + ]; |
| 667 | + |
| 668 | + self::createBucket( |
| 669 | + self::$client, |
| 670 | + uniqid(self::TESTING_PREFIX), |
| 671 | + [ |
| 672 | + 'ipFilter' => $ipFilterConfig, |
| 673 | + 'retries' => 0, |
| 674 | + 'sysTestRetries' => 0 |
| 675 | + ] |
| 676 | + ); |
| 677 | + } |
| 678 | + |
| 679 | + /** |
| 680 | + * @group storage-ipfilter |
| 681 | + */ |
| 682 | + public function testUpdateBucketWithInvalidIpFilterFails() |
| 683 | + { |
| 684 | + $bucket = self::createBucket(self::$client, uniqid(self::TESTING_PREFIX)); |
| 685 | + |
| 686 | + $this->expectException(BadRequestException::class); |
| 687 | + |
| 688 | + $ipFilterConfig = [ |
| 689 | + 'mode' => 'Disabled', |
| 690 | + 'publicNetworkSource' => [ |
| 691 | + 'allowedIpCidrRanges' => ['1.2.3.4/24'] |
| 692 | + ], |
| 693 | + 'allowAllServiceAgentAccess' => true |
| 694 | + ]; |
| 695 | + |
| 696 | + $bucket->update(['ipFilter' => $ipFilterConfig]); |
| 697 | + } |
| 698 | + |
| 699 | + /** |
| 700 | + * @group storage-ipfilter |
| 701 | + */ |
| 702 | + public function testGetBucketWithIpFilter() |
| 703 | + { |
| 704 | + $bucketName = uniqid(self::TESTING_PREFIX); |
| 705 | + $ipFilterConfig = [ |
| 706 | + 'mode' => 'Disabled', |
| 707 | + 'publicNetworkSource' => [ |
| 708 | + 'allowedIpCidrRanges' => ['1.2.3.0/24'] |
| 709 | + ], |
| 710 | + 'allowAllServiceAgentAccess' => true |
| 711 | + ]; |
| 712 | + |
| 713 | + self::createBucket( |
| 714 | + self::$client, |
| 715 | + $bucketName, |
| 716 | + ['ipFilter' => $ipFilterConfig] |
| 717 | + ); |
| 718 | + |
| 719 | + $bucket = self::$client->bucket($bucketName); |
| 720 | + $info = $bucket->reload(); |
| 721 | + |
| 722 | + $this->assertArrayHasKey('ipFilter', $info); |
| 723 | + $this->assertEquals('Disabled', $info['ipFilter']['mode']); |
| 724 | + $this->assertEquals( |
| 725 | + ['1.2.3.0/24'], |
| 726 | + $info['ipFilter']['publicNetworkSource']['allowedIpCidrRanges'] |
| 727 | + ); |
| 728 | + } |
| 729 | + |
| 730 | + /** |
| 731 | + * @group storage-ipfilter |
| 732 | + * @depends testCreateBucketWithIpFilterDisabled |
| 733 | + */ |
| 734 | + public function testDeleteBucketIpFilter(Bucket $bucket) |
| 735 | + { |
| 736 | + $ipFilterConfig = [ |
| 737 | + 'mode' => 'Disabled', |
| 738 | + 'publicNetworkSource' => [ |
| 739 | + 'allowedIpCidrRanges' => [] |
| 740 | + ], |
| 741 | + 'allowAllServiceAgentAccess' => true |
| 742 | + ]; |
| 743 | + |
| 744 | + $bucket->update(['ipFilter' => $ipFilterConfig]); |
| 745 | + $info = $bucket->reload(); |
| 746 | + |
| 747 | + $this->assertArrayHasKey('ipFilter', $info); |
| 748 | + $this->assertEquals('Disabled', $info['ipFilter']['mode']); |
| 749 | + $this->assertArrayNotHasKey('allowedIpCidrRanges', $info['ipFilter']['publicNetworkSource']); |
| 750 | + } |
| 751 | + |
| 752 | + /** |
| 753 | + * @group storage-ipfilter |
| 754 | + */ |
| 755 | + public function testBucketAccessWhenEnforced() |
| 756 | + { |
| 757 | + $iam = self::$bucket->iam(); |
| 758 | + $isExempt = !empty($iam->testPermissions(['storage.buckets.exemptFromIpFilter'])); |
| 759 | + |
| 760 | + if (!$isExempt) { |
| 761 | + $this->markTestSkipped( |
| 762 | + 'Runner is not exempt from IP filter. Skipping lockout tests to prevent orphaned resources.' |
| 763 | + ); |
| 764 | + } |
| 765 | + |
| 766 | + $bucketName = uniqid(self::TESTING_PREFIX); |
| 767 | + $ipFilterConfig = [ |
| 768 | + 'mode' => 'Enabled', |
| 769 | + 'publicNetworkSource' => [ |
| 770 | + 'allowedIpCidrRanges' => ['1.1.1.1/32'] // Blocked IP for runner |
| 771 | + ], |
| 772 | + 'allowAllServiceAgentAccess' => true |
| 773 | + ]; |
| 774 | + |
| 775 | + $bucket = self::createBucket( |
| 776 | + self::$client, |
| 777 | + $bucketName, |
| 778 | + ['ipFilter' => $ipFilterConfig] |
| 779 | + ); |
| 780 | + |
| 781 | + $objectName = 'test_ip_filter.txt'; |
| 782 | + $objectContent = 'hello world'; |
| 783 | + |
| 784 | + $object = $bucket->upload($objectContent, ['name' => $objectName]); |
| 785 | + $this->assertEquals($objectContent, $object->downloadAsString()); |
| 786 | + |
| 787 | + $unauthBucket = self::$unauthenticatedClient->bucket($bucketName); |
| 788 | + $unauthObject = $unauthBucket->object($objectName); |
| 789 | + |
| 790 | + try { |
| 791 | + $unauthObject->downloadAsString(); |
| 792 | + $this->fail('Expected unauthenticated download to fail due to IP filter.'); |
| 793 | + } catch (ServiceException $e) { |
| 794 | + $this->assertEquals(403, $e->getCode()); |
| 795 | + $this->assertStringContainsString('IP filtering', $e->getMessage()); |
| 796 | + } |
| 797 | + } |
580 | 798 | } |
0 commit comments