@@ -36,6 +36,7 @@ public enum SecretsRepositoryType
36
36
{
37
37
FileSystem ,
38
38
BlobStorage ,
39
+ BlobStorageSas ,
39
40
KeyVault
40
41
}
41
42
@@ -45,10 +46,12 @@ public async Task FileSystemRepo_Constructor_CreatesSecretPathIfNotExists()
45
46
await Constructor_CreatesSecretPathIfNotExists ( SecretsRepositoryType . FileSystem ) ;
46
47
}
47
48
48
- [ Fact ]
49
- public async Task BlobStorageRepo_Constructor_CreatesSecretPathIfNotExists ( )
49
+ [ Theory ]
50
+ [ InlineData ( SecretsRepositoryType . BlobStorage ) ]
51
+ [ InlineData ( SecretsRepositoryType . BlobStorageSas ) ]
52
+ public async Task BlobStorageRepo_Constructor_CreatesSecretPathIfNotExists ( SecretsRepositoryType repositoryType )
50
53
{
51
- await Constructor_CreatesSecretPathIfNotExists ( SecretsRepositoryType . BlobStorage ) ;
54
+ await Constructor_CreatesSecretPathIfNotExists ( repositoryType ) ;
52
55
}
53
56
54
57
[ Fact ]
@@ -80,11 +83,13 @@ private async Task Constructor_CreatesSecretPathIfNotExists(SecretsRepositoryTyp
80
83
}
81
84
82
85
[ Theory ]
83
- [ InlineData ( ScriptSecretsType . Host ) ]
84
- [ InlineData ( ScriptSecretsType . Function ) ]
85
- public async Task BlobStorageRepo_ReadAsync_ReadsExpectedFile ( ScriptSecretsType secretsType )
86
+ [ InlineData ( SecretsRepositoryType . BlobStorage , ScriptSecretsType . Host ) ]
87
+ [ InlineData ( SecretsRepositoryType . BlobStorage , ScriptSecretsType . Function ) ]
88
+ [ InlineData ( SecretsRepositoryType . BlobStorageSas , ScriptSecretsType . Host ) ]
89
+ [ InlineData ( SecretsRepositoryType . BlobStorageSas , ScriptSecretsType . Function ) ]
90
+ public async Task BlobStorageRepo_ReadAsync_ReadsExpectedFile ( SecretsRepositoryType repositoryType , ScriptSecretsType secretsType )
86
91
{
87
- await ReadAsync_ReadsExpectedFile ( SecretsRepositoryType . BlobStorage , secretsType ) ;
92
+ await ReadAsync_ReadsExpectedFile ( repositoryType , secretsType ) ;
88
93
}
89
94
90
95
[ Theory ]
@@ -152,11 +157,13 @@ private async Task ReadAsync_ReadsExpectedFile(SecretsRepositoryType repositoryT
152
157
}
153
158
154
159
[ Theory ]
155
- [ InlineData ( ScriptSecretsType . Host ) ]
156
- [ InlineData ( ScriptSecretsType . Function ) ]
157
- public async Task BlobStorageRepo_WriteAsync_CreatesExpectedFile ( ScriptSecretsType secretsType )
160
+ [ InlineData ( SecretsRepositoryType . BlobStorage , ScriptSecretsType . Host ) ]
161
+ [ InlineData ( SecretsRepositoryType . BlobStorage , ScriptSecretsType . Function ) ]
162
+ [ InlineData ( SecretsRepositoryType . BlobStorageSas , ScriptSecretsType . Host ) ]
163
+ [ InlineData ( SecretsRepositoryType . BlobStorageSas , ScriptSecretsType . Function ) ]
164
+ public async Task BlobStorageRepo_WriteAsync_CreatesExpectedFile ( SecretsRepositoryType repositoryType , ScriptSecretsType secretsType )
158
165
{
159
- await WriteAsync_CreatesExpectedFile ( SecretsRepositoryType . BlobStorage , secretsType ) ;
166
+ await WriteAsync_CreatesExpectedFile ( repositoryType , secretsType ) ;
160
167
}
161
168
162
169
[ Theory ]
@@ -204,7 +211,7 @@ private async Task WriteAsync_CreatesExpectedFile(SecretsRepositoryType reposito
204
211
205
212
string filePath = Path . Combine ( directory . Path , $ "{ testFunctionName ?? "host" } .json") ;
206
213
207
- if ( repositoryType == SecretsRepositoryType . BlobStorage )
214
+ if ( repositoryType == SecretsRepositoryType . BlobStorage || repositoryType == SecretsRepositoryType . BlobStorageSas )
208
215
{
209
216
Assert . True ( _fixture . MarkerFileExists ( testFunctionName ?? "host" ) ) ;
210
217
}
@@ -235,10 +242,12 @@ public async Task FileSystemRepo_WriteAsync_ChangeNotificationUpdatesExistingSec
235
242
await WriteAsync_ChangeNotificationUpdatesExistingSecret ( SecretsRepositoryType . FileSystem ) ;
236
243
}
237
244
238
- [ Fact ]
239
- public async Task BlobStorageRepo_WriteAsync_ChangeNotificationUpdatesExistingSecret ( )
245
+ [ Theory ]
246
+ [ InlineData ( SecretsRepositoryType . BlobStorage ) ]
247
+ [ InlineData ( SecretsRepositoryType . BlobStorageSas ) ]
248
+ public async Task BlobStorageRepo_WriteAsync_ChangeNotificationUpdatesExistingSecret ( SecretsRepositoryType repositoryType )
240
249
{
241
- await WriteAsync_ChangeNotificationUpdatesExistingSecret ( SecretsRepositoryType . BlobStorage ) ;
250
+ await WriteAsync_ChangeNotificationUpdatesExistingSecret ( repositoryType ) ;
242
251
}
243
252
244
253
private async Task WriteAsync_ChangeNotificationUpdatesExistingSecret ( SecretsRepositoryType repositoryType )
@@ -300,6 +309,8 @@ public async Task FileSystemRepo_PurgeOldSecrets_RemovesOldAndKeepsCurrentSecret
300
309
[ InlineData ( SecretsRepositoryType . FileSystem , ScriptSecretsType . Function ) ]
301
310
[ InlineData ( SecretsRepositoryType . BlobStorage , ScriptSecretsType . Host ) ]
302
311
[ InlineData ( SecretsRepositoryType . BlobStorage , ScriptSecretsType . Function ) ]
312
+ [ InlineData ( SecretsRepositoryType . BlobStorageSas , ScriptSecretsType . Host ) ]
313
+ [ InlineData ( SecretsRepositoryType . BlobStorageSas , ScriptSecretsType . Function ) ]
303
314
public async Task GetSecretSnapshots_ReturnsExpected ( SecretsRepositoryType repositoryType , ScriptSecretsType secretsType )
304
315
{
305
316
using ( var directory = new TempDirectory ( ) )
@@ -341,7 +352,6 @@ public Fixture()
341
352
TestSiteName = "Test_test" ;
342
353
var configuration = TestHelpers . GetTestConfiguration ( ) ;
343
354
BlobConnectionString = configuration . GetWebJobsConnectionString ( ConnectionStringNames . Storage ) ;
344
- BlobContainer = CloudStorageAccount . Parse ( BlobConnectionString ) . CreateCloudBlobClient ( ) . GetContainerReference ( "azure-webjobs-secrets" ) ;
345
355
KeyVaultConnectionString = configuration . GetWebJobsConnectionString ( EnvironmentSettingNames . AzureWebJobsSecretStorageKeyVaultConnectionString ) ;
346
356
KeyVaultName = configuration . GetWebJobsConnectionString ( EnvironmentSettingNames . AzureWebJobsSecretStorageKeyVaultName ) ;
347
357
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider ( KeyVaultConnectionString ) ;
@@ -354,6 +364,8 @@ public Fixture()
354
364
355
365
public string BlobConnectionString { get ; private set ; }
356
366
367
+ public Uri BlobSasConnectionUri { get ; private set ; }
368
+
357
369
public CloudBlobContainer BlobContainer { get ; private set ; }
358
370
359
371
public KeyVaultClient KeyVaultClient { get ; private set ; }
@@ -373,6 +385,16 @@ public async Task TestInitialize(SecretsRepositoryType repositoryType, string se
373
385
TestSiteName = testSiteName ;
374
386
}
375
387
388
+ if ( RepositoryType == SecretsRepositoryType . BlobStorageSas )
389
+ {
390
+ BlobSasConnectionUri = await TestHelpers . CreateBlobContainerSas ( BlobConnectionString , "azure-webjobs-secrets-sas" ) ;
391
+ BlobContainer = new CloudBlobContainer ( BlobSasConnectionUri ) ;
392
+ }
393
+ else
394
+ {
395
+ BlobContainer = CloudStorageAccount . Parse ( BlobConnectionString ) . CreateCloudBlobClient ( ) . GetContainerReference ( "azure-webjobs-secrets" ) ;
396
+ }
397
+
376
398
await ClearAllBlobSecrets ( ) ;
377
399
ClearAllFileSecrets ( ) ;
378
400
await ClearAllKeyVaultSecrets ( ) ;
@@ -384,6 +406,10 @@ public ISecretsRepository GetNewSecretRepository()
384
406
{
385
407
return new BlobStorageSecretsRepository ( SecretsDirectory , BlobConnectionString , TestSiteName ) ;
386
408
}
409
+ else if ( RepositoryType == SecretsRepositoryType . BlobStorageSas )
410
+ {
411
+ return new BlobStorageSasSecretsRepository ( SecretsDirectory , BlobSasConnectionUri . ToString ( ) , TestSiteName ) ;
412
+ }
387
413
else if ( RepositoryType == SecretsRepositoryType . FileSystem )
388
414
{
389
415
return new FileSystemSecretsRepository ( SecretsDirectory ) ;
@@ -435,6 +461,7 @@ public async Task WriteSecret(string functionNameOrHost, ScriptSecrets scriptSec
435
461
WriteSecretsToFile ( functionNameOrHost , ScriptSecretSerializer . SerializeSecrets ( scriptSecret ) ) ;
436
462
break ;
437
463
case SecretsRepositoryType . BlobStorage :
464
+ case SecretsRepositoryType . BlobStorageSas :
438
465
await WriteSecretsBlobAndUpdateSentinelFile ( functionNameOrHost , ScriptSecretSerializer . SerializeSecrets ( scriptSecret ) ) ;
439
466
break ;
440
467
case SecretsRepositoryType . KeyVault :
@@ -485,6 +512,7 @@ public async Task<ScriptSecrets> GetSecretText(string functionNameOrHost, Script
485
512
secrets = ScriptSecretSerializer . DeserializeSecrets ( type , secretText ) ;
486
513
break ;
487
514
case SecretsRepositoryType . BlobStorage :
515
+ case SecretsRepositoryType . BlobStorageSas :
488
516
secrets = await GetSecretBlobText ( functionNameOrHost , type ) ;
489
517
break ;
490
518
case SecretsRepositoryType . KeyVault :
@@ -559,7 +587,13 @@ private string GetSecretName(string secretName)
559
587
560
588
private async Task ClearAllBlobSecrets ( )
561
589
{
562
- await BlobContainer . CreateIfNotExistsAsync ( ) ;
590
+ // A sas connection requires the container to already exist, it
591
+ // doesn't have permission to create it
592
+ if ( RepositoryType != SecretsRepositoryType . BlobStorageSas )
593
+ {
594
+ await BlobContainer . CreateIfNotExistsAsync ( ) ;
595
+ }
596
+
563
597
var blobs = await BlobContainer . ListBlobsSegmentedAsync ( prefix : TestSiteName . ToLowerInvariant ( ) , useFlatBlobListing : true ,
564
598
blobListingDetails : BlobListingDetails . None , maxResults : 100 , currentToken : null , options : null , operationContext : null ) ;
565
599
foreach ( IListBlobItem blob in blobs . Results )
0 commit comments