Skip to content

Commit 77dd920

Browse files
authored
returning error if the Storage operation for secret management fails (#8361)
1 parent 6d5f9a4 commit 77dd920

File tree

5 files changed

+40
-13
lines changed

5 files changed

+40
-13
lines changed

release_notes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<!-- Please add your release notes in the following format:
33
- My change description (#PR)
44
-->
5+
- Return 500 when when writing secrets to storage fails (#8361)
56

67
**Release sprint:** Sprint 119
78
[ [bugs](https://github.com/Azure/azure-functions-host/issues?q=is%3Aissue+milestone%3A%22Functions+Sprint+119%22+label%3Abug+is%3Aclosed) | [features](https://github.com/Azure/azure-functions-host/issues?q=is%3Aissue+milestone%3A%22Functions+Sprint+119%22+label%3Afeature+is%3Aclosed) ]

src/WebJobs.Script.WebHost/Controllers/KeysController.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,6 @@ private async Task<IActionResult> AddOrUpdateSecretAsync(string keyName, string
216216
return NotFound();
217217
case OperationResult.Conflict:
218218
return StatusCode(StatusCodes.Status409Conflict);
219-
case OperationResult.Forbidden:
220-
return StatusCode(StatusCodes.Status403Forbidden);
221219
default:
222220
return StatusCode(StatusCodes.Status500InternalServerError);
223221
}

src/WebJobs.Script.WebHost/OperationResult.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ public enum OperationResult
1010
Created,
1111
Updated,
1212
NotFound,
13-
Conflict,
14-
Forbidden
13+
Conflict
1514
}
1615
}

src/WebJobs.Script.WebHost/Security/KeyManagement/SecretManager.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -328,13 +328,7 @@ await ModifyFunctionSecretsAsync(secretsType, keyScope, secrets =>
328328
}
329329

330330
return secrets;
331-
}, secretsFactory).ContinueWith(t =>
332-
{
333-
if (t.IsFaulted && t.Exception.InnerException is KeyVaultErrorException)
334-
{
335-
result = OperationResult.Forbidden;
336-
}
337-
});
331+
}, secretsFactory);
338332

339333
return new KeyOperationResult(secret, result);
340334
}

test/WebJobs.Script.Tests/Security/SecretManagerTests.cs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
using System.Collections.Generic;
77
using System.IO;
88
using System.Linq;
9+
using System.Net;
910
using System.Security.Cryptography;
1011
using System.Threading;
1112
using System.Threading.Tasks;
13+
using Azure;
1214
using Microsoft.Azure.WebJobs.Extensions.Http;
1315
using Microsoft.Azure.WebJobs.Logging;
1416
using Microsoft.Azure.WebJobs.Script.Diagnostics;
@@ -500,6 +502,27 @@ public async Task AddOrUpdateFunctionSecrets_WithFunctionNameAndNoSecret_Generat
500502
}
501503

502504
[Fact]
505+
public async Task AddOrUpdateFunctionSecret_WhenStorageWriteError_ThrowsException()
506+
{
507+
using (var directory = new TempDirectory())
508+
{
509+
CreateTestSecrets(directory.Path);
510+
511+
KeyOperationResult result;
512+
513+
ISecretsRepository repository = new TestSecretsRepository(false, true);
514+
using var secretManager = CreateSecretManager(directory.Path, simulateWriteConversion: false, secretsRepository: repository);
515+
try
516+
{
517+
result = await secretManager.AddOrUpdateFunctionSecretAsync("function-key-3", "9876", "TestFunction", ScriptSecretsType.Function);
518+
}
519+
catch (RequestFailedException ex)
520+
{
521+
Assert.Equal(ex.Status, (int)HttpStatusCode.InternalServerError);
522+
}
523+
}
524+
}
525+
503526
public async Task AddOrUpdateFunctionSecret_ClearsCache_WhenFunctionSecretAdded()
504527
{
505528
using (var directory = new TempDirectory())
@@ -1136,7 +1159,7 @@ private Mock<IKeyValueConverterFactory> GetConverterFactoryMock(bool simulateWri
11361159
return mockValueConverterFactory;
11371160
}
11381161

1139-
private SecretManager CreateSecretManager(string secretsPath, ILogger logger = null, IMetricsLogger metricsLogger = null, IKeyValueConverterFactory keyConverterFactory = null, bool createHostSecretsIfMissing = false, bool simulateWriteConversion = true, bool setStaleValue = true)
1162+
private SecretManager CreateSecretManager(string secretsPath, ILogger logger = null, IMetricsLogger metricsLogger = null, IKeyValueConverterFactory keyConverterFactory = null, bool createHostSecretsIfMissing = false, bool simulateWriteConversion = true, bool setStaleValue = true, ISecretsRepository secretsRepository = null)
11401163
{
11411164
logger = logger ?? _logger;
11421165
metricsLogger = metricsLogger ?? new TestMetricsLogger();
@@ -1147,7 +1170,7 @@ private SecretManager CreateSecretManager(string secretsPath, ILogger logger = n
11471170
keyConverterFactory = mockValueConverterFactory.Object;
11481171
}
11491172

1150-
ISecretsRepository repository = new FileSystemSecretsRepository(secretsPath, logger, _testEnvironment);
1173+
ISecretsRepository repository = secretsRepository ?? new FileSystemSecretsRepository(secretsPath, logger, _testEnvironment);
11511174
var secretManager = new SecretManager(repository, keyConverterFactory, logger, metricsLogger, _hostNameProvider, _startupContextProvider);
11521175

11531176
if (createHostSecretsIfMissing)
@@ -1216,12 +1239,19 @@ private class TestSecretsRepository : ISecretsRepository
12161239
private int _writeCount = 0;
12171240
private Random _rand = new Random();
12181241
private bool _enforceSerialWrites = false;
1242+
private bool _forceWriteErrors = false;
12191243

12201244
public TestSecretsRepository(bool enforceSerialWrites)
12211245
{
12221246
_enforceSerialWrites = enforceSerialWrites;
12231247
}
12241248

1249+
public TestSecretsRepository(bool enforceSerialWrites, bool forceWriteErrors)
1250+
: this(enforceSerialWrites)
1251+
{
1252+
_forceWriteErrors = forceWriteErrors;
1253+
}
1254+
12251255
public event EventHandler<SecretsChangedEventArgs> SecretsChanged;
12261256

12271257
public ConcurrentDictionary<string, ScriptSecrets> FunctionSecrets { get; } = new ConcurrentDictionary<string, ScriptSecrets>(StringComparer.OrdinalIgnoreCase);
@@ -1260,6 +1290,11 @@ public Task<ScriptSecrets> ReadAsync(ScriptSecretsType type, string functionName
12601290

12611291
public async Task WriteAsync(ScriptSecretsType type, string functionName, ScriptSecrets secrets)
12621292
{
1293+
if (_forceWriteErrors)
1294+
{
1295+
throw new RequestFailedException((int)HttpStatusCode.InternalServerError, "Error");
1296+
}
1297+
12631298
if (_enforceSerialWrites && _writeCount > 1)
12641299
{
12651300
throw new Exception("Concurrent writes detected!");

0 commit comments

Comments
 (0)