diff --git a/.github/workflows/ci-gate.yml b/.github/workflows/ci-gate.yml index e1b247aa..c928f65a 100644 --- a/.github/workflows/ci-gate.yml +++ b/.github/workflows/ci-gate.yml @@ -26,6 +26,7 @@ jobs: javascript-node-postgres: ${{ steps.detect.outputs.javascript-node-postgres }} javascript-postgresjs: ${{ steps.detect.outputs.javascript-postgresjs }} lambda-nodejs: ${{ steps.detect.outputs.lambda-nodejs }} + php-authentication: ${{ steps.detect.outputs.php-authentication }} python-asyncpg: ${{ steps.detect.outputs.python-asyncpg }} python-cm: ${{ steps.detect.outputs.python-cm }} python-psycopg2: ${{ steps.detect.outputs.python-psycopg2 }} @@ -56,6 +57,7 @@ jobs: 'javascript-node-postgres': ['javascript/node-postgres/', '.github/workflows/javascript-node-postgres-integ-tests.yml'], 'javascript-postgresjs': ['javascript/postgres-js/', '.github/workflows/javascript-postgresjs-integ-tests.yml'], 'lambda-nodejs': ['lambda/', '.github/workflows/lambda-nodejs-integ-tests.yml'], + 'php-authentication': ['php/authentication/', '.github/workflows/php-authentication-integ-tests.yml'], 'python-asyncpg': ['python/asyncpg/', '.github/workflows/python-asyncpg-integ-tests.yml'], 'python-cm': ['python/cluster_management/', '.github/workflows/python-cm-integ-tests.yml'], 'python-psycopg2': ['python/psycopg2/', '.github/workflows/python-psycopg2-integ-tests.yml'], @@ -217,6 +219,14 @@ jobs: permissions: id-token: write # required by aws-actions/configure-aws-credentials + php-authentication: + needs: changes + if: needs.changes.outputs.php-authentication == 'true' + uses: ./.github/workflows/php-authentication-integ-tests.yml + secrets: inherit + permissions: + id-token: write # required by aws-actions/configure-aws-credentials + python-asyncpg: needs: changes if: needs.changes.outputs.python-asyncpg == 'true' @@ -324,6 +334,7 @@ jobs: - javascript-node-postgres - javascript-postgresjs - lambda-nodejs + - php-authentication - python-asyncpg - python-cm - python-psycopg2 diff --git a/.github/workflows/php-authentication-integ-tests.yml b/.github/workflows/php-authentication-integ-tests.yml new file mode 100644 index 00000000..3fabe805 --- /dev/null +++ b/.github/workflows/php-authentication-integ-tests.yml @@ -0,0 +1,61 @@ +name: PHP authentication integration tests + +permissions: {} + +on: + workflow_call: {} + workflow_dispatch: + push: + branches: [ main ] + +jobs: + create-cluster: + uses: ./.github/workflows/dsql-cluster-create.yml + with: + workflow_name: php-authentication + secrets: + AWS_IAM_ROLE: ${{ secrets.PYTHON_IAM_ROLE }} + permissions: + id-token: write + + php-authentication-integ-test: + needs: create-cluster + runs-on: ubuntu-latest + permissions: + id-token: write + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Enable pdo_pgsql extension + run: sudo phpenmod pdo_pgsql + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v6 + with: + role-to-assume: ${{ secrets.PYTHON_IAM_ROLE }} + aws-region: ${{ needs.create-cluster.outputs.region }} + + - name: Install dependencies + working-directory: ./php/authentication + run: composer install --no-interaction + + - name: Run integration tests + working-directory: ./php/authentication + env: + CLUSTER_ENDPOINT: ${{ needs.create-cluster.outputs.cluster-endpoint }} + REGION: ${{ needs.create-cluster.outputs.region }} + run: ./vendor/bin/phpunit + + delete-cluster: + if: always() && needs.create-cluster.result == 'success' + needs: [create-cluster, php-authentication-integ-test] + uses: ./.github/workflows/dsql-cluster-delete.yml + with: + cluster-id: ${{ needs.create-cluster.outputs.cluster-id }} + region: ${{ needs.create-cluster.outputs.region }} + secrets: + AWS_IAM_ROLE: ${{ secrets.PYTHON_IAM_ROLE }} + permissions: + id-token: write diff --git a/php/authentication/composer.json b/php/authentication/composer.json new file mode 100644 index 00000000..6b7f4de1 --- /dev/null +++ b/php/authentication/composer.json @@ -0,0 +1,13 @@ +{ + "require": { + "aws/aws-sdk-php": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "autoload": { + "psr-4": { + "Dsql\\": "src/" + } + } +} diff --git a/php/authentication/phpunit.xml b/php/authentication/phpunit.xml new file mode 100644 index 00000000..74a349ae --- /dev/null +++ b/php/authentication/phpunit.xml @@ -0,0 +1,11 @@ + + + + + test + + + diff --git a/php/authentication/src/generate_token.php b/php/authentication/src/generate_token.php new file mode 100644 index 00000000..f91bf180 --- /dev/null +++ b/php/authentication/src/generate_token.php @@ -0,0 +1,23 @@ +generateDbConnectAdminAuthToken($yourClusterEndpoint, $region); + + echo $token . PHP_EOL; + return $token; +} +// --8<-- [end:php-generate-token] diff --git a/php/authentication/test/GenerateTokenTest.php b/php/authentication/test/GenerateTokenTest.php new file mode 100644 index 00000000..cbbed0c1 --- /dev/null +++ b/php/authentication/test/GenerateTokenTest.php @@ -0,0 +1,42 @@ +assertNotEmpty($endpoint, 'CLUSTER_ENDPOINT environment variable must be set'); + + $token = generateToken($endpoint, $region); + + $this->assertIsString($token); + $this->assertNotEmpty($token); + } + + public function testTokenCanConnectToCluster(): void + { + $endpoint = getenv('CLUSTER_ENDPOINT'); + $region = getenv('REGION') ?: 'us-east-1'; + + $this->assertNotEmpty($endpoint, 'CLUSTER_ENDPOINT environment variable must be set'); + + $token = generateToken($endpoint, $region); + + $dsn = "pgsql:host={$endpoint};port=5432;dbname=postgres;sslmode=verify-full;sslrootcert=system"; + $pdo = new PDO($dsn, 'admin', $token); + + $stmt = $pdo->query('SELECT 1 AS result'); + $result = $stmt->fetchColumn(); + + $this->assertEquals(1, (int) $result); + } +}