Skip to content

Commit

Permalink
enhancement: update to crt signing config
Browse files Browse the repository at this point in the history
  • Loading branch information
Sean O'Brien committed Jul 18, 2024
1 parent e832e59 commit ce1ecad
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 4 deletions.
7 changes: 7 additions & 0 deletions .changes/nextrelease/crt-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"type": "enhancement",
"category": "",
"description": "Updates CRT signing config region handling"
}
]
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"require": {
"php": ">=7.2.5",
"guzzlehttp/guzzle": "^6.5.8 || ^7.4.5",
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5 <2.9.0",
"guzzlehttp/promises": "^1.4.0 || ^2.0",
"mtdowling/jmespath.php": "^2.6",
"ext-pcre": "*",
Expand Down
25 changes: 24 additions & 1 deletion src/AwsClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class AwsClient implements AwsClientInterface
/** @var string */
private $region;

/** @var string */
private $signingRegionSet;

/** @var string */
private $endpoint;

Expand Down Expand Up @@ -240,6 +243,7 @@ public function __construct(array $args)
$this->credentialProvider = $config['credentials'];
$this->tokenProvider = $config['token'];
$this->region = $config['region'] ?? null;
$this->signingRegionSet = $config['sigv4a_signing_region_set'] ?? null;
$this->config = $config['config'];
$this->setClientBuiltIns($args);
$this->clientContextParams = $this->setClientContextParams($args);
Expand Down Expand Up @@ -422,6 +426,7 @@ private function addSignatureMiddleware(array $args)
$signatureVersion = $this->config['signature_version'];
$name = $this->config['signing_name'];
$region = $this->config['signing_region'];
$signingRegionSet = $this->signingRegionSet;

if (isset($args['signature_version'])
|| isset($this->config['configured_signature_version'])
Expand All @@ -433,7 +438,15 @@ private function addSignatureMiddleware(array $args)

$resolver = static function (
CommandInterface $c
) use ($api, $provider, $name, $region, $signatureVersion, $configuredSignatureVersion) {
) use (
$api,
$provider,
$name,
$region,
$signatureVersion,
$configuredSignatureVersion,
$signingRegionSet
) {
if (!$configuredSignatureVersion) {
if (!empty($c['@context']['signing_region'])) {
$region = $c['@context']['signing_region'];
Expand All @@ -459,6 +472,16 @@ private function addSignatureMiddleware(array $args)
}
}

if ($signatureVersion === 'v4a') {
$commandSigningRegionSet = !empty($c['@context']['signing_region_set'])
? implode(', ', $c['@context']['signing_region_set'])
: null;

$region = $signingRegionSet
?? $commandSigningRegionSet
?? $region;
}

return SignatureProvider::resolve($provider, $signatureVersion, $name, $region);
};
$this->handlerList->appendSign(
Expand Down
28 changes: 28 additions & 0 deletions src/ClientResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,13 @@ class ClientResolver
'doc' => 'Set to false to disable checking for shared aws config files usually located in \'~/.aws/config\' and \'~/.aws/credentials\'. This will be ignored if you set the \'profile\' setting.',
'default' => true,
],
'sigv4a_signing_region_set' => [
'type' => 'value',
'valid' => ['array', 'string'],
'doc' => 'A comma-delimited list of supported regions sent in sigv4a requests.',
'fn' => [__CLASS__, '_apply_sigv4a_signing_region_set'],
'default' => [__CLASS__, '_default_sigv4a_signing_region_set']
]
];

/**
Expand Down Expand Up @@ -1240,6 +1247,27 @@ public static function _default_endpoint(array &$args)
return $value;
}

public static function _apply_sigv4a_signing_region_set($value, array &$args)
{
if (empty($value)) {
$args['sigv4a_signing_region_set'] = null;
}
elseif (is_array($value)) {
$args['sigv4a_signing_region_set'] = implode(', ', $value);
} else {
$args['sigv4a_signing_region_set'] = $value;
}
}

public static function _default_sigv4a_signing_region_set(array &$args)
{
return ConfigurationResolver::resolve(
'sigv4a_signing_region_set',
'',
'string'
);
}

public static function _apply_region($value, array &$args)
{
if (empty($value)) {
Expand Down
2 changes: 1 addition & 1 deletion src/Signature/S3SignatureV4.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ protected function signWithV4a(
'signature_type' => SignatureType::HTTP_REQUEST_HEADERS,
'credentials_provider' => $credentials_provider,
'signed_body_value' => $this->getPayload($request),
'region' => "*",
'region' => $this->region,
'should_normalize_uri_path' => false,
'use_double_uri_encode' => false,
'service' => $signingService,
Expand Down
2 changes: 1 addition & 1 deletion src/Signature/SignatureV4.php
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ protected function signWithV4a(
'signed_body_value' => $this->getPayload($request),
'should_normalize_uri_path' => true,
'use_double_uri_encode' => true,
'region' => "*",
'region' => $this->region,
'service' => $signingService,
'date' => time(),
]);
Expand Down
128 changes: 128 additions & 0 deletions tests/AwsClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,134 @@ public function testAppliesConfiguredSignatureVersionViaClientConfig() {
$client->foo();
}

/** @dataProvider signingRegionSetProvider */
public function testSigningRegionSetResolution(
$command,
$env,
$ini,
$clientSetting,
$expected
){
if (!extension_loaded('awscrt')) {
$this->markTestSkipped();
}

if ($env) {
putenv('AWS_SIGV4A_SIGNING_REGION_SET=' . $env);
}

if ($ini) {
$dir = sys_get_temp_dir() . '/.aws';
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
}
file_put_contents($dir . '/config', $ini);
$home = getenv('HOME');
putenv('HOME=' . dirname($dir));
}

$client = $this->createClient(
[
'metadata' => [
'signatureVersion' => 'v4a',
],
'operations' => [
'Foo' => [
'http' => ['method' => 'POST'],
],
],
],
[
'handler' => function (
CommandInterface $command,
RequestInterface $request
) use ($expected) {
$this->assertEquals($expected, $request->getHeaderLine('x-amz-region-set'));
return new Result;
},
'signature_version' => 'v4a',
'region' => 'us-west-2',
'sigv4a_signing_region_set' => $clientSetting ?? null
]
);

$client->foo([
'@context' => [
'signing_region_set' => $command ?? null
]
]);

if ($ini) {
unlink($dir . '/config');
putenv("HOME=$home");
}

putenv('AWS_SIGV4A_SIGNING_REGION_SET=');

}

