| | | 1 | | // Copyright (c) Microsoft Corporation. All rights reserved. |
| | | 2 | | // Licensed under the MIT License. |
| | | 3 | | |
| | | 4 | | using System; |
| | | 5 | | using System.Collections.Generic; |
| | | 6 | | using System.Net.Http; |
| | | 7 | | using Azure.Core; |
| | | 8 | | using Azure.Core.Pipeline; |
| | | 9 | | |
| | | 10 | | namespace Azure.Storage |
| | | 11 | | { |
| | | 12 | | /// <summary> |
| | | 13 | | /// Defines the client configuration options for connecting to Azure |
| | | 14 | | /// Storage. |
| | | 15 | | /// </summary> |
| | | 16 | | internal static class StorageClientOptions |
| | | 17 | | { |
| | | 18 | | /// <summary> |
| | | 19 | | /// The default scope used for token authentication with Storage. |
| | | 20 | | /// </summary> |
| | | 21 | | private const string StorageScope = "https://storage.azure.com/.default"; |
| | | 22 | | |
| | | 23 | | /// <summary> |
| | | 24 | | /// Set common ClientOptions defaults for Azure Storage. |
| | | 25 | | /// </summary> |
| | | 26 | | /// <param name="options">Storage ClientOptions.</param> |
| | | 27 | | public static void Initialize(this ClientOptions options) |
| | | 28 | | { |
| | | 29 | | // We're going to use the default ResponseClassifier to decide |
| | | 30 | | // which errors are retriable, but may extend this in the future. |
| | | 31 | | |
| | | 32 | | // We'll use the standard RetryPolicy with a few more retries |
| | 15334 | 33 | | options.Retry.MaxRetries = Constants.MaxReliabilityRetries; |
| | 15334 | 34 | | } |
| | | 35 | | |
| | | 36 | | /// <summary> |
| | | 37 | | /// Get an authentication policy to sign Storage requests. |
| | | 38 | | /// </summary> |
| | | 39 | | /// <param name="credential">Credential to use.</param> |
| | | 40 | | /// <returns>An authentication policy.</returns> |
| | | 41 | | public static HttpPipelinePolicy AsPolicy(this StorageSharedKeyCredential credential) => |
| | 4216 | 42 | | new StorageSharedKeyPipelinePolicy( |
| | 4216 | 43 | | credential ?? throw Errors.ArgumentNull(nameof(credential))); |
| | | 44 | | |
| | | 45 | | /// <summary> |
| | | 46 | | /// Get an authentication policy to sign Storage requests. |
| | | 47 | | /// </summary> |
| | | 48 | | /// <param name="credential">Credential to use.</param> |
| | | 49 | | /// <returns>An authentication policy.</returns> |
| | | 50 | | public static HttpPipelinePolicy AsPolicy(this TokenCredential credential) => |
| | 100 | 51 | | new BearerTokenAuthenticationPolicy( |
| | 100 | 52 | | credential ?? throw Errors.ArgumentNull(nameof(credential)), |
| | 100 | 53 | | StorageScope); |
| | | 54 | | |
| | | 55 | | /// <summary> |
| | | 56 | | /// Get an optional authentication policy to sign Storage requests. |
| | | 57 | | /// </summary> |
| | | 58 | | /// <param name="credentials">Optional credentials to use.</param> |
| | | 59 | | /// <returns>An optional authentication policy.</returns> |
| | | 60 | | public static HttpPipelinePolicy GetAuthenticationPolicy(object credentials = null) |
| | | 61 | | { |
| | | 62 | | // Use the credentials to decide on the authentication policy |
| | | 63 | | switch (credentials) |
| | | 64 | | { |
| | | 65 | | case SharedAccessSignatureCredentials _: |
| | | 66 | | case null: // Anonymous authentication |
| | 32 | 67 | | return null; |
| | | 68 | | case StorageSharedKeyCredential sharedKey: |
| | 124 | 69 | | return sharedKey.AsPolicy(); |
| | | 70 | | case TokenCredential token: |
| | 0 | 71 | | return token.AsPolicy(); |
| | | 72 | | default: |
| | 0 | 73 | | throw Errors.InvalidCredentials(credentials.GetType().FullName); |
| | | 74 | | } |
| | | 75 | | } |
| | | 76 | | |
| | | 77 | | /// <summary> |
| | | 78 | | /// Create an HttpPipeline from Storage ClientOptions. |
| | | 79 | | /// </summary> |
| | | 80 | | /// <param name="options">The Storage ClientOptions.</param> |
| | | 81 | | /// <param name="authentication">Optional authentication policy.</param> |
| | | 82 | | /// <param name="geoRedundantSecondaryStorageUri">The secondary URI to be used for retries on failed read reques |
| | | 83 | | /// <returns>An HttpPipeline to use for Storage requests.</returns> |
| | | 84 | | public static HttpPipeline Build(this ClientOptions options, HttpPipelinePolicy authentication = null, Uri geoRe |
| | | 85 | | { |
| | 4740 | 86 | | List<HttpPipelinePolicy> perRetryClientPolicies = new List<HttpPipelinePolicy>(); |
| | 4740 | 87 | | StorageResponseClassifier classifier = new StorageResponseClassifier(); |
| | 4740 | 88 | | if (geoRedundantSecondaryStorageUri != null) |
| | | 89 | | { |
| | 28 | 90 | | perRetryClientPolicies.Add(new GeoRedundantReadPolicy(geoRedundantSecondaryStorageUri)); |
| | 28 | 91 | | classifier.SecondaryStorageUri = geoRedundantSecondaryStorageUri; |
| | | 92 | | } |
| | | 93 | | |
| | 4740 | 94 | | perRetryClientPolicies.Add(new StorageRequestValidationPipelinePolicy(options)); |
| | 4740 | 95 | | perRetryClientPolicies.Add(authentication); // authentication needs to be the last of the perRetry client po |
| | | 96 | | |
| | 4740 | 97 | | return HttpPipelineBuilder.Build( |
| | 4740 | 98 | | options, |
| | 4740 | 99 | | Array.Empty<HttpPipelinePolicy>(), |
| | 4740 | 100 | | perRetryClientPolicies.ToArray(), |
| | 4740 | 101 | | classifier); |
| | | 102 | | } |
| | | 103 | | |
| | | 104 | | /// <summary> |
| | | 105 | | /// Create an HttpPipeline from Storage ClientOptions. |
| | | 106 | | /// </summary> |
| | | 107 | | /// <param name="options">The Storage ClientOptions.</param> |
| | | 108 | | /// <param name="credentials">Optional authentication credentials.</param> |
| | | 109 | | /// <param name="geoRedundantSecondaryStorageUri">The secondary URI to be used for retries on failed read reques |
| | | 110 | | /// <returns>An HttpPipeline to use for Storage requests.</returns> |
| | | 111 | | public static HttpPipeline Build(this ClientOptions options, object credentials, Uri geoRedundantSecondaryStorag |
| | 148 | 112 | | Build(options, GetAuthenticationPolicy(credentials), geoRedundantSecondaryStorageUri); |
| | | 113 | | } |
| | | 114 | | } |