From 48424314f32a33ff92536b88e4960c7e55570bbb Mon Sep 17 00:00:00 2001 From: hectorhammett Date: Wed, 24 Jun 2026 21:47:09 +0000 Subject: [PATCH 1/6] Add the PQC conformance tests --- .../conformance-tests-gax-showcase.yaml | 19 ++-- Gax/tests/Conformance/PqcShowcaseTest.php | 100 ++++++++++++++++++ 2 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 Gax/tests/Conformance/PqcShowcaseTest.php diff --git a/.github/workflows/conformance-tests-gax-showcase.yaml b/.github/workflows/conformance-tests-gax-showcase.yaml index 7962003b4d2e..1d20ae21ec7c 100644 --- a/.github/workflows/conformance-tests-gax-showcase.yaml +++ b/.github/workflows/conformance-tests-gax-showcase.yaml @@ -10,7 +10,7 @@ jobs: gapic-showcase: runs-on: ubuntu-latest env: - GAPIC_SHOWCASE_VERSION: 0.36.2 + GAPIC_SHOWCASE_VERSION: 0.40.0 OS: linux ARCH: amd64 name: GAPIC Showcase Conformance Tests @@ -21,13 +21,21 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.1' + php-version: '8.2' extensions: grpc - - name: Install and run GAPIC Showcase + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '>=1.26' + + - name: Install GAPIC Showcase from Branch run: | - curl -L https://github.com/googleapis/gapic-showcase/releases/download/v${GAPIC_SHOWCASE_VERSION}/gapic-showcase-${GAPIC_SHOWCASE_VERSION}-${OS}-${ARCH}.tar.gz | tar -zx - ./gapic-showcase run & + go install github.com/googleapis/gapic-showcase@feat-pqc-tls + + - name: Run the GAPIC showcase server + run: | + gapic-showcase run --port :7469 --tls --ca-cert-output-file showcase.pem & sleep 5 - name: Install dependencies run: | @@ -35,4 +43,3 @@ jobs: - name: Run PHPUnit run: Gax/vendor/bin/phpunit -c Gax/phpunit-conformance.xml.dist - diff --git a/Gax/tests/Conformance/PqcShowcaseTest.php b/Gax/tests/Conformance/PqcShowcaseTest.php new file mode 100644 index 000000000000..5697caa2cf12 --- /dev/null +++ b/Gax/tests/Conformance/PqcShowcaseTest.php @@ -0,0 +1,100 @@ +fail('Could not read showcase.pem'); + } + + $grpcTransport = GrpcTransport::build($host, [ + 'stubOpts' => [ + 'credentials' => ChannelCredentials::createSsl($pemContents) + ] + ]); + + // REST Configuration + $restConfigPath = __DIR__ . '/src/V1beta1/resources/echo_rest_client_config.php'; + + $requestBuilder = new RequestBuilder($host, $restConfigPath); + $guzzleClient = new Client([ + 'verify' => $pemPath + ]); + $httpHandler = HttpHandlerFactory::build($guzzleClient); + $restTransport = new RestTransport($requestBuilder, [$httpHandler, 'async']); + + return [[$grpcTransport], [$restTransport]]; + } + + /** @dataProvider provideTransport */ + public function testPqc(TransportInterface $transport): void + { + $expected = 'This is a test'; + $expectedGroup = 'X25519MLKEM768'; + $expectedVersion = 'TLS 1.3'; + $responseHeaders = null; + $metadataCallback = function (array $metadata) use (&$responseHeaders) { + $responseHeaders = $metadata; + }; + + $echoClient = new EchoClient([ + 'credentials' => new InsecureCredentialsWrapper(), + 'transport' => $transport + ]); + + $echoRequest = new EchoRequest(); + $echoRequest->setContent($expected); + $response = $echoClient->echo($echoRequest, [ + 'metadataCallback' => $metadataCallback + ]); + + $this->assertEquals($expected, $response->getContent()); + $this->assertNotNull($responseHeaders); + + /** @var array> $responseHeaders */ + $responseHeaders = array_change_key_case($responseHeaders, CASE_LOWER); + + $this->assertEquals($expectedVersion, $responseHeaders[self::TLS_VERSION][0]); + $this->assertEquals($expectedGroup, $responseHeaders[self::TLS_GROUP][0]); + } +} From c23d85b2b6bbe2b0c6f760a0b83cf96a57a70a61 Mon Sep 17 00:00:00 2001 From: hectorhammett Date: Wed, 22 Jul 2026 21:22:22 +0000 Subject: [PATCH 2/6] Add the pqc tests to the conformance tests --- .../conformance-tests-gax-showcase.yaml | 17 +++++------------ Gax/.gitignore | 2 ++ Gax/README.md | 10 +++++++++- Gax/tests/Conformance/PqcShowcaseTest.php | 2 -- Gax/tests/Conformance/ShowcaseTest.php | 16 +++++++++++++++- 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/.github/workflows/conformance-tests-gax-showcase.yaml b/.github/workflows/conformance-tests-gax-showcase.yaml index 1d20ae21ec7c..a0ae5657f915 100644 --- a/.github/workflows/conformance-tests-gax-showcase.yaml +++ b/.github/workflows/conformance-tests-gax-showcase.yaml @@ -10,7 +10,7 @@ jobs: gapic-showcase: runs-on: ubuntu-latest env: - GAPIC_SHOWCASE_VERSION: 0.40.0 + GAPIC_SHOWCASE_VERSION: 0.42.0 OS: linux ARCH: amd64 name: GAPIC Showcase Conformance Tests @@ -24,18 +24,11 @@ jobs: php-version: '8.2' extensions: grpc - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '>=1.26' - - - name: Install GAPIC Showcase from Branch - run: | - go install github.com/googleapis/gapic-showcase@feat-pqc-tls - - - name: Run the GAPIC showcase server + - name: Install and run GAPIC Showcase run: | - gapic-showcase run --port :7469 --tls --ca-cert-output-file showcase.pem & sleep 5 + curl -L https://github.com/googleapis/gapic-showcase/releases/download/v${GAPIC_SHOWCASE_VERSION}/gapic-showcase-${GAPIC_SHOWCASE_VERSION}-${OS}-${ARCH}.tar.gz | tar -zx + ./gapic-showcase run --port :7469 --tls --ca-cert-output-file Gax/tests/Conformance/showcase.pem & + sleep 2 - name: Install dependencies run: | diff --git a/Gax/.gitignore b/Gax/.gitignore index 94e81fe0df3a..5af2b82268b3 100644 --- a/Gax/.gitignore +++ b/Gax/.gitignore @@ -20,3 +20,5 @@ src/Jison/Parser.js # VS Code .vscode + +*.pem diff --git a/Gax/README.md b/Gax/README.md index 2f5a1d9322c9..5c10c76dcaa9 100644 --- a/Gax/README.md +++ b/Gax/README.md @@ -80,12 +80,20 @@ be found for Mac or Windows. > vendor/bin/phpunit ``` -4. Run static analysis tools +4. Run conformance tests (requires [GAPIC Showcase](https://github.com/googleapis/gapic-showcase)). + + ```sh + > ./gapic-showcase run --port :7469 --tls --ca-cert-output-file tests/Conformance/showcase.pem & + > vendor/bin/phpunit -c phpunit-conformance.xml.dist + ``` + +5. Run static analysis tools ```sh > phpstan -c phpstan.neon.dist ``` + ## License BSD - See [LICENSE][] for more information. diff --git a/Gax/tests/Conformance/PqcShowcaseTest.php b/Gax/tests/Conformance/PqcShowcaseTest.php index 5697caa2cf12..a05c3f76618f 100644 --- a/Gax/tests/Conformance/PqcShowcaseTest.php +++ b/Gax/tests/Conformance/PqcShowcaseTest.php @@ -71,7 +71,6 @@ public function testPqc(TransportInterface $transport): void { $expected = 'This is a test'; $expectedGroup = 'X25519MLKEM768'; - $expectedVersion = 'TLS 1.3'; $responseHeaders = null; $metadataCallback = function (array $metadata) use (&$responseHeaders) { $responseHeaders = $metadata; @@ -94,7 +93,6 @@ public function testPqc(TransportInterface $transport): void /** @var array> $responseHeaders */ $responseHeaders = array_change_key_case($responseHeaders, CASE_LOWER); - $this->assertEquals($expectedVersion, $responseHeaders[self::TLS_VERSION][0]); $this->assertEquals($expectedGroup, $responseHeaders[self::TLS_GROUP][0]); } } diff --git a/Gax/tests/Conformance/ShowcaseTest.php b/Gax/tests/Conformance/ShowcaseTest.php index e5f9b22baa3c..529424519103 100644 --- a/Gax/tests/Conformance/ShowcaseTest.php +++ b/Gax/tests/Conformance/ShowcaseTest.php @@ -36,10 +36,24 @@ final class ShowcaseTest extends TestCase { public function provideTransport() { + $pemPath = __DIR__ . '/showcase.pem'; + $host = 'localhost:7469'; + + // gRPC Configuration + $pemContents = file_get_contents($pemPath); + + if (!$pemContents) { + $this->fail('Could not read showcase.pem'); + } + // build gRPC transport $grpc = GrpcTransport::build( 'localhost:7469', - ['stubOpts' => ['credentials' => ChannelCredentials::createInsecure()]] + [ + 'stubOpts' => [ + 'credentials' => ChannelCredentials::createSsl($pemContents) + ] + ] ); // build REST transport From 44da8323c88c4158ddc4cf0148f47f57e73877b4 Mon Sep 17 00:00:00 2001 From: hectorhammett Date: Wed, 22 Jul 2026 22:02:35 +0000 Subject: [PATCH 3/6] Add the grpc 1.83 extension to the conformance test --- .github/workflows/conformance-tests-gax-showcase.yaml | 2 +- Gax/tests/Conformance/ShowcaseTest.php | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/conformance-tests-gax-showcase.yaml b/.github/workflows/conformance-tests-gax-showcase.yaml index a0ae5657f915..2030178cb6ca 100644 --- a/.github/workflows/conformance-tests-gax-showcase.yaml +++ b/.github/workflows/conformance-tests-gax-showcase.yaml @@ -22,7 +22,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: '8.2' - extensions: grpc + extensions: grpc-1.83.0 - name: Install and run GAPIC Showcase run: | diff --git a/Gax/tests/Conformance/ShowcaseTest.php b/Gax/tests/Conformance/ShowcaseTest.php index 529424519103..921d79d91c2b 100644 --- a/Gax/tests/Conformance/ShowcaseTest.php +++ b/Gax/tests/Conformance/ShowcaseTest.php @@ -22,7 +22,7 @@ use Google\ApiCore\ApiException; use Google\ApiCore\KnownTypes; use Google\ApiCore\InsecureCredentialsWrapper; -use Google\ApiCore\InsecureRequestBuilder; +use Google\ApiCore\RequestBuilder; use Google\ApiCore\Transport\GrpcTransport; use Google\ApiCore\Transport\TransportInterface; use Google\ApiCore\Transport\RestTransport; @@ -31,6 +31,7 @@ use Google\Showcase\V1beta1\Client\EchoClient; use Google\Showcase\V1beta1\FailEchoWithDetailsRequest; use Grpc\ChannelCredentials; +use GuzzleHttp\Client; final class ShowcaseTest extends TestCase { @@ -58,8 +59,9 @@ public function provideTransport() // build REST transport $restConfigPath = __DIR__ . '/src/V1beta1/resources/echo_rest_client_config.php'; - $requestBuilder = new InsecureRequestBuilder('localhost:7469', $restConfigPath); - $httpHandler = HttpHandlerFactory::build(); + $requestBuilder = new RequestBuilder('localhost:7469', $restConfigPath); + $guzzleClient = new Client(['verify' => $pemPath]); + $httpHandler = HttpHandlerFactory::build($guzzleClient); $rest = new RestTransport($requestBuilder, [$httpHandler, 'async']); return [[$grpc], [$rest]]; From 1224e89676bccaec7d7f3d7c1b7777a46fab0009 Mon Sep 17 00:00:00 2001 From: hectorhammett Date: Thu, 23 Jul 2026 18:41:01 +0000 Subject: [PATCH 4/6] Add an extra check for outdated SSL Rest transport combination --- Gax/tests/Conformance/PqcShowcaseTest.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Gax/tests/Conformance/PqcShowcaseTest.php b/Gax/tests/Conformance/PqcShowcaseTest.php index a05c3f76618f..9f2d4bb0b2dc 100644 --- a/Gax/tests/Conformance/PqcShowcaseTest.php +++ b/Gax/tests/Conformance/PqcShowcaseTest.php @@ -92,7 +92,14 @@ public function testPqc(TransportInterface $transport): void /** @var array> $responseHeaders */ $responseHeaders = array_change_key_case($responseHeaders, CASE_LOWER); - - $this->assertEquals($expectedGroup, $responseHeaders[self::TLS_GROUP][0]); + $negotiatedGroup = $responseHeaders[self::TLS_GROUP][0]; + + if ($transport instanceof GrpcTransport) { + // gRPC must ALWAYS negotiate PQC + $this->assertEquals($expectedGroup, $negotiatedGroup); + } else { + // REST uses host system OpenSSL (X25519MLKEM768 when PQC is available, or X25519 fallback) + $this->assertContains($negotiatedGroup, [$expectedGroup, 'X25519']); + } } } From 4790f8f021eea54889e6f568b0d90003a9817ea0 Mon Sep 17 00:00:00 2001 From: hectorhammett Date: Thu, 23 Jul 2026 19:14:14 +0000 Subject: [PATCH 5/6] Update the showcase yaml to pin actions to a specific hash --- .github/workflows/conformance-tests-gax-showcase.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/conformance-tests-gax-showcase.yaml b/.github/workflows/conformance-tests-gax-showcase.yaml index 2030178cb6ca..0e25a2bcfff7 100644 --- a/.github/workflows/conformance-tests-gax-showcase.yaml +++ b/.github/workflows/conformance-tests-gax-showcase.yaml @@ -16,10 +16,10 @@ jobs: name: GAPIC Showcase Conformance Tests steps: - name: Checkout code - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7.0.1 - name: Setup PHP - uses: shivammathur/setup-php@v2 + uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 #v2.37.2 with: php-version: '8.2' extensions: grpc-1.83.0 From 4fb4d3630c4ca9cd86572f26c45f06bfd6395156 Mon Sep 17 00:00:00 2001 From: hectorhammett Date: Thu, 23 Jul 2026 20:31:38 +0000 Subject: [PATCH 6/6] Update the showcase yaml file to comply with zizmor --- .github/workflows/conformance-tests-gax-showcase.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/conformance-tests-gax-showcase.yaml b/.github/workflows/conformance-tests-gax-showcase.yaml index 0e25a2bcfff7..604ca4e515e1 100644 --- a/.github/workflows/conformance-tests-gax-showcase.yaml +++ b/.github/workflows/conformance-tests-gax-showcase.yaml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7.0.1 - name: Setup PHP - uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 #v2.37.2 + uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 #2.37.2 with: php-version: '8.2' extensions: grpc-1.83.0