From 6af315dcd22761f5b7046e93e7eb3349020f2ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Pi=C5=A1t=C4=9Bk?= Date: Tue, 28 Jan 2025 16:39:40 +0100 Subject: [PATCH 1/5] chore: Replace `docker-compose` with `docker compose` --- .github/workflows/push.yml | 4 ++-- README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 30224a2..bf40e3e 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -29,7 +29,7 @@ jobs: - name: Build image run: | docker login --username "$DOCKERHUB_USER" --password "$DOCKERHUB_TOKEN" - docker-compose build + docker compose build - name: Run tests run: | - docker-compose run ci + docker compose run ci diff --git a/README.md b/README.md index a70562a..5f6a71b 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Prerequisites: * installed AWS CLI `aws` (and run `aws configure --profile YOUR_AWS_PROFILE_NAME`) * installed GCP CLI `gcloud` (and run `gcloud auth login` or `gcloud auth application-default login`) * installed `terraform` (https://www.terraform.io) and `jq` (https://stedolan.github.io/jq) to setup local env -* installed `docker` and `docker-compose` to run & develop the app +* installed `docker` to run & develop the app ```bash export NAME_PREFIX= # your name/nickname to make your resource unique & recognizable @@ -88,7 +88,7 @@ terraform -chdir=./provisioning/local init -backend-config="key=object-encryptor terraform -chdir=./provisioning/local apply ./provisioning/local/update-env.sh aws # or azure or gcp -docker-compose run --rm tests +docker compose run --rm tests ``` ## License From 5c6394551c7f3475d84d40557d7a8630e95497ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Pi=C5=A1t=C4=9Bk?= Date: Wed, 29 Jan 2025 08:39:02 +0100 Subject: [PATCH 2/5] chore: Recreate AKV for CI --- .github/workflows/push.yml | 2 +- provisioning/ci/.terraform.lock.hcl | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index bf40e3e..21e336b 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -4,7 +4,7 @@ concurrency: ci env: TEST_TENANT_ID: 9b85ee6f-4fb0-4a46-8cb7-4dcc6b262a89 - TEST_CLIENT_ID: 3a4162fa-43d4-4de7-a8c1-be3bc7765a8c + TEST_CLIENT_ID: bbd79ac8-74a2-4853-8c8c-99af4c614492 TEST_CLIENT_SECRET: ${{ secrets.TEST_CLIENT_SECRET }} TEST_KEY_VAULT_URL: https://ci-object-encryptor.vault.azure.net/ TEST_AWS_REGION: eu-central-1 diff --git a/provisioning/ci/.terraform.lock.hcl b/provisioning/ci/.terraform.lock.hcl index 0331dee..fe36afd 100644 --- a/provisioning/ci/.terraform.lock.hcl +++ b/provisioning/ci/.terraform.lock.hcl @@ -7,6 +7,7 @@ provider "registry.terraform.io/hashicorp/aws" { hashes = [ "h1:Yi/V8LtJKyGZhKJmgsqKpVqBZKNECctHOn4fV3LFvOw=", "h1:x0gluX9ZKEmz+JJW3Ut5GgWDFOq/lhs2vkqJ+xt57zs=", + "h1:xXeHg5KDyH3rn2mrFh+iuvO2d9CEx8ryvOWRUMC3aWg=", "zh:0e75fb14ec42d69bc46461dd54016bb2487d38da324222cec20863918b8954c4", "zh:30831a1fe29f005d8b809250b43d09522288db45d474c9d238b26f40bdca2388", "zh:36163d625ab2999c9cd31ef2475d978f9f033a8dfa0d585f1665f2d6492fac4b", @@ -26,6 +27,7 @@ provider "registry.terraform.io/hashicorp/azuread" { version = "2.22.0" constraints = "~> 2.18" hashes = [ + "h1:8AfMLW7SHmCPDODLKpx4QY0kNV4IZBrwDvfS/yAzpTI=", "h1:BLBnXLc5mCzSZ0PX5lGn5zgtnrkP7LMRwTA5pBwr2fk=", "h1:so17lrrqkdZcmQp5V/hvY5vLXw1BmwQMnlvGcRq/u0c=", "zh:062d84c514cd5015af60693ca4f3aece80d358fd7172951546eaba8093065c5b", @@ -47,6 +49,7 @@ provider "registry.terraform.io/hashicorp/azurerm" { version = "2.99.0" constraints = "~> 2.98" hashes = [ + "h1:/M8yLHqv0uOm9IbHRa4yZvQORr9ir1QyJyIyjGs4ryQ=", "h1:FXBB5TkvZpZA+ZRtofPvp5IHZpz4Atw7w9J8GDgMhvk=", "h1:Ith/+ax1KB67flRhGOP0+UxM8kEXOT950tGattoYvP4=", "h1:aCGPSDzEWQZLeWmUeSnXA6sDHMumbDqOVdSVKVziYoE=", @@ -69,6 +72,7 @@ provider "registry.terraform.io/hashicorp/google" { constraints = "~> 4.74.0" hashes = [ "h1:WazqiKdNsMSDEIyNBNT9rIY99jN2eWuiE6qMfKAZTpY=", + "h1:ghkjuvUrHsIlzjNL5KRsYZcP3R9BoFRfb0q069BXBi4=", "zh:60904193c367b1ba9a3cb1bd86ca469ffcec2f7237e59adf4b0a34c84b2fa9ff", "zh:6e5ac12f3fefc23907a94e5f6040118c978af76ab5deb60a5b80110c1c8ade09", "zh:9fc0ae0f97ab598c27fae0a6b19e82c13fd59d020d7cdfeeebdbe41c4a8216ef", From 73440a8a606a26b045454ac09e80cdf46347dd47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Pi=C5=A1t=C4=9Bk?= Date: Mon, 3 Feb 2025 13:42:13 +0100 Subject: [PATCH 3/5] chore: Replace deprecated checkMissingIterableValueType param in phpstan.neon --- phpstan.neon | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/phpstan.neon b/phpstan.neon index 03311a5..7ba6c82 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,8 +1,10 @@ parameters: level: max - checkMissingIterableValueType: false paths: - src - tests + ignoreErrors: + - + identifier: missingType.iterableValue includes: - vendor/phpstan/phpstan-phpunit/extension.neon From dca09cef3627e873f1d85185235cf6c8ae52338d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Pi=C5=A1t=C4=9Bk?= Date: Mon, 3 Feb 2025 13:42:42 +0100 Subject: [PATCH 4/5] chore: Drop obsolete version attr in docker-compose.yml --- docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index dbe32e9..b92133c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,3 @@ -version: "3" services: # for development purposes tests: &tests From a818fb23fba19f446c17e41457310cd1fbdcb81c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Pi=C5=A1t=C4=9Bk?= Date: Mon, 3 Feb 2025 19:27:45 +0100 Subject: [PATCH 5/5] feat: Drop SECRET_VERSION when retrieving a secret in GenericAKVWrapper::decrypt() --- src/Wrapper/GenericAKVWrapper.php | 7 +++---- tests/GenericAKVWrapperTest.php | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/Wrapper/GenericAKVWrapper.php b/src/Wrapper/GenericAKVWrapper.php index b21afef..576e497 100644 --- a/src/Wrapper/GenericAKVWrapper.php +++ b/src/Wrapper/GenericAKVWrapper.php @@ -150,10 +150,9 @@ public function decrypt(string $encryptedData): string } try { $decryptedContext = $this->getRetryProxy()->call(function () use ($encrypted) { - return $this->getClient()->getSecret( - $encrypted[self::SECRET_NAME], - $encrypted[self::SECRET_VERSION], - )->getValue(); + return $this->getClient() + ->getSecret($encrypted[self::SECRET_NAME]) + ->getValue(); }); assert(is_string($decryptedContext)); $decryptedContext = $this->decode($decryptedContext); diff --git a/tests/GenericAKVWrapperTest.php b/tests/GenericAKVWrapperTest.php index 3ee68e9..666bca7 100644 --- a/tests/GenericAKVWrapperTest.php +++ b/tests/GenericAKVWrapperTest.php @@ -122,6 +122,27 @@ public function testEncryptEmptyValue(?string $secret): void self::assertEquals($secret, $wrapper->decrypt($encrypted)); } + public function testIgnoreSecretVersionWhenRetrievingSecret(): void + { + $secret = 'mySecretValue'; + $wrapper = $this->getWrapper(); + $encrypted = $wrapper->encrypt($secret); + + // decode the encrypted secret and manually change the version + $decoded = unserialize((string) gzuncompress(base64_decode($encrypted))); + $secretVersionIndex = 4; // = GenericAKVWrapper::SECRET_VERSION + /** @var array $decoded */ + $decoded[$secretVersionIndex] = bin2hex(random_bytes(16)); + + // encode back with the changed version + $encrypted = base64_encode((string) gzcompress(serialize($decoded))); + + // decrypt should succeed regardless of changed version + $decrypted = $wrapper->decrypt($encrypted); + + self::assertSame($secret, $decrypted); + } + private function getMockWrapper(Client $mockClient): GenericAKVWrapper { $mockWrapper = $this->createPartialMock(GenericAKVWrapper::class, ['getClient']);