1: | <?php |
2: | |
3: | declare(strict_types=1); |
4: | |
5: | namespace OpenSearch\Handlers; |
6: | |
7: | use Aws\Credentials\CredentialProvider; |
8: | use Aws\Signature\SignatureV4; |
9: | use GuzzleHttp\Psr7\Request; |
10: | use GuzzleHttp\Psr7\Uri; |
11: | use GuzzleHttp\Psr7\Utils; |
12: | use OpenSearch\ClientBuilder; |
13: | use Psr\Http\Message\RequestInterface; |
14: | use RuntimeException; |
15: | |
16: | |
17: | @trigger_error(SigV4Handler::class . ' is deprecated in 2.4.0 and will be removed in 3.0.0.', E_USER_DEPRECATED); |
18: | |
19: | |
20: | |
21: | |
22: | |
23: | |
24: | class SigV4Handler |
25: | { |
26: | |
27: | |
28: | |
29: | private $signer; |
30: | |
31: | |
32: | |
33: | private $credentialProvider; |
34: | |
35: | |
36: | |
37: | private $wrappedHandler; |
38: | |
39: | |
40: | |
41: | |
42: | |
43: | |
44: | |
45: | |
46: | |
47: | |
48: | |
49: | |
50: | |
51: | |
52: | public function __construct( |
53: | string $region, |
54: | string $service, |
55: | ?callable $credentialProvider = null, |
56: | ?callable $wrappedHandler = null |
57: | ) { |
58: | self::assertDependenciesInstalled(); |
59: | $this->signer = new SignatureV4($service, $region); |
60: | $this->wrappedHandler = $wrappedHandler |
61: | ?: ClientBuilder::defaultHandler(); |
62: | $this->credentialProvider = $credentialProvider |
63: | ?: CredentialProvider::defaultProvider(); |
64: | } |
65: | |
66: | |
67: | |
68: | |
69: | public function __invoke(array $request) |
70: | { |
71: | $creds = call_user_func($this->credentialProvider)->wait(); |
72: | |
73: | $psr7Request = $this->createPsr7Request($request); |
74: | $psr7Request = $psr7Request->withHeader('x-amz-content-sha256', Utils::hash($psr7Request->getBody(), 'sha256')); |
75: | $signedRequest = $this->signer |
76: | ->signRequest($psr7Request, $creds); |
77: | return call_user_func($this->wrappedHandler, $this->createRingRequest($signedRequest, $request)); |
78: | } |
79: | |
80: | public static function assertDependenciesInstalled(): void |
81: | { |
82: | if (!class_exists(SignatureV4::class)) { |
83: | throw new RuntimeException( |
84: | 'The AWS SDK for PHP must be installed in order to use the SigV4 signing handler' |
85: | ); |
86: | } |
87: | } |
88: | |
89: | |
90: | |
91: | |
92: | private function createPsr7Request(array $ringPhpRequest): Request |
93: | { |
94: | |
95: | |
96: | $hostKey = isset($ringPhpRequest['headers']['Host']) ? 'Host' : 'host'; |
97: | |
98: | |
99: | |
100: | $parsedUrl = parse_url($ringPhpRequest['headers'][$hostKey][0]); |
101: | if (isset($parsedUrl['host'])) { |
102: | $ringPhpRequest['headers'][$hostKey][0] = $parsedUrl['host']; |
103: | } |
104: | |
105: | |
106: | $uri = (new Uri($ringPhpRequest['uri'])) |
107: | ->withScheme($ringPhpRequest['scheme']) |
108: | ->withHost($ringPhpRequest['headers'][$hostKey][0]); |
109: | if (isset($ringPhpRequest['query_string'])) { |
110: | $uri = $uri->withQuery($ringPhpRequest['query_string']); |
111: | } |
112: | |
113: | |
114: | return new Request( |
115: | $ringPhpRequest['http_method'], |
116: | $uri, |
117: | $ringPhpRequest['headers'], |
118: | $ringPhpRequest['body'] |
119: | ); |
120: | } |
121: | |
122: | |
123: | |
124: | |
125: | |
126: | |
127: | private function createRingRequest(RequestInterface $request, array $originalRequest): array |
128: | { |
129: | $uri = $request->getUri(); |
130: | $body = (string) $request->getBody(); |
131: | |
132: | |
133: | |
134: | if (empty($body)) { |
135: | $body = null; |
136: | } |
137: | |
138: | |
139: | $client = $originalRequest['client']; |
140: | unset($client['curl'][CURLOPT_PORT]); |
141: | |
142: | $ringRequest = [ |
143: | 'http_method' => $request->getMethod(), |
144: | 'scheme' => $uri->getScheme(), |
145: | 'uri' => $uri->getPath(), |
146: | 'body' => $body, |
147: | 'headers' => $request->getHeaders(), |
148: | 'client' => $client |
149: | ]; |
150: | if ($uri->getQuery()) { |
151: | $ringRequest['query_string'] = $uri->getQuery(); |
152: | } |
153: | |
154: | return $ringRequest; |
155: | } |
156: | } |
157: | |