public function signingRegionSetProvider()
{
return [
[null, null, null, null, 'us-west-2'],
[['*'], null, null, null, '*'],
[null, '*', null, null, '*'],
[
null,
null,
<<<EOT
[default]
sigv4a_signing_region_set = *
EOT
,
null,
'*'
],
[
null, null, null, '*', '*'
],
[null, 'us-west-2', null, null, 'us-west-2'],
[
null,
null,
<<<EOT
[default]
sigv4a_signing_region_set = us-west-2
EOT
,
null,
'us-west-2'
],
[null, null, null, 'us-west-2', 'us-west-2'],
[null, '*', null, 'us-west-2', 'us-west-2'],
[
null,
null,
<<<EOT
[default]
sigv4a_signing_region_set = *
EOT
,
'us-west-2',
'us-west-2'
],
[['us-west-2', 'us-east-1'], null, null, null, 'us-west-2, us-east-1'],
[null, "us-west-2, us-east-1", null , null, 'us-west-2, us-east-1'],
[
null,
null,
<<<EOT
[default]
sigv4a_signing_region_set = us-west-2, us-east-1
EOT
,
null,
'us-west-2, us-east-1'
],
[null, null, null, 'us-west-2, us-east-1', 'us-west-2, us-east-1']
];
}

private function createHttpsEndpointClient(array $service = [], array $config = [])
{
$apiProvider = function () use ($service) {
Expand Down

0 comments on commit ce1ecad

Please sign in to comment.