4
4
using System ;
5
5
using System . Collections . Generic ;
6
6
using System . Diagnostics ;
7
+ using System . IdentityModel . Tokens . Jwt ;
7
8
using System . IO ;
8
9
using System . Linq ;
9
10
using System . Net . Http ;
14
15
using Microsoft . AspNetCore . Builder ;
15
16
using Microsoft . AspNetCore . Hosting ;
16
17
using Microsoft . AspNetCore . TestHost ;
18
+ using Microsoft . Azure . Web . DataProtection ;
17
19
using Microsoft . Azure . WebJobs . Host . Executors ;
18
20
using Microsoft . Azure . WebJobs . Script . ExtensionBundle ;
19
- using Microsoft . Azure . WebJobs . Script . Grpc ;
20
21
using Microsoft . Azure . WebJobs . Script . Models ;
21
22
using Microsoft . Azure . WebJobs . Script . WebHost ;
23
+ using Microsoft . Azure . WebJobs . Script . WebHost . Authentication ;
22
24
using Microsoft . Azure . WebJobs . Script . WebHost . DependencyInjection ;
23
25
using Microsoft . Azure . WebJobs . Script . WebHost . Middleware ;
24
26
using Microsoft . Azure . WebJobs . Script . WebHost . Models ;
32
34
using Microsoft . Extensions . Logging ;
33
35
using Microsoft . Extensions . Logging . Abstractions ;
34
36
using Microsoft . Extensions . Options ;
37
+ using Microsoft . IdentityModel . Tokens ;
35
38
using Microsoft . WebJobs . Script . Tests ;
36
39
using Newtonsoft . Json . Linq ;
37
40
using IApplicationLifetime = Microsoft . AspNetCore . Hosting . IApplicationLifetime ;
@@ -59,9 +62,10 @@ public TestFunctionHost(string scriptPath,
59
62
Action < IWebJobsBuilder > configureScriptHostWebJobsBuilder = null ,
60
63
Action < IConfigurationBuilder > configureScriptHostAppConfiguration = null ,
61
64
Action < ILoggingBuilder > configureScriptHostLogging = null ,
62
- Action < IServiceCollection > configureScriptHostServices = null )
65
+ Action < IServiceCollection > configureScriptHostServices = null ,
66
+ Action < IConfigurationBuilder > configureWebHostAppConfiguration = null )
63
67
: this ( scriptPath , Path . Combine ( Path . GetTempPath ( ) , @"Functions" ) , configureWebHostServices , configureScriptHostWebJobsBuilder ,
64
- configureScriptHostAppConfiguration , configureScriptHostLogging , configureScriptHostServices )
68
+ configureScriptHostAppConfiguration , configureScriptHostLogging , configureScriptHostServices , configureWebHostAppConfiguration )
65
69
{
66
70
}
67
71
@@ -70,7 +74,9 @@ public TestFunctionHost(string scriptPath, string logPath,
70
74
Action < IWebJobsBuilder > configureScriptHostWebJobsBuilder = null ,
71
75
Action < IConfigurationBuilder > configureScriptHostAppConfiguration = null ,
72
76
Action < ILoggingBuilder > configureScriptHostLogging = null ,
73
- Action < IServiceCollection > configureScriptHostServices = null )
77
+ Action < IServiceCollection > configureScriptHostServices = null ,
78
+ Action < IConfigurationBuilder > configureWebHostAppConfiguration = null ,
79
+ bool addTestSettings = true )
74
80
{
75
81
_appRoot = scriptPath ;
76
82
@@ -126,7 +132,10 @@ public TestFunctionHost(string scriptPath, string logPath,
126
132
} )
127
133
. ConfigureScriptHostAppConfiguration ( scriptHostConfigurationBuilder =>
128
134
{
129
- scriptHostConfigurationBuilder . AddTestSettings ( ) ;
135
+ if ( addTestSettings )
136
+ {
137
+ scriptHostConfigurationBuilder . AddTestSettings ( ) ;
138
+ }
130
139
configureScriptHostAppConfiguration ? . Invoke ( scriptHostConfigurationBuilder ) ;
131
140
} )
132
141
. ConfigureScriptHostLogging ( scriptHostLoggingBuilder =>
@@ -149,7 +158,11 @@ public TestFunctionHost(string scriptPath, string logPath,
149
158
}
150
159
151
160
config . Add ( new ScriptEnvironmentVariablesConfigurationSource ( ) ) ;
152
- config . AddTestSettings ( ) ;
161
+ if ( addTestSettings )
162
+ {
163
+ config . AddTestSettings ( ) ;
164
+ }
165
+ configureWebHostAppConfiguration ? . Invoke ( config ) ;
153
166
} )
154
167
. UseStartup < TestStartup > ( ) ;
155
168
@@ -185,7 +198,9 @@ public TestFunctionHost(string scriptPath, string logPath,
185
198
186
199
public ScriptJobHostOptions ScriptOptions => JobHostServices . GetService < IOptions < ScriptJobHostOptions > > ( ) . Value ;
187
200
188
- public ISecretManager SecretManager => _testServer . Host . Services . GetService < ISecretManagerProvider > ( ) . Current ;
201
+ public ISecretManagerProvider SecretManagerProvider => _testServer . Host . Services . GetService < ISecretManagerProvider > ( ) ;
202
+
203
+ public ISecretManager SecretManager => SecretManagerProvider . Current ;
189
204
190
205
public string LogPath => _hostOptions . LogPath ;
191
206
@@ -195,6 +210,11 @@ public TestFunctionHost(string scriptPath, string logPath,
195
210
196
211
public async Task < string > GetMasterKeyAsync ( )
197
212
{
213
+ if ( ! SecretManagerProvider . SecretsEnabled )
214
+ {
215
+ return null ;
216
+ }
217
+
198
218
HostSecretsInfo secrets = await SecretManager . GetHostSecretsAsync ( ) ;
199
219
return secrets . MasterKey ;
200
220
}
@@ -348,13 +368,44 @@ public async Task<FunctionStatus> GetFunctionStatusAsync(string functionName)
348
368
349
369
public async Task < HostStatus > GetHostStatusAsync ( )
350
370
{
351
- HostSecretsInfo secrets = await SecretManager . GetHostSecretsAsync ( ) ;
352
- string uri = $ "admin/host/status?code={ secrets . MasterKey } ";
353
- HttpResponseMessage response = await HttpClient . GetAsync ( uri ) ;
371
+ HttpRequestMessage request = new HttpRequestMessage ( HttpMethod . Get , "admin/host/status" ) ;
372
+
373
+ if ( SecretManagerProvider . SecretsEnabled )
374
+ {
375
+ // use admin key
376
+ HostSecretsInfo secrets = await SecretManager . GetHostSecretsAsync ( ) ;
377
+ request . Headers . Add ( AuthenticationLevelHandler . FunctionsKeyHeaderName , secrets . MasterKey ) ;
378
+ }
379
+ else
380
+ {
381
+ // use admin jwt token
382
+ string token = GenerateAdminJwtToken ( ) ;
383
+ request . Headers . Authorization = new System . Net . Http . Headers . AuthenticationHeaderValue ( "Bearer" , token ) ;
384
+ }
385
+
386
+ HttpResponseMessage response = await HttpClient . SendAsync ( request ) ;
354
387
response . EnsureSuccessStatusCode ( ) ;
355
388
return await response . Content . ReadAsAsync < HostStatus > ( ) ;
356
389
}
357
390
391
+ public string GenerateAdminJwtToken ( )
392
+ {
393
+ var tokenHandler = new JwtSecurityTokenHandler ( ) ;
394
+ string defaultKey = Util . GetDefaultKeyValue ( ) ;
395
+ var key = Encoding . ASCII . GetBytes ( defaultKey ) ;
396
+ var tokenDescriptor = new SecurityTokenDescriptor
397
+ {
398
+ Audience = string . Format ( ScriptConstants . AdminJwtValidAudienceFormat , Environment . GetEnvironmentVariable ( EnvironmentSettingNames . AzureWebsiteName ) ) ,
399
+ Issuer = string . Format ( ScriptConstants . AdminJwtValidIssuerFormat , Environment . GetEnvironmentVariable ( EnvironmentSettingNames . AzureWebsiteName ) ) ,
400
+ Expires = DateTime . UtcNow . AddHours ( 1 ) ,
401
+ SigningCredentials = new SigningCredentials ( new SymmetricSecurityKey ( key ) , SecurityAlgorithms . HmacSha256Signature )
402
+ } ;
403
+ var token = tokenHandler . CreateToken ( tokenDescriptor ) ;
404
+ string tokenHeaderValue = tokenHandler . WriteToken ( token ) ;
405
+
406
+ return tokenHeaderValue ;
407
+ }
408
+
358
409
public void Dispose ( )
359
410
{
360
411
if ( ! _isDisposed )
0 commit comments