Skip to content

Commit

Permalink
Merge branch 'sns-message-validate-url'
Browse files Browse the repository at this point in the history
  • Loading branch information
mtdowling committed Jul 31, 2014
2 parents 77236ce + adc5fea commit a6d82f5
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 10 deletions.
17 changes: 14 additions & 3 deletions src/Aws/Sns/MessageValidator/MessageValidator.php
Expand Up @@ -64,9 +64,7 @@ public function validate(Message $message)
{
// Get the cert's URL and ensure it is from AWS
$certUrl = Url::factory($message->get('SigningCertURL'));
if ('.amazonaws.com' != substr($certUrl->getHost(), -14)) {
throw new CertificateFromUnrecognizedSourceException();
}
$this->validateUrl($certUrl);

// Get the cert itself and extract the public key
$certificate = $this->client->get((string) $certUrl)->send()->getBody();
Expand All @@ -83,6 +81,19 @@ public function validate(Message $message)
}
}

private function validateUrl(Url $url)
{
// The host must match the following pattern
$hostPattern = '/^sns\.[a-zA-Z0-9\-]{3,}\.amazonaws\.com(\.cn)?$/';

if ($url->getScheme() !== 'https' ||
substr($url, -4) !== '.pem' ||
!preg_match($hostPattern, $url->getHost())
) {
throw new CertificateFromUnrecognizedSourceException();
}
}

/**
* Determines if a message is valid and that is was delivered by AWS. This method does not throw exceptions and
* returns a simple boolean value.
Expand Down
47 changes: 40 additions & 7 deletions tests/Aws/Tests/Sns/MessageValidator/MessageValidatorTest.php
Expand Up @@ -16,9 +16,11 @@

namespace Aws\Tests\Sns\MessageValidator;

use Aws\Sns\MessageValidator\Exception\CertificateFromUnrecognizedSourceException;
use Aws\Sns\MessageValidator\Message;
use Aws\Sns\MessageValidator\MessageValidator;
use Guzzle\Common\Collection;
use Guzzle\Http\Url;
use Guzzle\Plugin\Mock\MockPlugin;
use Guzzle\Http\Message\Response;
use Guzzle\Http\Client;
Expand All @@ -42,13 +44,44 @@ public function testIsValidReturnsFalseOnFailedValidation()
$this->assertFalse($validator->isValid($message));
}

public function testValidateFailsWhenCertUrlDoesNotMatchAws()
public function urlProvider()
{
$this->setExpectedException('Aws\Sns\MessageValidator\Exception\CertificateFromUnrecognizedSourceException');
return array(
array('https://sns.us-east-1.amazonaws.com/key.pem', false),
array('https://sns.us-west-2.amazonaws.com/key.pem', false),
array('https://sns.us-west-2.amazonaws.com/key.pem', false),
array('https://sns.cn-north-1.amazonaws.com.cn/SimpleNotificationService-foo.pem', false),
array('https://sns.us-gov-west-1.amazonaws.com/abc.pem', false),
// Failure cases
array('http://sns.us-gov-west-1.amazonaws.com/abc.pem', true),
array('https://sns.us-gov-west-1.amazonaws.com/abc', true),
array('https://sns.amazonaws.com/abc', true),
array('https://s3.sns.amazonaws.com/abc.pem', true),
array('https://s3.amazonaws.com/sns/abc.pem', true),
array('https://sns.us-west-2.amazon.com/key.pem', true),
array('https://sns.s3.amazonaws.com/key.pem', true),
);
}

/**
* @dataProvider urlProvider
*/
public function testValidateFailsWhenCertUrlDoesNotMatchAws($url, $throws)
{
$validator = new MessageValidator();
$message = new Message(new Collection());
$validator->validate($message);
$m = new \ReflectionMethod($validator, 'validateUrl');
$m->setAccessible(true);

try {
$m->invoke($validator, Url::factory($url));
if ($throws) {
$this->fail('URL was invalid but did not fail the test');
}
} catch (CertificateFromUnrecognizedSourceException $e) {
if (!$throws) {
$this->fail('URL was supposed to be valid, but failed test');
}
}
}

public function testValidateFailsWhenCannotDeterminePublicKey()
Expand All @@ -59,7 +92,7 @@ public function testValidateFailsWhenCannotDeterminePublicKey()
$client = $this->getMockClient();
$validator = new MessageValidator($client);

$message = new Message(new Collection(array('SigningCertURL' => 'https://foo.amazonaws.com/bar')));
$message = new Message(new Collection(array('SigningCertURL' => 'https://sns.foo.amazonaws.com/bar.pem')));
$validator->validate($message);
}

Expand All @@ -75,7 +108,7 @@ public function testValidateFailsWhenMessageIsInvalid()
$validator = new MessageValidator($client);

$message = new Message(new Collection(array(
'SigningCertURL' => 'https://foo.amazonaws.com/bar',
'SigningCertURL' => 'https://sns.foo.amazonaws.com/bar.pem',
'Signature' => $signature,
)));
$validator->validate($message);
Expand All @@ -90,7 +123,7 @@ public function testValidateSucceedsWhenMessageIsValid()
'Timestamp' => time(),
'TopicArn' => 'baz',
'Type' => 'Notification',
'SigningCertURL' => 'https://foo.amazonaws.com/bar',
'SigningCertURL' => 'https://sns.us-west-2.amazonaws.com/bar.pem',
'Signature' => '',
));

Expand Down

0 comments on commit a6d82f5

Please sign in to comment.