diff --git a/composer.json b/composer.json index d55ab33..5a210a2 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,8 @@ }, "require-dev": { "roave/security-advisories": "dev-master", - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^7.0", + "guzzlehttp/guzzle": "^6.3" }, "suggest": { "csa/guzzle-bundle": "Allow to unseal and verify response from sapient api automatically." diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 948a66a..9e48bcf 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -33,6 +33,7 @@ public function getConfigTreeBuilder() ->children() ->booleanNode('unseal')->defaultFalse()->end() ->booleanNode('verify')->defaultFalse()->end() + ->scalarNode('requester_name')->defaultFalse()->end() ->end() ->end() ->arrayNode('sealing_public_keys') diff --git a/src/DependencyInjection/SapientExtension.php b/src/DependencyInjection/SapientExtension.php index ce182b5..1877e18 100644 --- a/src/DependencyInjection/SapientExtension.php +++ b/src/DependencyInjection/SapientExtension.php @@ -45,6 +45,11 @@ public function load(array $configs, ContainerBuilder $container) if ($config['guzzle_middleware']['unseal']) { $loader->load('guzzle_middleware/unseal_response.yml'); } + + if ($config['guzzle_middleware']['requester_name']) { + $container->setParameter('sapient.guzzle_middleware.requester_name', $config['guzzle_middleware']['requester_name']); + $loader->load('guzzle_middleware/requester_header.yml'); + } } } } diff --git a/src/GuzzleHttp/Middleware/RequesterHeaderMiddleware.php b/src/GuzzleHttp/Middleware/RequesterHeaderMiddleware.php new file mode 100644 index 0000000..30b3f74 --- /dev/null +++ b/src/GuzzleHttp/Middleware/RequesterHeaderMiddleware.php @@ -0,0 +1,33 @@ +requesterName = $requesterName; + } + + public function __invoke(callable $handler): callable + { + return function(RequestInterface $request, array $options) use ($handler) { + return $handler( + $request->withHeader(PublicKeyGetter::HEADER_REQUESTER, $this->requesterName), + $options + ); + }; + } +} diff --git a/src/Resources/config/guzzle_middleware/requester_header.yml b/src/Resources/config/guzzle_middleware/requester_header.yml new file mode 100644 index 0000000..7f775f2 --- /dev/null +++ b/src/Resources/config/guzzle_middleware/requester_header.yml @@ -0,0 +1,6 @@ +services: + lepiaf\SapientBundle\GuzzleHttp\Middleware\RequesterHeaderMiddleware: + arguments: + - '%sapient.guzzle_middleware.requester_name%' + tags: + - { name: 'csa_guzzle.middleware', alias: 'requester_name' } diff --git a/src/Resources/doc/reference.rst b/src/Resources/doc/reference.rst index 25c1cf8..984d162 100644 --- a/src/Resources/doc/reference.rst +++ b/src/Resources/doc/reference.rst @@ -16,6 +16,7 @@ Reference guzzle_middleware: unseal: boolean verify: boolean + requester_name: string sealing_public_keys: - name: string @@ -104,6 +105,16 @@ If enable, it will activate Guzzle middleware that verify signature in response. Before enabling this option, you must configure verifying_public_keys_ array. +.. guzzle_middleware.requester_name: +guzzle_middleware.requester_name +------------------------ + +This Guzzle middleware will add a header ``Sapient-Requester`` automatically on each request. This +header is used by recipient to choose the right key to encrypt response. + +It is optional but highly recommended. If not enable, you must add header manually in +Guzzle client configuration. + .. sealing_public_keys: sealing_public_keys ------------------- diff --git a/src/Service/PublicKeyGetter.php b/src/Service/PublicKeyGetter.php index 4bee0be..53d05f5 100644 --- a/src/Service/PublicKeyGetter.php +++ b/src/Service/PublicKeyGetter.php @@ -14,7 +14,7 @@ class PublicKeyGetter { public const HEADER_SIGNER = 'Sapient-Signer'; - private const HEADER_REQUESTER = 'Sapient-Requester'; + public const HEADER_REQUESTER = 'Sapient-Requester'; /** * @var array diff --git a/tests/GuzzleHttp/Middleware/RequesterHeaderMiddlewareTest.php b/tests/GuzzleHttp/Middleware/RequesterHeaderMiddlewareTest.php new file mode 100644 index 0000000..1ba76f9 --- /dev/null +++ b/tests/GuzzleHttp/Middleware/RequesterHeaderMiddlewareTest.php @@ -0,0 +1,31 @@ +assertTrue($request->hasHeader('Sapient-Requester')); + $this->assertSame(['client-bob'], $request->getHeader('Sapient-Requester')); + + return new Response(200); + }, + ]); + $handler = HandlerStack::create($mockHandler); + $handler->push(new RequesterHeaderMiddleware('client-bob')); + $client = new Client(['handler' => $handler]); + + $client->request('GET', 'http://api.example.com/api/ping'); + } +}