Skip to content
This repository has been archived by the owner on May 8, 2024. It is now read-only.

Commit

Permalink
Added support to authenticate with MSI token
Browse files Browse the repository at this point in the history
  • Loading branch information
katmsft authored and vinjiang committed Apr 25, 2019
1 parent 80b9cb4 commit 272dbba
Show file tree
Hide file tree
Showing 14 changed files with 892 additions and 2 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ Or:
BlobEndpoint=myBlobEndpoint;QueueEndpoint=myQueueEndpoint;TableEndpoint=myTableEndpoint;FileEndpoint=myFileEndpoint;SharedAccessSignature=sasToken
```

Or if AAD authentication is used:

```
BlobEndpoint=myBlobEndpoint;QueueEndpoint=myQueueEndpoint;TableEndpoint=myTableEndpoint;FileEndpoint=myFileEndpoint;AccountName=[yourAccount]
```
Note that account name is required.

* Instantiate a client object - a wrapper around the available calls for the given service.

```php
Expand All @@ -121,6 +128,13 @@ $queueClient = QueueRestProxy::createQueueService($connectionString);
$fileClient = FileRestProxy::createFileService($connectionString);
```

Or for AAD authentication:
```php
$blobClient = BlobRestProxy::createBlobServiceWithTokenCredential($token, $connectionString);
$queueClient = QueueRestProxy::createQueueServiceWithTokenCredential($token, $connectionString);
```
Note that Blob and Queue service supports AAD authentication.

### Using Middlewares
To specify the middlewares, user have to create an array with middlewares
and put it in the `$requestOptions` with key 'middlewares'. The sequence of
Expand Down
4 changes: 4 additions & 0 deletions azure-storage-blob/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ BlobEndpoint=[myBlobEndpoint];SharedAccessSignature=[sasToken]
```php
$blobClient = BlobRestProxy::createBlobService($connectionString);
```
Or for token authentication:
```php
$blobClient = BlobRestProxy::createBlobServiceWithTokenCredential($token, $connectionString);
```
### Using Middlewares
To specify the middlewares, user have to create an array with middlewares
and put it in the `$requestOptions` with key 'middlewares'. The sequence of
Expand Down
61 changes: 61 additions & 0 deletions azure-storage-blob/src/Blob/BlobRestProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
use MicrosoftAzure\Storage\Blob\Models\SetBlobTierOptions;
use MicrosoftAzure\Storage\Common\Internal\Authentication\SharedAccessSignatureAuthScheme;
use MicrosoftAzure\Storage\Common\Internal\Authentication\SharedKeyAuthScheme;
use MicrosoftAzure\Storage\Common\Internal\Authentication\TokenAuthScheme;
use MicrosoftAzure\Storage\Common\Internal\Http\HttpFormatter;
use MicrosoftAzure\Storage\Common\Internal\Middlewares\CommonRequestMiddleware;
use MicrosoftAzure\Storage\Common\Internal\Serialization\XmlSerializer;
Expand Down Expand Up @@ -171,6 +172,66 @@ public static function createBlobService(
return $blobWrapper;
}

/**
* Builds a blob service object, it accepts the following
* options:
*
* - http: (array) the underlying guzzle options. refer to
* http://docs.guzzlephp.org/en/latest/request-options.html for detailed available options
* - middlewares: (mixed) the middleware should be either an instance of a sub-class that
* implements {@see MicrosoftAzure\Storage\Common\Middlewares\IMiddleware}, or a
* `callable` that follows the Guzzle middleware implementation convention
*
* Please refer to
* https://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad
* for authenticate access to Azure blobs and queues using Azure Active Directory.
*
* @param string $token The bearer token passed as reference.
* @param string $connectionString The configuration connection string.
* @param array $options Array of options to pass to the service
*
* @return BlobRestProxy
*/
public static function createBlobServiceWithTokenCredential(
&$token,
$connectionString,
array $options = []
) {
$settings = StorageServiceSettings::createFromConnectionStringForTokenCredential(
$connectionString
);

$primaryUri = Utilities::tryAddUrlScheme(
$settings->getBlobEndpointUri()
);

$secondaryUri = Utilities::tryAddUrlScheme(
$settings->getBlobSecondaryEndpointUri()
);

$blobWrapper = new BlobRestProxy(
$primaryUri,
$secondaryUri,
$settings->getName(),
$options
);

// Getting authentication scheme
$authScheme = new TokenAuthScheme(
$token
);

// Adding common request middleware
$commonRequestMiddleware = new CommonRequestMiddleware(
$authScheme,
Resources::STORAGE_API_LATEST_VERSION,
Resources::BLOB_SDK_VERSION
);
$blobWrapper->pushMiddleware($commonRequestMiddleware);

return $blobWrapper;
}

/**
* Builds an anonymous access object with given primary service
* endpoint. The service endpoint should contain a scheme and a
Expand Down
2 changes: 1 addition & 1 deletion azure-storage-blob/src/Blob/Internal/BlobResources.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class BlobResources extends Resources
// @codingStandardsIgnoreStart

const BLOB_SDK_VERSION = '1.3.0';
const STORAGE_API_LATEST_VERSION = '2017-04-17';
const STORAGE_API_LATEST_VERSION = '2017-11-09';

// Error messages
const INVALID_BTE_MSG = "The blob block type must exist in %s";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

/**
* LICENSE: The MIT License (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* https://github.com/azure/azure-storage-php/LICENSE
*
* 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
* @package MicrosoftAzure\Storage\Common\Internal\Authentication
* @author Azure Storage PHP SDK <dmsh@microsoft.com>
* @copyright 2019 Microsoft Corporation
* @license https://github.com/azure/azure-storage-php/LICENSE
* @link https://github.com/azure/azure-storage-php
*/

namespace MicrosoftAzure\Storage\Common\Internal\Authentication;

use GuzzleHttp\Psr7\Request;
use MicrosoftAzure\Storage\Common\Internal\Resources;
use MicrosoftAzure\Storage\Common\Internal\Validate;

/**
* Azure authentication scheme for token credential.
*
* @ignore
* @category Microsoft
* @package MicrosoftAzure\Storage\Common\Internal\Authentication
* @author Azure Storage PHP SDK <dmsh@microsoft.com>
* @copyright 2019 Microsoft Corporation
* @license https://github.com/azure/azure-storage-php/LICENSE
* @link https://github.com/azure/azure-storage-php
*/
class TokenAuthScheme implements IAuthScheme
{
/**
* The authentication token
*/
protected $tokenRef;

/**
* Constructor.
*
* @param string $token the token used for AAD authentication.
*/
public function __construct(&$token)
{
$this->tokenRef =& $token;
}

/**
* Adds authentication header to the request headers.
*
* @param \GuzzleHttp\Psr7\Request $request HTTP request object.
*
* @abstract
*
* @return \GuzzleHttp\Psr7\Request
*/
public function signRequest(Request $request)
{
$bearerToken = "Bearer ". $this->tokenRef;
return $request->withHeader(Resources::AUTHENTICATION, $bearerToken);
}
}
2 changes: 2 additions & 0 deletions azure-storage-common/src/Common/Internal/Resources.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ class Resources
const INVALID_ACCEPT_CONTENT_TYPE = "The given accept content type is not valid.";
const ERROR_CANNOT_PARSE_XML = "Cannot parse XML, reasons: %s";
const INVALID_SCHEME = 'HTTP scheme can only be string \'http\' or \'https\'.';
const AAD_TOKEN_MUST_START_WITH_BEARER = 'AAD token is invalid, please make sure that it has format \'Bearer ################\'';

// HTTP Headers
const X_MS_HEADER_PREFIX = 'x-ms-';
Expand Down Expand Up @@ -235,6 +236,7 @@ class Resources
const NUMBER_OF_CONCURRENCY = 25;//Guzzle's default value
const DEFAULT_NUMBER_OF_RETRIES = 3;
const DEFAULT_RETRY_INTERVAL = 1000;//Milliseconds
const BEARER = 'Bearer ';

// Header values
const COMMON_SDK_VERSION = '1.3.0';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,90 @@ public static function createFromConnectionString($connectionString)
self::noMatch($connectionString);
}

/**
* Creates a StorageServiceSettings object from the given connection string.
* Note this is only for AAD connection string, it should at least contain
* the account name.
*
* @param string $connectionString The storage settings connection string.
*
* @return StorageServiceSettings
*/
public static function createFromConnectionStringForTokenCredential($connectionString)
{
// Explicit case for AAD token, Connection string could only have account
// name.
$tokenizedSettings = self::parseAndValidateKeys($connectionString);

$scheme = Utilities::tryGetValueInsensitive(
Resources::DEFAULT_ENDPOINTS_PROTOCOL_NAME,
$tokenizedSettings
);
$accountName = Utilities::tryGetValueInsensitive(
Resources::ACCOUNT_NAME_NAME,
$tokenizedSettings
);
$endpointSuffix = Utilities::tryGetValueInsensitive(
Resources::ENDPOINT_SUFFIX_NAME,
$tokenizedSettings
);
return self::createStorageServiceSettings(
$tokenizedSettings,
self::getServiceEndpoint(
$scheme,
$accountName,
Resources::BLOB_DNS_PREFIX,
$endpointSuffix
),
self::getServiceEndpoint(
$scheme,
$accountName,
Resources::QUEUE_DNS_PREFIX,
$endpointSuffix
),
self::getServiceEndpoint(
$scheme,
$accountName,
Resources::TABLE_DNS_PREFIX,
$endpointSuffix
),
self::getServiceEndpoint(
$scheme,
$accountName,
Resources::FILE_DNS_PREFIX,
$endpointSuffix
),
self::getServiceEndpoint(
$scheme,
$accountName,
Resources::BLOB_DNS_PREFIX,
$endpointSuffix,
true
),
self::getServiceEndpoint(
$scheme,
$accountName,
Resources::QUEUE_DNS_PREFIX,
$endpointSuffix,
true
),
self::getServiceEndpoint(
$scheme,
$accountName,
Resources::TABLE_DNS_PREFIX,
$endpointSuffix,
true
),
self::getServiceEndpoint(
$scheme,
$accountName,
Resources::FILE_DNS_PREFIX,
$endpointSuffix,
true
)
);
}

/**
* Gets storage service name.
*
Expand Down
4 changes: 4 additions & 0 deletions azure-storage-queue/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ QueueEndpoint=[myQueueEndpoint];SharedAccessSignature=[sasToken]
```php
$queueClient = QueueRestProxy::createQueueService($connectionString);
```
Or for AAD authentication:
```php
$queueClient = QueueRestProxy::createQueueServiceWithTokenCredential($token, $connectionString);
```
### Using Middlewares
To specify the middlewares, user have to create an array with middlewares
and put it in the `$requestOptions` with key 'middlewares'. The sequence of
Expand Down
2 changes: 1 addition & 1 deletion azure-storage-queue/src/Queue/Internal/QueueResources.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class QueueResources extends Resources
// @codingStandardsIgnoreStart

const QUEUE_SDK_VERSION = '1.2.0';
const STORAGE_API_LATEST_VERSION = '2016-05-31';
const STORAGE_API_LATEST_VERSION = '2017-11-09';

// Error messages
const INVALID_RECEIVE_MODE_MSG = 'The receive message option is in neither RECEIVE_AND_DELETE nor PEEK_LOCK mode.';
Expand Down
61 changes: 61 additions & 0 deletions azure-storage-queue/src/Queue/QueueRestProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

use MicrosoftAzure\Storage\Common\Internal\Authentication\SharedAccessSignatureAuthScheme;
use MicrosoftAzure\Storage\Common\Internal\Authentication\SharedKeyAuthScheme;
use MicrosoftAzure\Storage\Common\Internal\Authentication\TokenAuthScheme;
use MicrosoftAzure\Storage\Common\Internal\Http\HttpFormatter;
use MicrosoftAzure\Storage\Common\Internal\Middlewares\CommonRequestMiddleware;
use MicrosoftAzure\Storage\Common\Internal\Serialization\XmlSerializer;
Expand Down Expand Up @@ -132,6 +133,66 @@ public static function createQueueService(
return $queueWrapper;
}

/**
* Builds a queue service object, it accepts the following
* options:
*
* - http: (array) the underlying guzzle options. refer to
* http://docs.guzzlephp.org/en/latest/request-options.html for detailed available options
* - middlewares: (mixed) the middleware should be either an instance of a sub-class that
* implements {@see MicrosoftAzure\Storage\Common\Middlewares\IMiddleware}, or a
* `callable` that follows the Guzzle middleware implementation convention
*
* Please refer to
* https://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad
* for authenticate access to Azure blobs and queues using Azure Active Directory.
*
* @param string $token The bearer token passed as reference.
* @param string $connectionString The configuration connection string.
* @param array $options Array of options to pass to the service
*
* @return QueueRestProxy
*/
public static function createQueueServiceWithTokenCredential(
&$token,
$connectionString,
array $options = []
) {
$settings = StorageServiceSettings::createFromConnectionStringForTokenCredential(
$connectionString
);

$primaryUri = Utilities::tryAddUrlScheme(
$settings->getQueueEndpointUri()
);

$secondaryUri = Utilities::tryAddUrlScheme(
$settings->getQueueSecondaryEndpointUri()
);

$queueWrapper = new QueueRestProxy(
$primaryUri,
$secondaryUri,
$settings->getName(),
$options
);

// Getting authentication scheme
$authScheme = new TokenAuthScheme(
$token
);

// Adding common request middleware
$commonRequestMiddleware = new CommonRequestMiddleware(
$authScheme,
Resources::STORAGE_API_LATEST_VERSION,
Resources::QUEUE_SDK_VERSION
);
$queueWrapper->pushMiddleware($commonRequestMiddleware);

return $queueWrapper;
}

/**
* Lists all queues in the storage account.
*
Expand Down

0 comments on commit 272dbba

Please sign in to comment.