Skip to content

Commit be7b649

Browse files
committed
Changes to flow the TraceWriter into the SecretManager
1 parent 0080db7 commit be7b649

23 files changed

+376
-184
lines changed

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License. See License.txt in the project root for license information.
33

44
using Autofac;
5+
using Microsoft.Azure.WebJobs.Host;
56
using Microsoft.Azure.WebJobs.Script.Config;
67
using Microsoft.Azure.WebJobs.Script.WebHost.WebHooks;
78

@@ -13,16 +14,15 @@ internal static void Initialize(ScriptSettingsManager settingsManager, Container
1314
{
1415
builder.RegisterInstance(settingsManager);
1516

16-
// register the resolver so that it is disposed when the container
17-
// is disposed
18-
var webHostResolver = new WebHostResolver(settingsManager);
19-
builder.RegisterInstance(webHostResolver);
17+
builder.RegisterType<WebHostResolver>().SingleInstance();
2018

2119
// these services are externally owned by the WebHostResolver, and will be disposed
2220
// when the resolver is disposed
23-
builder.Register<ISecretManager>(ct => webHostResolver.GetSecretManager(settings)).ExternallyOwned();
24-
builder.Register<WebScriptHostManager>(ct => webHostResolver.GetWebScriptHostManager(settings)).ExternallyOwned();
25-
builder.Register<WebHookReceiverManager>(ct => webHostResolver.GetWebHookReceiverManager(settings)).ExternallyOwned();
21+
builder.RegisterType<DefaultSecretManagerFactory>().As<ISecretManagerFactory>().SingleInstance();
22+
builder.Register<TraceWriter>(ct => ct.ResolveOptional<WebScriptHostManager>()?.Instance?.TraceWriter ?? NullTraceWriter.Instance).ExternallyOwned();
23+
builder.Register<ISecretManager>(ct => ct.Resolve<WebHostResolver>().GetSecretManager(settings)).ExternallyOwned();
24+
builder.Register<WebScriptHostManager>(ct => ct.Resolve<WebHostResolver>().GetWebScriptHostManager(settings)).ExternallyOwned();
25+
builder.Register<WebHookReceiverManager>(ct => ct.Resolve<WebHostResolver>().GetWebHookReceiverManager(settings)).ExternallyOwned();
2626
}
2727
}
2828
}

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

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,21 @@ public sealed class WebHostResolver : IDisposable
1616
{
1717
private static object _syncLock = new object();
1818

19+
private readonly ISecretManagerFactory _secretManagerFactory;
1920
private ScriptHostConfiguration _standbyScriptHostConfig;
2021
private WebScriptHostManager _standbyHostManager;
21-
private ISecretManager _standbySecretManager;
2222
private WebHookReceiverManager _standbyReceiverManager;
2323

2424
private ScriptHostConfiguration _activeScriptHostConfig;
2525
private WebScriptHostManager _activeHostManager;
26-
private ISecretManager _activeSecretManager;
2726
private WebHookReceiverManager _activeReceiverManager;
2827

2928
private static ScriptSettingsManager _settingsManager;
3029

31-
public WebHostResolver(ScriptSettingsManager settingsManager)
30+
public WebHostResolver(ScriptSettingsManager settingsManager, ISecretManagerFactory secretManagerFactory)
3231
{
3332
_settingsManager = settingsManager;
33+
_secretManagerFactory = secretManagerFactory;
3434
}
3535

3636
public ScriptHostConfiguration GetScriptHostConfiguration(WebHostSettings settings)
@@ -50,17 +50,7 @@ public ScriptHostConfiguration GetScriptHostConfiguration(WebHostSettings settin
5050

5151
public ISecretManager GetSecretManager(WebHostSettings settings)
5252
{
53-
if (_activeSecretManager != null)
54-
{
55-
return _activeSecretManager;
56-
}
57-
58-
lock (_syncLock)
59-
{
60-
EnsureInitialized(settings);
61-
62-
return _activeSecretManager ?? _standbySecretManager;
63-
}
53+
return GetWebScriptHostManager(settings).SecretManager;
6454
}
6555

6656
public WebScriptHostManager GetWebScriptHostManager(WebHostSettings settings)
@@ -109,16 +99,14 @@ private void EnsureInitialized(WebHostSettings settings)
10999
}
110100

111101
_activeScriptHostConfig = GetScriptHostConfiguration(settings.ScriptPath, settings.LogPath);
112-
_activeSecretManager = GetSecretManager(_settingsManager, settings.SecretsPath);
113-
_activeReceiverManager = new WebHookReceiverManager(_activeSecretManager);
114-
_activeHostManager = new WebScriptHostManager(_activeScriptHostConfig, _activeSecretManager, _settingsManager, settings);
115102

116-
(_standbySecretManager as IDisposable)?.Dispose();
103+
_activeHostManager = new WebScriptHostManager(_activeScriptHostConfig, _secretManagerFactory, _settingsManager, settings);
104+
_activeReceiverManager = new WebHookReceiverManager(_activeHostManager.SecretManager);
105+
117106
_standbyHostManager?.Dispose();
118107
_standbyReceiverManager?.Dispose();
119108

120109
_standbyScriptHostConfig = null;
121-
_standbySecretManager = null;
122110
_standbyHostManager = null;
123111
_standbyReceiverManager = null;
124112
_settingsManager.Reset();
@@ -129,9 +117,9 @@ private void EnsureInitialized(WebHostSettings settings)
129117
if (_standbyHostManager == null)
130118
{
131119
_standbyScriptHostConfig = GetScriptHostConfiguration(settings.ScriptPath, settings.LogPath);
132-
_standbySecretManager = GetSecretManager(_settingsManager, settings.SecretsPath);
133-
_standbyReceiverManager = new WebHookReceiverManager(_standbySecretManager);
134-
_standbyHostManager = new WebScriptHostManager(_standbyScriptHostConfig, _standbySecretManager, _settingsManager, settings);
120+
121+
_standbyHostManager = new WebScriptHostManager(_standbyScriptHostConfig, _secretManagerFactory, _settingsManager, settings);
122+
_standbyReceiverManager = new WebHookReceiverManager(_standbyHostManager.SecretManager);
135123
}
136124
}
137125
}
@@ -224,15 +212,11 @@ private static void InitializeFileSystem(string scriptPath)
224212
}
225213
}
226214

