1
1
// Copyright (c) Microsoft Corporation.
2
2
// Licensed under the MIT License.
3
3
4
+ using System . Net ;
4
5
using Azure . Storage . Blobs ;
5
6
using Azure . Storage . Blobs . Models ;
6
7
using Azure . Storage . Sas ;
@@ -15,22 +16,25 @@ public class ArmUrlTransformationStrategy : IUrlTransformationStrategy
15
16
const string BlobUrlPrefix = ".blob." ; // "core.windows.net";
16
17
private const int BlobSasTokenExpirationInHours = 24 * 7 ; //7 days which is the Azure Batch node runtime;
17
18
const int UserDelegationKeyExpirationInHours = 1 ;
19
+ private static readonly Lazy < BlobApiHttpUtils > blobApiHttpUtilsFactory = new ( ( ) => new ( ) ) ;
18
20
19
21
private readonly ILogger logger = PipelineLoggerFactory . Create < ArmUrlTransformationStrategy > ( ) ;
20
22
private readonly Dictionary < string , UserDelegationKey > userDelegationKeyDictionary = [ ] ;
21
23
private readonly SemaphoreSlim semaphoreSlim = new ( 1 , 1 ) ;
22
24
private readonly Func < Uri , BlobServiceClient > blobServiceClientFactory ;
23
25
private readonly RuntimeOptions runtimeOptions ;
24
26
private readonly string storageHostSuffix ;
27
+ private readonly BlobApiHttpUtils blobApiHttpUtils ;
25
28
26
- public ArmUrlTransformationStrategy ( Func < Uri , BlobServiceClient > blobServiceClientFactory , RuntimeOptions runtimeOptions )
29
+ public ArmUrlTransformationStrategy ( Func < Uri , BlobServiceClient > blobServiceClientFactory , RuntimeOptions runtimeOptions , BlobApiHttpUtils ? blobApiHttpUtils = default )
27
30
{
28
31
ArgumentNullException . ThrowIfNull ( blobServiceClientFactory ) ;
29
32
ArgumentNullException . ThrowIfNull ( runtimeOptions ) ;
30
33
31
34
this . blobServiceClientFactory = blobServiceClientFactory ;
32
35
this . runtimeOptions = runtimeOptions ;
33
36
storageHostSuffix = BlobUrlPrefix + this . runtimeOptions ! . AzureEnvironmentConfig ! . StorageUrlSuffix ;
37
+ this . blobApiHttpUtils = blobApiHttpUtils ?? blobApiHttpUtilsFactory . Value ;
34
38
}
35
39
36
40
public async Task < Uri > TransformUrlWithStrategyAsync ( string sourceUrl , BlobSasPermissions blobSasPermissions )
@@ -60,9 +64,16 @@ private async Task<Uri> GetStorageUriWithSasTokenAsync(string sourceUrl, BlobSas
60
64
{
61
65
try
62
66
{
63
- var blobUrl = new BlobUriBuilder ( new Uri ( sourceUrl ) ) ;
67
+ Uri uri = new ( sourceUrl ) ;
68
+ var blobUrl = new BlobUriBuilder ( uri ) ;
64
69
var blobServiceClient = blobServiceClientFactory ( new Uri ( $ "https://{ blobUrl . Host } ") ) ;
65
70
71
+ if ( ( permissions & ~ ( BlobSasPermissions . Read | BlobSasPermissions . List | BlobSasPermissions . Execute ) ) == 0 && await blobApiHttpUtils . IsEndPointPublic ( uri ) )
72
+ {
73
+ logger . LogWarning ( "The URL provided is not a storage account the managed identity can access. The resolution strategy won't be applied. Host: {Host}" , blobUrl . Host ) ;
74
+ return uri ;
75
+ }
76
+
66
77
var userKey = await GetUserDelegationKeyAsync ( blobServiceClient , blobUrl . AccountName ) ;
67
78
68
79
var sasBuilder = new BlobSasBuilder ( )
@@ -73,13 +84,9 @@ private async Task<Uri> GetStorageUriWithSasTokenAsync(string sourceUrl, BlobSas
73
84
} ;
74
85
75
86
sasBuilder . SetPermissions ( permissions ) ;
87
+ blobUrl . Sas = sasBuilder . ToSasQueryParameters ( userKey , blobUrl . AccountName ) ;
76
88
77
- var blobUriWithSas = new BlobUriBuilder ( blobUrl . ToUri ( ) )
78
- {
79
- Sas = sasBuilder . ToSasQueryParameters ( userKey , blobUrl . AccountName )
80
- } ;
81
-
82
- return blobUriWithSas . ToUri ( ) ;
89
+ return blobUrl . ToUri ( ) ;
83
90
}
84
91
catch ( Exception e )
85
92
{
0 commit comments