Skip to content

Commit 9808402

Browse files
committed
Ensuring host secrets are created on startup
1 parent 11dafe0 commit 9808402

File tree

4 files changed

+37
-5
lines changed

4 files changed

+37
-5
lines changed

src/WebJobs.Script.WebHost/App_Start/WebHostResolver.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ private static ScriptHostConfiguration GetScriptHostConfiguration(string scriptP
184184
return scriptHostConfig;
185185
}
186186

187-
private static ISecretManager GetSecretManager(string secretsPath) => new SecretManager(secretsPath);
187+
private static ISecretManager GetSecretManager(string secretsPath) => new SecretManager(secretsPath, true);
188188

189189
public void Dispose()
190190
{

src/WebJobs.Script.WebHost/GlobalSuppressions.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,6 @@
6969
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.ISecretManager.#TryAddOrUpdateHostFunctionSecret(System.String,System.String,System.String&)")]
7070
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Scope = "type", Target = "Microsoft.Azure.WebJobs.Script.WebHost.Models.ApiModel")]
7171
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.Models.ApiModel.#Links")]
72-
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.Models.ApiModelUtility.#.cctor()")]
72+
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.Models.ApiModelUtility.#.cctor()")]
73+
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.SecretManager.#.ctor(System.String,Microsoft.Azure.WebJobs.Script.WebHost.IKeyValueConverterFactory,System.Boolean)")]
74+
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.SecretManager.#.ctor(System.String,Microsoft.Azure.WebJobs.Script.WebHost.IKeyValueConverterFactory,System.Boolean)")]

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ public SecretManager()
2626
{
2727
}
2828

29-
public SecretManager(string secretsPath)
30-
: this(secretsPath, new DefaultKeyValueConverterFactory())
29+
public SecretManager(string secretsPath, bool createHostSecretsIfMissing = false)
30+
: this(secretsPath, new DefaultKeyValueConverterFactory(), createHostSecretsIfMissing)
3131
{
3232
}
3333

34-
public SecretManager(string secretsPath, IKeyValueConverterFactory keyValueConverterFactory)
34+
public SecretManager(string secretsPath, IKeyValueConverterFactory keyValueConverterFactory, bool createHostSecretsIfMissing = false)
3535
{
3636
_secretsPath = secretsPath;
3737
_hostSecretsPath = Path.Combine(_secretsPath, ScriptConstants.HostMetadataFileName);
@@ -49,6 +49,13 @@ public SecretManager(string secretsPath, IKeyValueConverterFactory keyValueConve
4949
_fileWatcher.Created += OnChanged;
5050
_fileWatcher.Deleted += OnChanged;
5151
_fileWatcher.Renamed += OnChanged;
52+
53+
if (createHostSecretsIfMissing)
54+
{
55+
// The SecretManager implementation of GetHostSecrets will
56+
// create a host secret if one is not present.
57+
GetHostSecrets();
58+
}
5259
}
5360

5461
public void Dispose()

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,29 @@ public void SetMasterKey_WithoutProvidedKey_GeneratesKeyAndPersistsFile()
410410
}
411411
}
412412

413+
[Fact]
414+
public void Constructor_WithCreateHostSecretsIfMissingSet_CreatesHostSecret()
415+
{
416+
var secretsPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
417+
var hostSecretPath = Path.Combine(secretsPath, ScriptConstants.HostMetadataFileName);
418+
try
419+
{
420+
bool preExistingFile = File.Exists(hostSecretPath);
421+
422+
Mock<IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false);
423+
424+
var secretManager = new SecretManager(secretsPath, mockValueConverterFactory.Object, true);
425+
bool fileCreated = File.Exists(hostSecretPath);
426+
427+
Assert.False(preExistingFile);
428+
Assert.True(fileCreated);
429+
}
430+
finally
431+
{
432+
Directory.Delete(secretsPath, true);
433+
}
434+
}
435+
413436
private Mock<IKeyValueConverterFactory> GetConverterFactoryMock(bool simulateWriteConversion = true)
414437
{
415438
var mockValueReader = new Mock<IKeyValueReader>();

0 commit comments

Comments
 (0)