227-
private static ISecretManager GetSecretManager(ScriptSettingsManager settingsManager, string secretsPath) => new SecretManager(settingsManager, secretsPath);
228-
229215
public void Dispose()
230216
{
231-
(_standbySecretManager as IDisposable)?.Dispose();
232217
_standbyHostManager?.Dispose();
233218
_standbyReceiverManager?.Dispose();
234219

235-
(_activeSecretManager as IDisposable)?.Dispose();
236220
_activeHostManager?.Dispose();
237221
_activeReceiverManager?.Dispose();
238222
}

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Diagnostics;
67
using System.Linq;
78
using System.Net;
89
using System.Web.Http;
10+
using Microsoft.Azure.WebJobs.Host;
911
using Microsoft.Azure.WebJobs.Script.WebHost.Filters;
1012
using Microsoft.Azure.WebJobs.Script.WebHost.Models;
13+
using Microsoft.Azure.WebJobs.Script.WebHost.Properties;
1114

1215
namespace Microsoft.Azure.WebJobs.Script.WebHost.Controllers
1316
{
@@ -18,11 +21,13 @@ public class KeysController : ApiController
1821

1922
private readonly WebScriptHostManager _scriptHostManager;
2023
private readonly ISecretManager _secretManager;
24+
private readonly TraceWriter _traceWriter;
2125

22-
public KeysController(WebScriptHostManager scriptHostManager, ISecretManager secretManager)
26+
public KeysController(WebScriptHostManager scriptHostManager, ISecretManager secretManager, TraceWriter traceWriter)
2327
{
2428
_scriptHostManager = scriptHostManager;
2529
_secretManager = secretManager;
30+
_traceWriter = traceWriter.WithSource($"{ScriptConstants.TraceSourceSecretManagement}.Api");
2631
}
2732

2833
[HttpGet]
@@ -110,6 +115,8 @@ private IHttpActionResult AddOrUpdateFunctionSecret(string keyName, string value
110115
operationResult = _secretManager.AddOrUpdateFunctionSecret(keyName, value, functionName);
111116
}
112117

118+
_traceWriter.VerboseFormat(Resources.TraceKeysApiSecretChange, keyName, functionName ?? "host", operationResult.Result);
119+
113120
switch (operationResult.Result)
114121
{
115122
case OperationResult.Created:
@@ -146,6 +153,8 @@ private IHttpActionResult DeleteFunctionSecret(string keyName, string functionNa
146153
return NotFound();
147154
}
148155

156+
_traceWriter.VerboseFormat(Resources.TraceKeysApiSecretChange, keyName, functionName ?? "host", "Deleted");
157+
149158
return StatusCode(HttpStatusCode.NoContent);
150159
}
151160
}

