зеркало из
1
0
Форкнуть 0

Add support to sas authorization (#958)

* add sas filter

* typos

* typos

* - Change minimum azure-storage version to 0.15.0
- Change createWrapService to static method and reference it by self to
  avoid non object context error

* - Revert changes to composer.lock file to allow support for php 5.6
- Fix $this in non object context error

* - Revert azure back to version 19 and update lock

* - Altered __construct comments
- Added getNamespace method to return private _namespace property
- Changed getFilter comments

* - Configure tests inline with new code changes

* - Emulate tests that require environment variables to be set
This commit is contained in:
polkfarody 2017-11-28 06:34:29 +11:00 коммит произвёл Sergey Shandar
Родитель f5d4efa45c
Коммит 0d3ce5b0c3
8 изменённых файлов: 530 добавлений и 361 удалений

425
composer.lock сгенерированный

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,112 @@
<?php
/**
* LICENSE: Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP version 5
*
* @category Microsoft
*
* @author Azure PHP SDK <azurephpsdk@microsoft.com>
* @copyright 2012 Microsoft Corporation
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
*
* @link https://github.com/windowsazure/azure-sdk-for-php
*/
namespace WindowsAzure\Common\Internal\Filters;
use WindowsAzure\Common\Internal\Resources;
use WindowsAzure\Common\Internal\Utilities;
use WindowsAzure\Common\Internal\IServiceFilter;
use WindowsAzure\Common\Internal\Http\IHttpClient;
use WindowsAzure\ServiceBus\Internal\WrapTokenManager;
use WindowsAzure\ServiceBus\Internal\IWrap;
use Psr\Http\Message\ResponseInterface;
/**
* Adds SAS authentication header to the http request object.
*
* @category Microsoft
*
* @author Azure PHP SDK <azurephpsdk@microsoft.com>
* @copyright 2012 Microsoft Corporation
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
*
* @version Release: 0.5.0_2016-11
*
* @link https://github.com/windowsazure/azure-sdk-for-php
*/
class SASFilter implements IServiceFilter {
private $sharedAccessKeyName;
private $sharedAccessKey;
public function __construct(
$sharedAccessKeyName,
$sharedAccessKey
) {
$this->sharedAccessKeyName = $sharedAccessKeyName;
$this->sharedAccessKey = $sharedAccessKey;
}
/**
* Adds WRAP authentication header to the request headers.
*
* @param IHttpClient $request HTTP channel object
*
* @return IHttpClient
*/
public function handleRequest(IHttpClient $request) {
$token = $this->getAuthorization(
$request->getUrl(),
$this->sharedAccessKeyName,
$this->sharedAccessKey
);
$request->setHeader(Resources::AUTHENTICATION, $token);
return $request;
}
/**
* @param $url
* @param $policy
* @param $key
*/
private function getAuthorization($url, $sharedAccessKeyName, $sharedAccessKey) {
$expiry = time() + 3600;
$encodedUrl = Utilities::lowerUrlencode($url);
$scope = $encodedUrl . "\n" . $expiry;
$signature = base64_encode(hash_hmac('sha256', $scope, $sharedAccessKey, true));
return sprintf(Resources::SAS_AUTHORIZATION,
Utilities::lowerUrlencode($signature),
$expiry,
$sharedAccessKeyName,
$encodedUrl
);
}
/**
* Returns the original response.
*
* @param IHttpClient $request A HTTP channel object
* @param ResponseInterface $response A HTTP response object
*
* @return ResponseInterface
*/
public function handleResponse(IHttpClient $request, ResponseInterface $response) {
return $response;
}
}

Просмотреть файл

@ -38,8 +38,7 @@ namespace WindowsAzure\Common\Internal;
*
* @link https://github.com/windowsazure/azure-sdk-for-php
*/
class Resources
{
class Resources {
// @codingStandardsIgnoreStart
// Connection strings
@ -64,6 +63,8 @@ class Resources
const SERVICE_BUS_ENDPOINT_NAME = 'Endpoint';
const SHARED_SECRET_ISSUER_NAME = 'SharedSecretIssuer';
const SHARED_SECRET_VALUE_NAME = 'SharedSecretValue';
const SHARED_SHARED_ACCESS_KEY_NAME = 'SharedAccessKeyName';
const SHARED_SHARED_ACCESS_KEY = 'SharedAccessKey';
const STS_ENDPOINT_NAME = 'StsEndpoint';
const MEDIA_SERVICES_ENDPOINT_URI_NAME = 'MediaServicesEndpoint';
const MEDIA_SERVICES_ACCOUNT_NAME = 'AccountName';
@ -169,6 +170,7 @@ class Resources
const DATE = 'date';
const AUTHENTICATION = 'authorization';
const WRAP_AUTHORIZATION = 'WRAP access_token="%s"';
const SAS_AUTHORIZATION = 'SharedAccessSignature sig=%s&se=%s&skn=%s&sr=%s';
const CONTENT_ENCODING = 'content-encoding';
const CONTENT_LANGUAGE = 'content-language';
const CONTENT_LENGTH = 'content-length';

Просмотреть файл

@ -25,6 +25,10 @@
namespace WindowsAzure\Common\Internal;
use WindowsAzure\Common\Internal\Http\HttpClient;
use WindowsAzure\ServiceBus\Internal\WrapRestProxy;
use WindowsAzure\Common\Internal\Filters\WrapFilter;
use WindowsAzure\Common\Internal\Filters\SASFilter;
/**
* Represents the settings used to sign and access a request against the service
* bus.
@ -39,8 +43,7 @@ namespace WindowsAzure\Common\Internal;
*
* @link https://github.com/windowsazure/azure-sdk-for-php
*/
class ServiceBusSettings extends ServiceSettings
{
class ServiceBusSettings extends ServiceSettings {
/**
* @var string
*/
@ -94,6 +97,16 @@ class ServiceBusSettings extends ServiceSettings
*/
private static $_wrapEndpointUriSetting;
/**
* @var string
*/
private static $_sasKeyNameSetting;
/**
* @var string
*/
private static $_sasKeySetting;
/**
* @var bool
*/
@ -109,8 +122,7 @@ class ServiceBusSettings extends ServiceSettings
/**
* Initializes static members of the class.
*/
protected static function init()
{
protected static function init() {
self::$_serviceBusEndpointSetting = self::settingWithFunc(
Resources::SERVICE_BUS_ENDPOINT_NAME,
Validate::getIsValidUri()
@ -124,6 +136,14 @@ class ServiceBusSettings extends ServiceSettings
Resources::SHARED_SECRET_VALUE_NAME
);
self::$_sasKeyNameSetting = self::setting(
Resources::SHARED_SHARED_ACCESS_KEY_NAME
);
self::$_sasKeySetting = self::setting(
Resources::SHARED_SHARED_ACCESS_KEY
);
self::$_wrapEndpointUriSetting = self::settingWithFunc(
Resources::STS_ENDPOINT_NAME,
Validate::getIsValidUri()
@ -132,32 +152,134 @@ class ServiceBusSettings extends ServiceSettings
self::$validSettingKeys[] = Resources::SERVICE_BUS_ENDPOINT_NAME;
self::$validSettingKeys[] = Resources::SHARED_SECRET_ISSUER_NAME;
self::$validSettingKeys[] = Resources::SHARED_SECRET_VALUE_NAME;
self::$validSettingKeys[] = Resources::SHARED_SHARED_ACCESS_KEY_NAME;
self::$validSettingKeys[] = Resources::SHARED_SHARED_ACCESS_KEY;
self::$validSettingKeys[] = Resources::STS_ENDPOINT_NAME;
}
/**
* Creates new Service Bus settings instance.
*
* @param string $serviceBusEndpoint The Service Bus endpoint uri
* @param string $namespace The service namespace
* @param $wrapEndpointUri
* @param string $wrapName The wrap name
* @param string $wrapPassword The wrap password
* @param type $serviceBusEndpoint The Service Bus endpoint uri
* @param type $filter
*/
public function __construct(
$serviceBusEndpoint,
$namespace,
$wrapEndpointUri,
$wrapName,
$wrapPassword
$filter
) {
$this->_namespace = $namespace;
$this->_serviceBusEndpointUri = $serviceBusEndpoint;
$this->_wrapEndpointUri = $wrapEndpointUri;
$this->_wrapName = $wrapName;
$this->_wrapPassword = $wrapPassword;
$this->_filter = $filter;
}
/**
* @param array $tokenizedSettings
* @param string $connectionString
*/
private static function createServiceBusWithWrapAuthentication(array $tokenizedSettings, $connectionString = '') {
$required = [
self::$_serviceBusEndpointSetting,
self::$_wrapNameSetting,
self::$_wrapPasswordSetting,
];
$optional = [
self::$_wrapEndpointUriSetting,
];
$matchedSpecs = self::getMatchedSpecs($tokenizedSettings, $required, $optional, $connectionString);
$endpoint = Utilities::tryGetValueInsensitive(
Resources::SERVICE_BUS_ENDPOINT_NAME,
$tokenizedSettings
);
// Parse the namespace part from the URI
$namespace = explode('.', parse_url($endpoint, PHP_URL_HOST));
$namespace = $namespace[0];
$wrapEndpointUri = Utilities::tryGetValueInsensitive(
Resources::STS_ENDPOINT_NAME,
$tokenizedSettings,
sprintf(Resources::WRAP_ENDPOINT_URI_FORMAT, $namespace)
);
$issuerName = Utilities::tryGetValueInsensitive(
Resources::SHARED_SECRET_ISSUER_NAME,
$tokenizedSettings
);
$issuerValue = Utilities::tryGetValueInsensitive(
Resources::SHARED_SECRET_VALUE_NAME,
$tokenizedSettings
);
return new self($endpoint, new WrapFilter(
$wrapEndpointUri,
$issuerName,
$issuerValue,
self::createWrapService($wrapEndpointUri)
));
}
/**
* @param array $tokenizedSettings
* @param string $connectionString
*/
private static function createServiceBusWithSasAuthentication(array $tokenizedSettings, $connectionString = '') {
$required = [
self::$_serviceBusEndpointSetting,
self::$_sasKeyNameSetting,
self::$_sasKeySetting,
];
$optional = [
self::$_wrapEndpointUriSetting,
];
$matchedSpecs = self::getMatchedSpecs($tokenizedSettings, $required, $optional, $connectionString);
$endpoint = Utilities::tryGetValueInsensitive(
Resources::SERVICE_BUS_ENDPOINT_NAME,
$tokenizedSettings
);
$sharedAccessKeyName = Utilities::tryGetValueInsensitive(
Resources::SHARED_SHARED_ACCESS_KEY_NAME,
$tokenizedSettings
);
$sharedAccessKey = Utilities::tryGetValueInsensitive(
Resources::SHARED_SHARED_ACCESS_KEY,
$tokenizedSettings
);
return new self($endpoint, new SASFilter(
$sharedAccessKeyName,
$sharedAccessKey
));
}
/**
* @param $wrapEndpointUri
* @return mixed
*/
protected static function createWrapService($wrapEndpointUri) {
$httpClient = new HttpClient();
$wrapWrapper = new WrapRestProxy($httpClient, $wrapEndpointUri);
return $wrapWrapper;
}
/**
* @param $tokenizedSettings
* @param $required
* @param array $optional
* @param string $connectionString
* @return mixed
*/
private static function getMatchedSpecs($tokenizedSettings, $required, $optional = [], $connectionString = '') {
$matchedSpecs = self::matchedSpecification(
$tokenizedSettings,
self::allRequired(...$required),
self::optional(...$optional)
);
if (!$matchedSpecs) {
self::noMatch($connectionString);
}
return $matchedSpecs;
}
/**
* Creates a ServiceBusSettings object from the given connection string.
*
@ -165,54 +287,13 @@ class ServiceBusSettings extends ServiceSettings
*
* @return ServiceBusSettings|void
*/
public static function createFromConnectionString($connectionString)
{
public static function createFromConnectionString($connectionString) {
$tokenizedSettings = self::parseAndValidateKeys($connectionString);
$matchedSpecs = self::matchedSpecification(
$tokenizedSettings,
self::allRequired(
self::$_serviceBusEndpointSetting,
self::$_wrapNameSetting,
self::$_wrapPasswordSetting
),
self::optional(self::$_wrapEndpointUriSetting)
);
if ($matchedSpecs) {
$endpoint = Utilities::tryGetValueInsensitive(
Resources::SERVICE_BUS_ENDPOINT_NAME,
$tokenizedSettings
);
// Parse the namespace part from the URI
$namespace = explode('.', parse_url($endpoint, PHP_URL_HOST));
$namespace = $namespace[0];
$wrapEndpointUri = Utilities::tryGetValueInsensitive(
Resources::STS_ENDPOINT_NAME,
$tokenizedSettings,
sprintf(Resources::WRAP_ENDPOINT_URI_FORMAT, $namespace)
);
$issuerName = Utilities::tryGetValueInsensitive(
Resources::SHARED_SECRET_ISSUER_NAME,
$tokenizedSettings
);
$issuerValue = Utilities::tryGetValueInsensitive(
Resources::SHARED_SECRET_VALUE_NAME,
$tokenizedSettings
);
return new self(
$endpoint,
$namespace,
$wrapEndpointUri,
$issuerName,
$issuerValue
);
if (array_key_exists(Resources::SHARED_SHARED_ACCESS_KEY_NAME, $tokenizedSettings)) {
return self::createServiceBusWithSasAuthentication($tokenizedSettings, $connectionString);
}
self::noMatch($connectionString);
return null;
return self::createServiceBusWithWrapAuthentication($tokenizedSettings, $connectionString);
}
/**
@ -220,8 +301,7 @@ class ServiceBusSettings extends ServiceSettings
*
* @return string
*/
public function getServiceBusEndpointUri()
{
public function getServiceBusEndpointUri() {
return $this->_serviceBusEndpointUri;
}
@ -230,8 +310,7 @@ class ServiceBusSettings extends ServiceSettings
*
* @return string
*/
public function getWrapEndpointUri()
{
public function getWrapEndpointUri() {
return $this->_wrapEndpointUri;
}
@ -240,8 +319,7 @@ class ServiceBusSettings extends ServiceSettings
*
* @return string
*/
public function getWrapName()
{
public function getWrapName() {
return $this->_wrapName;
}
@ -250,18 +328,25 @@ class ServiceBusSettings extends ServiceSettings
*
* @return string
*/
public function getWrapPassword()
{
public function getWrapPassword() {
return $this->_wrapPassword;
}
/**
* Gets the namespace name.
* Gets the filter.
*
* @return string
*/
public function getNamespace()
{
public function getFilter() {
return $this->_filter;
}
/**
* Depricated!
* Namespace is now included in the uri.
* @return string
*/
public function getNamespace() {
return $this->_namespace;
}
}

Просмотреть файл

@ -719,4 +719,12 @@ class Utilities
return $result;
}
public static function lowerUrlencode($str)
{
return preg_replace_callback('/%[0-9A-F]{2}/',
function (array $matches) {
return strtolower($matches[0]);
}, urlencode($str));
}
}

Просмотреть файл

@ -235,14 +235,9 @@ class ServicesBuilder
$headersFilter = new HeadersFilter($headers);
$serviceBusWrapper = $serviceBusWrapper->withFilter($headersFilter);
$wrapFilter = new WrapFilter(
$settings->getWrapEndpointUri(),
$settings->getWrapName(),
$settings->getWrapPassword(),
$this->createWrapService($settings->getWrapEndpointUri())
);
$filter = $settings->getFilter();
return $serviceBusWrapper->withFilter($wrapFilter);
return $serviceBusWrapper->withFilter($filter);
}
/**

Просмотреть файл

@ -11,7 +11,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
* PHP version 5
*
* @category Microsoft
@ -27,6 +27,7 @@ namespace Tests\unit\WindowsAzure\Common\Internal;
use WindowsAzure\Common\Internal\ServiceBusSettings;
use WindowsAzure\Common\Internal\Resources;
use WindowsAzure\Common\Internal\Filters\WrapFilter;
/**
* Unit tests for class ServiceBusSettings.
@ -66,22 +67,19 @@ class ServiceBusSettingsTest extends \PHPUnit_Framework_TestCase
public function testCreateFromConnectionStringWithServiceBusAutomaticCase()
{
// Setup
$expectedNamespace = 'mynamespace';
$expectedServiceBusEndpoint = "https://$expectedNamespace.servicebus.windows.net";
$namespace = 'mynamespace';
$expectedServiceBusEndpoint = "https://$namespace.servicebus.windows.net";
$expectedWrapName = 'myname';
$expectedWrapPassword = 'mypassword';
$expectedWrapEndpointUri = "https://$expectedNamespace-sb.accesscontrol.windows.net/WRAPv0.9";
$expectedWrapEndpointUri = "https://$namespace-sb.accesscontrol.windows.net/WRAPv0.9";
$connectionString = "Endpoint=$expectedServiceBusEndpoint;SharedSecretIssuer=$expectedWrapName;SharedSecretValue=$expectedWrapPassword";
// Test
$actual = ServiceBusSettings::createFromConnectionString($connectionString);
// Assert
$this->assertEquals($expectedNamespace, $actual->getNamespace());
$this->assertInstanceOf('WindowsAzure\Common\Internal\IServiceFilter', $actual->getFilter());
$this->assertEquals($expectedServiceBusEndpoint, $actual->getServiceBusEndpointUri());
$this->assertEquals($expectedWrapName, $actual->getWrapName());
$this->assertEquals($expectedWrapPassword, $actual->getWrapPassword());
$this->assertEquals($expectedWrapEndpointUri, $actual->getWrapEndpointUri());
}
/**
@ -102,6 +100,7 @@ class ServiceBusSettingsTest extends \PHPUnit_Framework_TestCase
// Setup
$connectionString = 'SharedSecretIssuer=name;SharedSecretValue=password';
$expectedMsg = sprintf(Resources::MISSING_CONNECTION_STRING_SETTINGS, $connectionString);
$this->setExpectedException('\RuntimeException', $expectedMsg);
// Test
@ -144,7 +143,7 @@ class ServiceBusSettingsTest extends \PHPUnit_Framework_TestCase
{
// Setup
$expected = 'serviceBusEndpointUri';
$setting = new ServiceBusSettings($expected, null, null, null, null);
$setting = new ServiceBusSettings($expected, null);
// Test
$actual = $setting->getServiceBusEndpointUri();
@ -154,65 +153,16 @@ class ServiceBusSettingsTest extends \PHPUnit_Framework_TestCase
}
/**
* @covers \WindowsAzure\Common\Internal\ServiceBusSettings::getNamespace
* @covers \WindowsAzure\Common\Internal\ServiceBusSettings::getFilter
*/
public function testGetNamespace()
public function testGetFilter()
{
// Setup
$expected = 'namespace';
$setting = new ServiceBusSettings(null, $expected, null, null, null);
$expected = 'filter';
$setting = new ServiceBusSettings(null, $expected);
// Test
$actual = $setting->getNamespace();
// Assert
$this->assertEquals($expected, $actual);
}
/**
* @covers \WindowsAzure\Common\Internal\ServiceBusSettings::getWrapName
*/
public function testGetWrapName()
{
// Setup
$expected = 'wrapname';
$setting = new ServiceBusSettings(null, null, null, $expected, null);
// Test
$actual = $setting->getWrapName();
// Assert
$this->assertEquals($expected, $actual);
}
/**
* @covers \WindowsAzure\Common\Internal\ServiceBusSettings::getWrapPassword
*/
public function testGetWrapPassword()
{
// Setup
$expected = 'wrappassword';
$setting = new ServiceBusSettings(null, null, null, null, $expected);
// Test
$actual = $setting->getWrapPassword();
// Assert
$this->assertEquals($expected, $actual);
}
/**
* @covers \WindowsAzure\Common\Internal\ServiceBusSettings::getWrapEndpointUri
*/
public function testGetWrapEndpointUri()
{
// Setup
$namespace = 'wrapendpoint';
$expected = "https://$namespace-sb.accesscontrol.windows.net/WRAPv0.9";
$setting = new ServiceBusSettings(null, null, $expected, null, null);
// Test
$actual = $setting->getWrapEndpointUri();
$actual = $setting->getFilter();
// Assert
$this->assertEquals($expected, $actual);
@ -234,22 +184,19 @@ class ServiceBusSettingsTest extends \PHPUnit_Framework_TestCase
public function testCreateFromConnectionStringWithCaseInvesitive()
{
// Setup
$expectedNamespace = 'mynamespace';
$expectedServiceBusEndpoint = "https://$expectedNamespace.servicebus.windows.net";
$namepspace = 'mynamespace';
$expectedServiceBusEndpoint = "https://$namepspace.servicebus.windows.net";
$expectedWrapName = 'myname';
$expectedWrapPassword = 'mypassword';
$expectedWrapEndpointUri = "https://$expectedNamespace-sb.accesscontrol.windows.net/WRAPv0.9";
$expectedWrapEndpointUri = "https://$namepspace-sb.accesscontrol.windows.net/WRAPv0.9";
$connectionString = "eNdPoinT=$expectedServiceBusEndpoint;sHarEdsecRetiSsuer=$expectedWrapName;shArEdsecrEtvAluE=$expectedWrapPassword";
// Test
$actual = ServiceBusSettings::createFromConnectionString($connectionString);
// Assert
$this->assertEquals($expectedNamespace, $actual->getNamespace());
$this->assertInstanceOf('WindowsAzure\Common\Internal\IServiceFilter', $actual->getFilter());
$this->assertEquals($expectedServiceBusEndpoint, $actual->getServiceBusEndpointUri());
$this->assertEquals($expectedWrapName, $actual->getWrapName());
$this->assertEquals($expectedWrapPassword, $actual->getWrapPassword());
$this->assertEquals($expectedWrapEndpointUri, $actual->getWrapEndpointUri());
}
/**
@ -268,8 +215,8 @@ class ServiceBusSettingsTest extends \PHPUnit_Framework_TestCase
public function testCreateFromConnectionStringWithWrapEndpoint()
{
// Setup
$expectedNamespace = 'mynamespace';
$expectedServiceBusEndpoint = "https://$expectedNamespace.servicebus.windows.net";
$namespace = 'mynamespace';
$expectedServiceBusEndpoint = "https://$namespace.servicebus.windows.net";
$expectedWrapName = 'myname';
$expectedWrapPassword = 'mypassword';
$expectedWrapEndpointUri = 'https://mysb-sb.accesscontrol.chinacloudapi.cn/';
@ -279,10 +226,7 @@ class ServiceBusSettingsTest extends \PHPUnit_Framework_TestCase
$actual = ServiceBusSettings::createFromConnectionString($connectionString);
// Assert
$this->assertEquals($expectedNamespace, $actual->getNamespace());
$this->assertInstanceOf('WindowsAzure\Common\Internal\IServiceFilter', $actual->getFilter());
$this->assertEquals($expectedServiceBusEndpoint, $actual->getServiceBusEndpointUri());
$this->assertEquals($expectedWrapName, $actual->getWrapName());
$this->assertEquals($expectedWrapPassword, $actual->getWrapPassword());
$this->assertEquals($expectedWrapEndpointUri, $actual->getWrapEndpointUri());
}
}

Просмотреть файл

@ -79,7 +79,7 @@ class WrapTokenManagerTest extends ServiceRestProxyTestBase
$wrapPassword = $settings->getWrapPassword();
$scope = $settings->getServiceBusEndpointUri();
// Execute
// Execute
$wrapTokenManager = new WrapTokenManager(
$wrapUri,
$wrapUserName,