From 52f22d28a094f6b7a0504a938e0fc2626f3ae9af Mon Sep 17 00:00:00 2001 From: Alex Renoki Date: Sat, 13 Nov 2021 09:00:32 +0200 Subject: [PATCH 1/5] Disabled SSL tearing --- src/Concerns/GeneratesSnsMessages.php | 14 -------------- tests/TestCase.php | 8 -------- 2 files changed, 22 deletions(-) diff --git a/src/Concerns/GeneratesSnsMessages.php b/src/Concerns/GeneratesSnsMessages.php index 2e90038..a600712 100644 --- a/src/Concerns/GeneratesSnsMessages.php +++ b/src/Concerns/GeneratesSnsMessages.php @@ -42,20 +42,6 @@ protected static function initializeSsl(): void $x509 = openssl_csr_sign($csr, null, self::$privateKey, 1); openssl_x509_export($x509, self::$certificate); - - // Deprecated in PHP >= 8.0 - // openssl_x509_free($x509); - } - - /** - * Deinitialize the SSL keys. - * - * @return void - */ - protected static function tearDownSsl(): void - { - // Deprecated in PHP >= 8.0 - // openssl_pkey_free(self::$privateKey); } /** diff --git a/tests/TestCase.php b/tests/TestCase.php index 316172b..bce2429 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -17,14 +17,6 @@ public static function setUpBeforeClass(): void static::initializeSsl(); } - /** - * {@inheritdoc} - */ - public static function tearDownAfterClass(): void - { - static::tearDownSsl(); - } - /** * Get package providers. * From df0f74e16cc6789522a9ffdfc29929cff2fbd14d Mon Sep 17 00:00:00 2001 From: Alex Renoki Date: Sat, 13 Nov 2021 09:02:04 +0200 Subject: [PATCH 2/5] Automatic $request->certificate injection for testing/local --- src/Concerns/HandlesSns.php | 5 ++++- tests/Controllers/CustomSnsController.php | 14 -------------- tests/Controllers/SnsController.php | 15 +-------------- 3 files changed, 5 insertions(+), 29 deletions(-) diff --git a/src/Concerns/HandlesSns.php b/src/Concerns/HandlesSns.php index f365e6a..8317298 100644 --- a/src/Concerns/HandlesSns.php +++ b/src/Concerns/HandlesSns.php @@ -6,6 +6,7 @@ use Aws\Sns\MessageValidator; use Exception; use Illuminate\Http\Request; +use Illuminate\Support\Facades\App; trait HandlesSns { @@ -51,6 +52,8 @@ public function snsMessageIsValid(Request $request): bool */ protected function getMessageValidator(Request $request) { - return new MessageValidator; + return App::environment(['testing', 'local']) + ? new MessageValidator(fn ($url) => $request->certificate ?: $url) + : new MessageValidator; } } diff --git a/tests/Controllers/CustomSnsController.php b/tests/Controllers/CustomSnsController.php index bb306d9..bbb6ea4 100644 --- a/tests/Controllers/CustomSnsController.php +++ b/tests/Controllers/CustomSnsController.php @@ -2,7 +2,6 @@ namespace Rennokki\LaravelSnsEvents\Tests\Controllers; -use Aws\Sns\MessageValidator; use Illuminate\Http\Request; use Rennokki\LaravelSnsEvents\Http\Controllers\SnsController; use Rennokki\LaravelSnsEvents\Tests\Events\CustomSnsEvent; @@ -87,17 +86,4 @@ protected function onSubscriptionConfirmation(array $snsMessage, Request $reques { mt_rand(0, 10000); } - - /** - * Get the message validator instance. - * - * @param \Illuminate\Http\Request $request - * @return \Aws\Sns\MessageValidator - */ - protected function getMessageValidator(Request $request) - { - return new MessageValidator(function ($url) use ($request) { - return $request->certificate ?: $url; - }); - } } diff --git a/tests/Controllers/SnsController.php b/tests/Controllers/SnsController.php index 5945f92..42c4e53 100644 --- a/tests/Controllers/SnsController.php +++ b/tests/Controllers/SnsController.php @@ -2,22 +2,9 @@ namespace Rennokki\LaravelSnsEvents\Tests\Controllers; -use Aws\Sns\MessageValidator; -use Illuminate\Http\Request; use Rennokki\LaravelSnsEvents\Http\Controllers\SnsController as BaseSnsController; class SnsController extends BaseSnsController { - /** - * Get the message validator instance. - * - * @param \Illuminate\Http\Request $request - * @return \Aws\Sns\MessageValidator - */ - protected function getMessageValidator(Request $request) - { - return new MessageValidator(function ($url) use ($request) { - return $request->certificate ?: $url; - }); - } + // } From 94a18485b6f04472c429dee2344dbc26e8551f79 Mon Sep 17 00:00:00 2001 From: Alex Renoki Date: Sat, 13 Nov 2021 09:05:16 +0200 Subject: [PATCH 3/5] Renamed $privateKey to $snsPrivateKey Renamed $certificate to $snsCertificate --- src/Concerns/GeneratesSnsMessages.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Concerns/GeneratesSnsMessages.php b/src/Concerns/GeneratesSnsMessages.php index a600712..fc40ab1 100644 --- a/src/Concerns/GeneratesSnsMessages.php +++ b/src/Concerns/GeneratesSnsMessages.php @@ -8,21 +8,21 @@ trait GeneratesSnsMessages { /** - * Get the private key to sign the request. + * Get the private key to sign the request for SNS. * * @var string */ - protected static $privateKey; + protected static $snsPrivateKey; /** - * The certificate to sign the request. + * The certificate to sign the request for SNS. * * @var string */ - protected static $certificate; + protected static $snsCertificate; /** - * An valid certificate URL for test. + * An valid certificate URL to test SNS. * * @var string */ @@ -35,13 +35,13 @@ trait GeneratesSnsMessages */ protected static function initializeSsl(): void { - self::$privateKey = openssl_pkey_new(); + self::$snsPrivateKey = openssl_pkey_new(); - $csr = openssl_csr_new([], self::$privateKey); + $csr = openssl_csr_new([], self::$snsPrivateKey); - $x509 = openssl_csr_sign($csr, null, self::$privateKey, 1); + $x509 = openssl_csr_sign($csr, null, self::$snsPrivateKey, 1); - openssl_x509_export($x509, self::$certificate); + openssl_x509_export($x509, self::$snsCertificate); } /** @@ -52,7 +52,7 @@ protected static function initializeSsl(): void */ protected function getSignature($stringToSign) { - openssl_sign($stringToSign, $signature, self::$privateKey); + openssl_sign($stringToSign, $signature, self::$snsPrivateKey); return base64_encode($signature); } From f1803bef4b9725b45fdf2cae4c1b729f254edddc Mon Sep 17 00:00:00 2001 From: Alex Renoki Date: Sat, 13 Nov 2021 12:07:53 +0200 Subject: [PATCH 4/5] Making one trait for everything --- src/Concerns/GeneratesSnsMessages.php | 41 ++++++++++++++++++-------- src/Concerns/HandlesSns.php | 18 ++++++++++-- tests/EventTest.php | 42 ++++++++++----------------- tests/TestCase.php | 8 ----- 4 files changed, 59 insertions(+), 50 deletions(-) diff --git a/src/Concerns/GeneratesSnsMessages.php b/src/Concerns/GeneratesSnsMessages.php index fc40ab1..7d57dbe 100644 --- a/src/Concerns/GeneratesSnsMessages.php +++ b/src/Concerns/GeneratesSnsMessages.php @@ -26,7 +26,7 @@ trait GeneratesSnsMessages * * @var string */ - public static $validCertUrl = 'https://sns.us-west-2.amazonaws.com/bar.pem'; + public static $snsValidCertUrl = 'https://sns.us-west-2.amazonaws.com/bar.pem'; /** * Initialize the SSL keys and private keys. @@ -35,13 +35,13 @@ trait GeneratesSnsMessages */ protected static function initializeSsl(): void { - self::$snsPrivateKey = openssl_pkey_new(); + static::$snsPrivateKey = openssl_pkey_new(); - $csr = openssl_csr_new([], self::$snsPrivateKey); + $csr = openssl_csr_new([], static::$snsPrivateKey); - $x509 = openssl_csr_sign($csr, null, self::$snsPrivateKey, 1); + $x509 = openssl_csr_sign($csr, null, static::$snsPrivateKey, 1); - openssl_x509_export($x509, self::$snsCertificate); + openssl_x509_export($x509, static::$snsCertificate); } /** @@ -52,7 +52,9 @@ protected static function initializeSsl(): void */ protected function getSignature($stringToSign) { - openssl_sign($stringToSign, $signature, self::$snsPrivateKey); + static::initializeSsl(); + + openssl_sign($stringToSign, $signature, static::$snsPrivateKey); return base64_encode($signature); } @@ -77,7 +79,7 @@ protected function getSubscriptionConfirmationPayload(array $custom = []): array 'Timestamp' => now()->toDateTimeString(), 'SignatureVersion' => '1', 'Signature' => true, - 'SigningCertURL' => static::$validCertUrl, + 'SigningCertURL' => static::$snsValidCertUrl, ], $custom); $message['Signature'] = $this->getSignature( @@ -110,7 +112,7 @@ protected function getNotificationPayload(array $payload = [], array $custom = [ 'SignatureVersion' => '1', 'Token' => '2336412f37...', 'Signature' => true, - 'SigningCertURL' => static::$validCertUrl, + 'SigningCertURL' => static::$snsValidCertUrl, 'UnsubscribeURL' => 'https://sns.us-west-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-west-2:123456789012:MyTopic:c9135db0-26c4-47ec-8998-413945fb5a96', ], $custom); @@ -121,6 +123,21 @@ protected function getNotificationPayload(array $payload = [], array $custom = [ return $message; } + /** + * Send the SNS-signed message to the given URL. + * + * @param string $url + * @param array $snsPayload + * @return \Illuminate\Testing\TestResponse + */ + protected function sendSnsMessage($url, array $snsPayload = []) + { + /** @var \Illuminate\Foundation\Testing\Concerns\MakesHttpRequests&\Rennokki\LaravelSnsEvents\Concerns\GeneratesSnsMessages $this */ + return $this->withHeaders($this->getHeadersForMessage($snsPayload)) + ->withHeaders(['X-Sns-Testing-Certificate' => static::$snsCertificate]) + ->json('POST', $url, $snsPayload); + } + /** * Get the right headers for a SNS message. * @@ -130,10 +147,10 @@ protected function getNotificationPayload(array $payload = [], array $custom = [ protected function getHeadersForMessage(array $message): array { return [ - 'X-AMZ-SNS-MESSAGE-TYPE' => $message['Type'], - 'X-AMZ-SNS-MESSAGE-ID' => $message['MessageId'], - 'X-AMZ-SNS-TOPIC-ARN' => $message['TopicArn'], - 'X-AMZ-SNS-SUBSCRIPTION-ARN' => "{$message['TopicArn']}:c9135db0-26c4-47ec-8998-413945fb5a96", + 'X-AMZ-SNS-MESSAGE-TYPE' => $message['Type'] ?? null, + 'X-AMZ-SNS-MESSAGE-ID' => $message['MessageId'] ?? null, + 'X-AMZ-SNS-TOPIC-ARN' => $message['TopicArn'] ?? null, + 'X-AMZ-SNS-SUBSCRIPTION-ARN' => ($message['TopicArn'] ?? null).':c9135db0-26c4-47ec-8998-413945fb5a96', ]; } } diff --git a/src/Concerns/HandlesSns.php b/src/Concerns/HandlesSns.php index 8317298..d59d325 100644 --- a/src/Concerns/HandlesSns.php +++ b/src/Concerns/HandlesSns.php @@ -52,8 +52,20 @@ public function snsMessageIsValid(Request $request): bool */ protected function getMessageValidator(Request $request) { - return App::environment(['testing', 'local']) - ? new MessageValidator(fn ($url) => $request->certificate ?: $url) - : new MessageValidator; + if (App::environment(['testing', 'local'])) { + return new MessageValidator(function ($url) use ($request) { + if ($certificate = $request->sns_certificate) { + return $certificate; + } + + if ($certificate = $request->header('X-Sns-Testing-Certificate')) { + return $certificate; + } + + return $url; + }); + } + + return new MessageValidator; } } diff --git a/tests/EventTest.php b/tests/EventTest.php index 79f9f83..8e2abb9 100644 --- a/tests/EventTest.php +++ b/tests/EventTest.php @@ -14,23 +14,19 @@ public function test_no_event_triggering_on_bad_request() { Event::fake(); - $this->json('GET', route('sns')) - ->assertSee('OK'); + $this->sendSnsMessage(route('sns'))->assertSee('OK'); Event::assertNotDispatched(SnsNotification::class); Event::assertNotDispatched(SnsSubscriptionConfirmation::class); - $this->json('GET', route('sns', ['certificate' => static::$certificate])) - ->assertSee('OK'); + $this->sendSnsMessage(route('sns'))->assertSee('OK'); Event::assertNotDispatched(SnsNotification::class); Event::assertNotDispatched(SnsSubscriptionConfirmation::class); $payload = $this->getSubscriptionConfirmationPayload(); - $this->withHeaders($this->getHeadersForMessage($payload)) - ->json('GET', route('sns', ['certificate' => static::$certificate])) - ->assertSee('OK'); + $this->sendSnsMessage(route('sns'))->assertSee('OK'); Event::assertNotDispatched(SnsNotification::class); Event::assertNotDispatched(SnsSubscriptionConfirmation::class); @@ -42,11 +38,9 @@ public function test_subscription_confirmation() $payload = $this->getSubscriptionConfirmationPayload(); - $this->withHeaders(array_merge($this->getHeadersForMessage($payload), [ - 'x-test-header' => 1, - ])) - ->json('POST', route('sns', ['certificate' => static::$certificate]), $payload) - ->assertSee('OK'); + $this->withHeaders(['x-test-header' => 1]) + ->sendSnsMessage(route('sns'), $payload) + ->assertSee('OK'); Event::assertNotDispatched(SnsNotification::class); @@ -68,11 +62,9 @@ public function test_notification_confirmation() 'sns' => true, ]); - $this->withHeaders(array_merge($this->getHeadersForMessage($payload), [ - 'x-test-header' => 1, - ])) - ->json('POST', route('sns', ['certificate' => static::$certificate]), $payload) - ->assertSee('OK'); + $this->withHeaders(['x-test-header' => 1]) + ->sendSnsMessage(route('sns'), $payload) + ->assertSee('OK'); Event::assertNotDispatched(SnsSubscriptionConfirmation::class); @@ -98,11 +90,9 @@ public function test_custom_controller_confirmation() $payload = $this->getSubscriptionConfirmationPayload(); - $this->withHeaders(array_merge($this->getHeadersForMessage($payload), [ - 'x-test-header' => 1, - ])) - ->json('POST', route('custom-sns', ['test' => 'some-string', 'certificate' => static::$certificate]), $payload) - ->assertSee('OK'); + $this->withHeaders(['x-test-header' => 1]) + ->sendSnsMessage(route('custom-sns', ['test' => 'some-string']), $payload) + ->assertSee('OK'); Event::assertNotDispatched(CustomSnsEvent::class); @@ -128,11 +118,9 @@ public function test_custom_controller_notification() 'sns' => true, ]); - $this->withHeaders(array_merge($this->getHeadersForMessage($payload), [ - 'x-test-header' => 1, - ])) - ->json('POST', route('custom-sns', ['test' => 'some-string', 'certificate' => static::$certificate]), $payload) - ->assertSee('OK'); + $this->withHeaders(['x-test-header' => 1]) + ->sendSnsMessage(route('custom-sns', ['test' => 'some-string']), $payload) + ->assertSee('OK'); Event::assertNotDispatched(CustomSubscriptionConfirmation::class); diff --git a/tests/TestCase.php b/tests/TestCase.php index bce2429..277ee18 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -9,14 +9,6 @@ class TestCase extends Orchestra { use GeneratesSnsMessages; - /** - * {@inheritdoc} - */ - public static function setUpBeforeClass(): void - { - static::initializeSsl(); - } - /** * Get package providers. * From 60d5acfc29c2be80b0329180d5d3f7eed5b6eca7 Mon Sep 17 00:00:00 2001 From: Alex Renoki Date: Sat, 13 Nov 2021 12:15:25 +0200 Subject: [PATCH 5/5] csfixing --- tests/TestCase.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index 277ee18..8919dd5 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -13,7 +13,6 @@ class TestCase extends Orchestra * Get package providers. * * @param \Illuminate\Foundation\Application $app - * * @return array */ protected function getPackageProviders($app)