From 7b452e03eeb8c987dd0d50ade6df922b1c9a6c18 Mon Sep 17 00:00:00 2001 From: Stephan Schuler Date: Tue, 24 Oct 2023 11:59:05 +0200 Subject: [PATCH] feat: Encrypt POST data before sending it to sentry --- .../Controller/EncryptedPayloadController.php | 43 +++++ Classes/Encryption/EncryptionService.php | 114 ++++++++++++++ Classes/Encryption/Sealed.php | 61 ++++++++ Classes/EventProcessor/EncryptedPayload.php | 64 ++++++++ Classes/EventProcessor/EventProcessor.php | 13 ++ Classes/Integration/NetlogixIntegration.php | 23 ++- Configuration/Policy.yaml | 20 +++ Configuration/Routes.yaml | 9 ++ .../Settings.Encryption.Backend.yaml | 23 +++ Configuration/Settings.Encryption.yaml | 13 ++ README.md | 70 +++++++++ .../EncryptionServiceTestCase.php | 33 ++++ .../Encryption/EncryptionService/OpenTest.php | 35 +++++ .../EncryptionService/RsaWalletData.bin | Bin 0 -> 3520 bytes .../Encryption/EncryptionService/SealTest.php | 39 +++++ .../Scope/RewriteEvent/RewriteEventTest.php | 147 ++++++++++++++++++ composer.json | 4 +- 17 files changed, 709 insertions(+), 2 deletions(-) create mode 100644 Classes/Controller/EncryptedPayloadController.php create mode 100644 Classes/Encryption/EncryptionService.php create mode 100644 Classes/Encryption/Sealed.php create mode 100644 Classes/EventProcessor/EncryptedPayload.php create mode 100644 Classes/EventProcessor/EventProcessor.php create mode 100644 Configuration/Policy.yaml create mode 100644 Configuration/Routes.yaml create mode 100644 Configuration/Settings.Encryption.Backend.yaml create mode 100644 Configuration/Settings.Encryption.yaml create mode 100644 Tests/Unit/Encryption/EncryptionService/EncryptionServiceTestCase.php create mode 100644 Tests/Unit/Encryption/EncryptionService/OpenTest.php create mode 100644 Tests/Unit/Encryption/EncryptionService/RsaWalletData.bin create mode 100644 Tests/Unit/Encryption/EncryptionService/SealTest.php create mode 100644 Tests/Unit/Scope/RewriteEvent/RewriteEventTest.php diff --git a/Classes/Controller/EncryptedPayloadController.php b/Classes/Controller/EncryptedPayloadController.php new file mode 100644 index 0000000..9a61ee1 --- /dev/null +++ b/Classes/Controller/EncryptedPayloadController.php @@ -0,0 +1,43 @@ +encryptionService = $encryptionService; + } + + /** + * @param string $encryptedData + * @param string $initializationVector + * @param string $envelopeKey + */ + public function decryptAction( + string $encryptedData, + string $initializationVector, + string $envelopeKey + ): string { + $sealed = Sealed::fromArray([ + 'encryptedData' => $encryptedData, + 'initializationVector' => $initializationVector, + 'envelopeKey' => $envelopeKey, + ]); + $unencrypted = $this->encryptionService->open($sealed); + $this->response->setContentType('application/json'); + + return json_encode(json_decode($unencrypted, true), JSON_PRETTY_PRINT); + } +} diff --git a/Classes/Encryption/EncryptionService.php b/Classes/Encryption/EncryptionService.php new file mode 100644 index 0000000..4bd2e3b --- /dev/null +++ b/Classes/Encryption/EncryptionService.php @@ -0,0 +1,114 @@ +rsaKeyFingerprint = (string) ($privacySettings['rsaKeyFingerprint'] ?? ''); + $this->encryptionModuleUri = (string) ($privacySettings['encryptionModuleUri'] ?? ''); + } + + public function injectRsaWalletService(RsaWalletServiceInterface $rsaWallet): void + { + $this->rsaWallet = $rsaWallet; + } + + public function injectBaseUriProvider(BaseUriProvider $baseUriProvider): void + { + $this->baseUriProvider = $baseUriProvider; + } + + public function seal(string $unencryptedData): Sealed + { + $publicKeyString = $this->getKeyString('publicKey'); + + $initializationVector = openssl_random_pseudo_bytes(32); + + openssl_seal( + $unencryptedData, + $encryptedData, + $envelopeKeys, + [$publicKeyString], + self::ALGORITHM, + $initializationVector + ); + + return new Sealed($encryptedData, $initializationVector, $envelopeKeys[0]); + } + + public function open(Sealed $package): string + { + $privateKeyString = $this->getKeyString('privateKey'); + + $encryptedData = $package->getEncryptedData(); + $envelopeKey = $package->getEnvelopeKey(); + $initializationVector = $package->getInitializationVector(); + + openssl_open( + $encryptedData, + $unencryptedData, + $envelopeKey, + $privateKeyString, + self::ALGORITHM, + $initializationVector + ); + + return $unencryptedData; + } + + public function getEncryptionUriForSealedPayload(Sealed $sealed): UriInterface + { + return $this->baseUriProvider + ->getConfiguredBaseUriOrFallbackToCurrentRequest() + ->withPath($this->encryptionModuleUri) + ->withQuery(http_build_query($sealed->toArray())); + } + + /** + * @param 'privateKey' | 'publicKey' $slotName + */ + private function getKeyString(string $slotName): string + { + assert($this->rsaWallet instanceof RsaWalletServicePhp); + // Prime key pair, male rsaWallet load the key pair + $this->rsaWallet->getPublicKey($this->rsaKeyFingerprint); + // Private property + $keys = ObjectAccess::getProperty($this->rsaWallet, 'keys', true); + // Property path in plain array + $keyString = ObjectAccess::getPropertyPath( + $keys, + sprintf('%s.%s.keyString', $this->rsaKeyFingerprint, $slotName) + ); + if (!\is_string($keyString)) { + throw new InvalidKeyPairIdException('Invalid key fingerprint given', 1693231337); + } + + return $keyString; + } +} diff --git a/Classes/Encryption/Sealed.php b/Classes/Encryption/Sealed.php new file mode 100644 index 0000000..99012ab --- /dev/null +++ b/Classes/Encryption/Sealed.php @@ -0,0 +1,61 @@ +encryptedData = $encryptedData; + $this->initializationVector = $initializationVector; + $this->envelopeKey = $envelopeKeys; + } + + public static function fromArray(array $package): self + { + return new self( + $package['encryptedData'] ? base64_decode($package['encryptedData'], true) : '', + $package['initializationVector'] ? base64_decode($package['initializationVector'], true) : '', + $package['envelopeKey'] ? base64_decode($package['envelopeKey'], true) : '' + ); + } + + public function toArray(): array + { + return [ + 'encryptedData' => base64_encode($this->encryptedData), + 'initializationVector' => base64_encode($this->initializationVector), + 'envelopeKey' => base64_encode($this->envelopeKey), + ]; + } + + public function getEncryptedData(): string + { + return $this->encryptedData; + } + + public function getInitializationVector(): string + { + return $this->initializationVector; + } + + public function getEnvelopeKey(): string + { + return $this->envelopeKey; + } +} diff --git a/Classes/EventProcessor/EncryptedPayload.php b/Classes/EventProcessor/EncryptedPayload.php new file mode 100644 index 0000000..cfcc151 --- /dev/null +++ b/Classes/EventProcessor/EncryptedPayload.php @@ -0,0 +1,64 @@ +encryption = $encryption; + } + + public function injectSettings(array $settings): void + { + $privacyCettings = $settings['privacy'] ?? []; + $this->encryptPostBody = (bool) ($privacyCettings['encryptPostBody'] ?? false); + } + + public function rewriteEvent(Event $event, EventHint $hint): Event + { + if (!$this->encryptPostBody) { + return $event; + } + + $request = $event->getRequest(); + + $data = $request['data'] ?? []; + if (!$data || !is_array($data)) { + return $event; + } + + $unencrypted = (string) json_encode($data, \JSON_PRETTY_PRINT); + + $encrypted = $this->encryption + ->seal($unencrypted); + $uri = (string) $this->encryption + ->getEncryptionUriForSealedPayload($encrypted); + + $request['data'] = [ + '__ENCRYPTED__DATA__' => $encrypted->toArray(), + ]; + $event->setRequest($request); + + $extra = $event->getExtra() ?? []; + $extra['Encrypted POST Data'] = $uri; + $event->setExtra($extra); + + return $event; + } +} diff --git a/Classes/EventProcessor/EventProcessor.php b/Classes/EventProcessor/EventProcessor.php new file mode 100644 index 0000000..63ce59c --- /dev/null +++ b/Classes/EventProcessor/EventProcessor.php @@ -0,0 +1,13 @@ +get(\Netlogix\Sentry\EventProcessor\EncryptedPayload::class); + return $encryptedPayload->rewriteEvent($event, $hint); + } + } diff --git a/Configuration/Policy.yaml b/Configuration/Policy.yaml new file mode 100644 index 0000000..713f85f --- /dev/null +++ b/Configuration/Policy.yaml @@ -0,0 +1,20 @@ +privilegeTargets: + + 'Neos\Flow\Security\Authorization\Privilege\Method\MethodPrivilege': + + 'Netlogix.Sentry:Backend.EncryptedPayload': + matcher: 'method(Netlogix\Sentry\Controller\EncryptedPayloadController->.*())' + +roles: + + 'Neos.Flow:Anonymous': + privileges: + - + privilegeTarget: 'Netlogix.Sentry:Backend.EncryptedPayload' + permission: DENY + + 'Neos.Neos:Administrator': + privileges: + - + privilegeTarget: 'Netlogix.Sentry:Backend.EncryptedPayload' + permission: GRANT diff --git a/Configuration/Routes.yaml b/Configuration/Routes.yaml new file mode 100644 index 0000000..ecd4b6a --- /dev/null +++ b/Configuration/Routes.yaml @@ -0,0 +1,9 @@ +- name: 'HashToken Login' + uriPattern: 'neos/sentry/show-parameters' + defaults: + '@package': 'Netlogix.Sentry' + '@controller': 'EncryptedPayload' + '@action': 'decrypt' + '@format': 'html' + appendExceedingArguments: TRUE + httpMethods: ['GET'] diff --git a/Configuration/Settings.Encryption.Backend.yaml b/Configuration/Settings.Encryption.Backend.yaml new file mode 100644 index 0000000..cebf0f3 --- /dev/null +++ b/Configuration/Settings.Encryption.Backend.yaml @@ -0,0 +1,23 @@ +Neos: + Flow: + + mvc: + routes: + 'Netlogix.Sentry': + position: before Neos.Neos + + # Use the following configuration snippet when this package is used in conjunction with the neos/neos CMS. + # Use something similar when another authentication provider will be used. + # Unfortunately, this cannot be done preemptively. + # + # security: + # authentication: + # providers: + # 'Neos.Neos:Backend': + # requestPatterns: + # 'Netlogix.Sentry:ShowEncryptedPayload': + # pattern: ControllerObjectName + # patternOptions: + # controllerObjectNamePattern: 'Netlogix\Sentry\Controller\.*' + + diff --git a/Configuration/Settings.Encryption.yaml b/Configuration/Settings.Encryption.yaml new file mode 100644 index 0000000..a1c9d51 --- /dev/null +++ b/Configuration/Settings.Encryption.yaml @@ -0,0 +1,13 @@ +Netlogix: + Sentry: + privacy: + + # Enable to replace the request POSt body with an encrypted version + encryptPostBody: false + + # Enter a fingerprint of an RSA key stored in the RsaWallet + rsaKeyFingerprint: '' + + # Enter the URI of the encryption module + # No route generation is done during exception handling + encryptionModuleUri: '/neos/sentry/show-parameters' diff --git a/README.md b/README.md index 019c24c..6f38b26 100644 --- a/README.md +++ b/README.md @@ -198,3 +198,73 @@ Neos: ``` Please note that this also disables logging of this exception to `Data/Logs/Exceptions`. + +## Encrypt POST payload + +By default, the array of POST payload data is transported to the sentry server "as is". + +When encryption is enabled and a valid rsa key fingerprint is set, the POST payload is stripped and replaced by an +RSA encrypted string. + +```yaml +Netlogix: + Sentry: + + privacy: + encryptPostBody: true + rsaKeyFingerprint: '6ff568ae0f9b44b69627e275accf163a' +``` + +POST data without encryption usually looks like this in sentry: + +```json +{ + "--some-form": { + "__currentPage": 1, + "__state": "TmV0bG9naXguU2VudHJ5IHN0YXRlIGRhdGE=", + "__trustedProperties": "[Filtered]", + "firstName": "John", + "lastName": "Doe", + "birthday": "2021-01-01", + "email": "john.doe@netlogix.de", + "message": "Lorem ipsum dolor sit amet" + } +} +``` + +With encryption enabled it looks like this: + +```json +{ + "__ENCRYPTED__DATA__": { + "encryptedData": "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2ljaSBlbGl0LCBzZWQgZWl1c21vZCB0ZW1wb3IgaW5jaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWduYSBhbGlxdWEuIFV0IGVuaW0gYWQgbWluaW0gdmVuaWFtLCBxdWlzIG5vc3RydWQgZXhlcmNpdGF0aW9u", + "envelopeKey": "ZGVzZXJ1bnQgbW9sbGl0IGFuaW0gaWQgZXN0IGxhYm9ydW0=", + "initializationVector": "QmxpbmR0ZXh0" + } +} +``` + +There will be an additional sentry field "Encrypted POST Data" which contains a backlink to encrypt and show the +original data. + +In order for this to work, there must be an authentication provider in place that handels the Neos.Sentry controller. + +If this package is used in conjunction with the neos/neos CMS, the neos backend authentication provider can be tasked +with this job. See the code snippet below. + +If this package is used without neos/neos, a custom privilege for policy `Netlogix.Sentry:Backend.EncryptedPayload` +has to be configured. + +```yaml +Neos: + Flow: + security: + authentication: + providers: + 'Neos.Neos:Backend': + requestPatterns: + 'Netlogix.Sentry:ShowEncryptedPayload': + pattern: ControllerObjectName + patternOptions: + controllerObjectNamePattern: 'Netlogix\Sentry\Controller\.*' +``` diff --git a/Tests/Unit/Encryption/EncryptionService/EncryptionServiceTestCase.php b/Tests/Unit/Encryption/EncryptionService/EncryptionServiceTestCase.php new file mode 100644 index 0000000..ff025c9 --- /dev/null +++ b/Tests/Unit/Encryption/EncryptionService/EncryptionServiceTestCase.php @@ -0,0 +1,33 @@ +injectSettings([ + 'security' => [ + 'cryptography' => [ + 'RSAWalletServicePHP' => [ + 'keystorePath' => self::RSA_WALLET_FILE, + 'paddingAlgorithm' => 0, + ], + ], + ], + ]); + $wallet->initializeObject(); + + return $wallet; + } +} diff --git a/Tests/Unit/Encryption/EncryptionService/OpenTest.php b/Tests/Unit/Encryption/EncryptionService/OpenTest.php new file mode 100644 index 0000000..81375d0 --- /dev/null +++ b/Tests/Unit/Encryption/EncryptionService/OpenTest.php @@ -0,0 +1,35 @@ +injectSettings([ + 'privacy' => [ + 'rsaKeyFingerprint' => self::RSA_KEY_FINGERPRINT, + ], + ]); + + $sealed = Sealed::fromArray([ + 'encryptedData' => '8qM4pkKLNxgRy61vffZKwg==', + 'initializationVector' => 'StKlRPeWNOAk5LZ9jtFR3Q==', + 'envelopeKey' => 'Zk4jrCZcHDw8SJv3WgSyfJnkAteG1G8+A4DP3vIQJTbqoPqi6dKJLutqsJLwMfh4vmsp9K/uIud8SFh3M+HwvbCDs5KOnj4ozZTdtmCVKTKm6+6nx3v5zMdte+x0oahUeJqn4QcwDU7vCIDKtuSR1xQXXDkJGznYi/aMN/O20PHRCvuR93ZWD9IYyNd6ETJwqMglP81vWQHngX4uVK0KYXsUB7T5fgj+dISw/2+zSA4WVSjexK+BpZJQjqEwp+Zv1DL5l88LT3bG5l+k/bpDx4sBcDzc8/iwNvKmbngFluZWnxu+CuUjPR4PHyv5oWWBwQ6yy2i/0JAo9FgdGvVVKw==', + ]); + + $encryptionService->injectRsaWalletService(self::getRsaWalletServicePhp()); + $open = $encryptionService->open($sealed); + + self::assertEquals('foo', $open); + } +} diff --git a/Tests/Unit/Encryption/EncryptionService/RsaWalletData.bin b/Tests/Unit/Encryption/EncryptionService/RsaWalletData.bin new file mode 100644 index 0000000000000000000000000000000000000000..5b94bc14784a4e5a1229d2663b7f03e3010ce8a9 GIT binary patch literal 3520 zcmeHKNzb!7((N_BqV+60YJqLQ@Vx4UF(!e8F>`b`1PDV2a|USL|K2>eH$8moZ`GC% zCF3fNP8C&$@Ed&pz5hn=`wQWl5M6~B%dsSeY7AomC^!_72r8nS;ICidH~KlOet$L3 zYneyuWc>Q&ev8ugmy^`}Z$??af7>R}v&)C^H`%SP@)1A z4MLQVsX6R6oR6Jus80oSA z0Tp!&Arz@ZR3=Ig0HkZWLL{I=tWZ(XC=hgA))WB)j1UljA!-CDB9a9rK%~ql6df@c zsgf?r)WDDt0nNN3)zBq0UkcKgB4~&yx+npnV*vnJ*CYm^EbB5;W=kS7Kp+`Z5oT&- zO%POBM{q_$Gy>V2Cs~RKRMj9zqfD7SB*GNYFjPbtpemIG z8Bt9^MEfa(pE{UJ^7EXg>)B?c8}ik<$l%>%@%0kekRA`*=e6r5Z5_gX<@>UE z33B^}*0+y}Txmbr)44_=K42fPLv!0$aa?S%t~k5>u@80A0NinEARp};ac?32v`yi0 zwD^tHn%ymG^1B{XofX~0o9Vpr6Zv>;S=+Bg1axb0a89nnsS5+|U^8Loy$-8|bPsRH zS!LI9d$=T@8hJ;OeViz_>|-MtX5d}ndLLWj$9QRa9EzOwi6*A0oBHfSJvBwgFLqK< z#zC)+a_a7Vi9dMiQGeBRlAR#vP9(TqPr3B~&n&S*E)b2|NNgCs=}{Qrx|KIWxy&{% z0k-+sd*VDS`vBhemqqb%(;*9G#!H^NvOeiqdFovIHg)0?jr$`h%+dcVPhY=&|L3>g zbonbBlK*v)|8ApUzB3Csi8v486$>_tp%9xwk#FWFLUeSW9uHYX_~q@K_D z^a;(VbyuOE24LVyHl3}@X{ov|n>Ahdjy1i`%BA_?qlRCh2$wr^a`GbXhSQ+$gJY@m zC4kPR_ujw>xbRck>FIEFtE>9iR+(SLTD;aTSF=+3N1YGq_*nbSGU>|?pD8I^Sdq>a z?J*sBY1-RdCG9~ZA|##$FRZ*Ck*2-jN6_$*kQmQ{btv(&h}1J(F)*65JuqXVGeFzl-A{joHoVtxb9GttHC$BIokx z)~2d732VAacq^R`_ifc2U+=}Vz62=tigR>qE}H&4Q5@__+ccCAgs+=2LRfRPnM{pq z40~F3Jl!o}`?T|0w%wJdM**xnHOx0YyJNGmS6x7&tzvY-DJt|`)jvksam}MkFUZM}?-xsfdI`TNLF*0Otdi5I?FZE^DE?2h%V*Yc0Y z)kA&Z`x3E9I$WnW|A|I6emt|$Z*oya$!_xcyZ@n^ZT~n;yOTC7tCWKiomB}1)o^<8 zp(ZMub-CErC_`E4rU!xVtoyrpM*DOo_{<0j>(+D1XTAt0_bY9BF<2CzSXmd+es{4VahU=sc ziZK-z!QxrIf&EzSoJqP?keV-$d;5SQE9@Od;iQFj*m>+>oEl?SFH_`!c5Ed29e2aof`IJX<%DN_m$C#0(@qj@0d(tvM#A6D@}2V*s? z^#Nn~F6GAVb&0E^8aUM~zaPcaa_M@t>VS2Tr_=3T-!@_$+0V5Y)sM$3J}id^|AaN% zIQIRM#*fX@9><83SMPne; zCYR@`@Fyv0)>GGPq4h`-lydtXuAh~)*lwkuzLQjMHxtfL{+ZUrxnbsYU*Ju$s6Xlg zcuRZ>gY)J6Da7787NuvV+-JX;GM}i6?P+(&$5*v-{lE@0F;VVQkep)MidIr0yRpny zehunc60&gLi<_W+tyG!2y|DM@*XzRE<4=JkW65m#{@dUFMJoO0Ec&NblE1&6eG(gW U=Y@U$uDf{tTe^M=zkdJyAEinjectSettings([ + 'privacy' => [ + 'rsaKeyFingerprint' => self::RSA_KEY_FINGERPRINT, + ], + ]); + + $encryptionService->injectRsaWalletService(self::getRsaWalletServicePhp()); + $sealed = $encryptionService->seal('foo'); + + self::assertInstanceOf(Sealed::class, $sealed); + + $data = $sealed->toArray(); + + self::assertArrayHasKey('encryptedData', $data); + self::assertArrayHasKey('initializationVector', $data); + self::assertArrayHasKey('envelopeKey', $data); + + self::assertGreaterThan(0, \strlen($data['encryptedData'])); + self::assertGreaterThan(0, \strlen($data['initializationVector'])); + self::assertGreaterThan(0, \strlen($data['envelopeKey'])); + } +} diff --git a/Tests/Unit/Scope/RewriteEvent/RewriteEventTest.php b/Tests/Unit/Scope/RewriteEvent/RewriteEventTest.php new file mode 100644 index 0000000..52813cf --- /dev/null +++ b/Tests/Unit/Scope/RewriteEvent/RewriteEventTest.php @@ -0,0 +1,147 @@ +getMockBuilder(ObjectManagerInterface::class) + ->getMock(); + + $encryptedPayload = new EncryptedPayload(); + $encryptedPayload->injectSettings([]); + + $objectManager + ->expects(self::once()) + ->method('get') + ->with(EncryptedPayload::class) + ->willReturn($encryptedPayload); + + Bootstrap::$staticObjectManager = $objectManager; + + $event = Event::createEvent(EventId::generate()); + $request = [ + 'data' => [ + 'foo' => 'bar', + ], + ]; + $event->setRequest($request); + + $newEvent = NetlogixIntegration::encryptPostBody($event, new EventHint()); + $newRequest = $newEvent->getRequest(); + + self::assertSame($request, $newRequest); + } + + /** + * @test + */ + public function Enabled_encryption_but_no_request_data_does_not_replace_the_request(): void + { + $objectManager = $this->getMockBuilder(ObjectManagerInterface::class) + ->getMock(); + + $encryptedPayload = new EncryptedPayload(); + $encryptedPayload->injectSettings([ + 'privacy' => [ + 'encryptPostBody' => true, + ], + ]); + + $objectManager + ->expects(self::once()) + ->method('get') + ->with(EncryptedPayload::class) + ->willReturn($encryptedPayload); + + Bootstrap::$staticObjectManager = $objectManager; + + $request = [ + 'whatever' => [ + 'foo' => 'bar', + ], + ]; + $event = Event::createEvent(EventId::generate()); + $event->setRequest($request); + + $newEvent = NetlogixIntegration::encryptPostBody($event, new EventHint()); + $newRequest = $newEvent->getRequest(); + + self::assertEquals($request, $newRequest); + } + + /** + * @test + */ + public function Enabled_encryption_calls_the_encryption_service_and_rewrites_the_request_body(): void + { + $objectManager = $this->getMockBuilder(ObjectManagerInterface::class) + ->getMock(); + + $request = [ + 'data' => [ + 'foo' => 'bar', + ], + ]; + + $encryption = $this->createMock(EncryptionService::class); + $encryption + ->expects(self::once()) + ->method('seal') + ->with(\json_encode($request['data'], \JSON_PRETTY_PRINT)) + ->willReturn(new Sealed('$encryptedData', '$initializationVector', '$envelopeKeys')); + + $encryptedPayload = new EncryptedPayload(); + $encryptedPayload->injectSettings([ + 'privacy' => [ + 'encryptPostBody' => true, + ], + ]); + $encryptedPayload->injectEncryptionService($encryption); + + $objectManager + ->expects(self::once()) + ->method('get') + ->with(EncryptedPayload::class) + ->willReturn($encryptedPayload); + + Bootstrap::$staticObjectManager = $objectManager; + + $event = Event::createEvent(EventId::generate()); + $event->setRequest($request); + + $newEvent = NetlogixIntegration::encryptPostBody($event, new EventHint()); + $request = $newEvent->getRequest(); + + self::assertEquals( + [ + 'data' => [ + '__ENCRYPTED__DATA__' => [ + 'encryptedData' => \base64_encode('$encryptedData'), + 'initializationVector' => \base64_encode('$initializationVector'), + 'envelopeKey' => \base64_encode('$envelopeKeys'), + ], + ], + ], + $request + ); + } +} diff --git a/composer.json b/composer.json index 3815f85..9415001 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,9 @@ "require": { "php": "^7.4", "neos/flow": "^5.3 || ^6.3", - "sentry/sdk": "^3.1" + "sentry/sdk": "^3.1", + "ext-openssl": "*", + "ext-json": "*" }, "autoload": { "psr-4": {