src/WebJobs.Script.WebHost/GlobalSuppressions.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,9 @@
7777
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.Models.ApiModelUtility.#.cctor()")]
7878
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.WebHostResolver.#GetSecretManager(Microsoft.Azure.WebJobs.Script.Settings.ScriptSettingsManager,System.String)")]
7979
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.WebHostResolver.#GetSecretManager(Microsoft.Azure.WebJobs.Script.Config.ScriptSettingsManager,System.String)")]
80-
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "_fileWatcher", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.SecretManager.#Dispose(System.Boolean)")]
80+
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "_fileWatcher", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.SecretManager.#Dispose(System.Boolean)")]
81+
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.DefaultSecretManagerFactory.#Create(Microsoft.Azure.WebJobs.Script.Config.ScriptSettingsManager,Microsoft.Azure.WebJobs.Host.TraceWriter,System.String)")]
82+
[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,Microsoft.Azure.WebJobs.Host.TraceWriter,System.Boolean)")]
83+
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "_httpRoutes", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.WebScriptHostManager.#Dispose(System.Boolean)")]
84+
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "_metricsLogger", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.WebScriptHostManager.#Dispose(System.Boolean)")]
85+
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "_httpConfiguration", Scope = "member", Target = "Microsoft.Azure.WebJobs.Script.WebHost.WebHooks.WebHookReceiverManager.#Dispose(System.Boolean)")]

src/WebJobs.Script.WebHost/Properties/Resources.Designer.cs

Lines changed: 72 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/WebJobs.Script.WebHost/Properties/Resources.resx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,4 +259,28 @@
259259
]
260260
}</value>
261261
</data>
262+
<data name="TraceAddOrUpdateFunctionSecret" xml:space="preserve">
263+
<value>{0} secret '{1}' for '{2}' {3}.</value>
264+
</data>
265+
<data name="TraceFunctionSecretGeneration" xml:space="preserve">
266+
<value>Function ('{0}') secrets do not exist. Generating secrets.</value>
267+
</data>
268+
<data name="TraceHostSecretGeneration" xml:space="preserve">
269+
<value>Host secrets do not exist. Generating secrets.</value>
270+
</data>
271+
<data name="TraceKeysApiSecretChange" xml:space="preserve">
272+
<value>Secret '{0}' for '{1}' {2}.</value>
273+
</data>
274+
<data name="TraceMasterKeyCreatedOrUpdated" xml:space="preserve">
275+
<value>Master key {0}</value>
276+
</data>
277+
<data name="TraceSecretDeleted" xml:space="preserve">
278+
<value>{0} secret '{1}' deleted.</value>
279+
</data>
280+
<data name="TraceStaleFunctionSecretRefresh" xml:space="preserve">
281+
<value>Stale function ('{0}') secrets detected. Refreshing secrets.</value>
282+
</data>
283+
<data name="TraceStaleHostSecretRefresh" xml:space="preserve">
284+
<value>Stale host secrets detected. Refreshing secrets.</value>
285+
</data>
262286
</root>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
using Microsoft.Azure.WebJobs.Host;
10+
using Microsoft.Azure.WebJobs.Script.Config;
11+
12+
namespace Microsoft.Azure.WebJobs.Script.WebHost
13+
{
14+
public sealed class DefaultSecretManagerFactory : ISecretManagerFactory
15+
{
16+
public ISecretManager Create(ScriptSettingsManager settingsManager, TraceWriter traceWriter, string secretsPath)
17+
=> new SecretManager(settingsManager, secretsPath, traceWriter);
18+
}
19+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using System;
5+
using Microsoft.Azure.WebJobs.Host;
6+
using Microsoft.Azure.WebJobs.Script.Config;
7+
8+
namespace Microsoft.Azure.WebJobs.Script.WebHost
9+
{
10+
public interface ISecretManagerFactory
11+
{
12+
ISecretManager Create(ScriptSettingsManager settingsManager, TraceWriter traceWriter, string secretsPath);
13+
}
14+
}

0 commit comments

Comments
 (0)