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
@@ -123,7 +129,10 @@ public TestFunctionHost(string scriptPath, string logPath,
123
129
} )
124
130
. ConfigureScriptHostAppConfiguration ( scriptHostConfigurationBuilder =>
125
131
{
126
- scriptHostConfigurationBuilder . AddTestSettings ( ) ;
132
+ if ( addTestSettings )
133
+ {
134
+ scriptHostConfigurationBuilder . AddTestSettings ( ) ;
135
+ }
127
136
configureScriptHostAppConfiguration ? . Invoke ( scriptHostConfigurationBuilder ) ;
128
137
} )
129
138
. ConfigureScriptHostLogging ( scriptHostLoggingBuilder =>
@@ -146,7 +155,11 @@ public TestFunctionHost(string scriptPath, string logPath,
146
155
}
147
156
148
157
config . Add ( new ScriptEnvironmentVariablesConfigurationSource ( ) ) ;
149
- config . AddTestSettings ( ) ;
158
+ if ( addTestSettings )
159
+ {
160
+ config . AddTestSettings ( ) ;
161
+ }
162
+ configureWebHostAppConfiguration ? . Invoke ( config ) ;
150
163
} )
151
164
. UseStartup < TestStartup > ( ) ;
152
165
@@ -182,7 +195,9 @@ public TestFunctionHost(string scriptPath, string logPath,
182
195
183
196
public ScriptJobHostOptions ScriptOptions => JobHostServices . GetService < IOptions < ScriptJobHostOptions > > ( ) . Value ;
184
197
185
- public ISecretManager SecretManager => _testServer . Host . Services . GetService < ISecretManagerProvider > ( ) . Current ;
198
+ public ISecretManagerProvider SecretManagerProvider => _testServer . Host . Services . GetService < ISecretManagerProvider > ( ) ;
199
+
200
+ public ISecretManager SecretManager => SecretManagerProvider . Current ;
186
201
187
202
public string LogPath => _hostOptions . LogPath ;
188
203
@@ -192,6 +207,11 @@ public TestFunctionHost(string scriptPath, string logPath,
192
207
193
208
public async Task < string > GetMasterKeyAsync ( )
194
209
{
210
+ if ( ! SecretManagerProvider . SecretsEnabled )
211
+ {
212
+ return null ;
213
+ }
214
+
195
215
HostSecretsInfo secrets = await SecretManager . GetHostSecretsAsync ( ) ;
196
216
return secrets . MasterKey ;
197
217
}
@@ -345,13 +365,44 @@ public async Task<FunctionStatus> GetFunctionStatusAsync(string functionName)
345
365
346
366
public async Task < HostStatus > GetHostStatusAsync ( )
347
367
{
348
- HostSecretsInfo secrets = await SecretManager . GetHostSecretsAsync ( ) ;
349
- string uri = $ "admin/host/status?code={ secrets . MasterKey } ";
350
- HttpResponseMessage response = await HttpClient . GetAsync ( uri ) ;
368
+ HttpRequestMessage request = new HttpRequestMessage ( HttpMethod . Get , "admin/host/status" ) ;
369
+
370
+ if ( SecretManagerProvider . SecretsEnabled )
371
+ {
372
+ // use admin key
373
+ HostSecretsInfo secrets = await SecretManager . GetHostSecretsAsync ( ) ;
374
+ request . Headers . Add ( AuthenticationLevelHandler . FunctionsKeyHeaderName , secrets . MasterKey ) ;
375
+ }
376
+ else
377
+ {
378
+ // use admin jwt token
379
+ string token = GenerateAdminJwtToken ( ) ;
380
+ request . Headers . Authorization = new System . Net . Http . Headers . AuthenticationHeaderValue ( "Bearer" , token ) ;
381
+ }
382
+
383
+ HttpResponseMessage response = await HttpClient . SendAsync ( request ) ;
351
384
response . EnsureSuccessStatusCode ( ) ;
352
385
return await response . Content . ReadAsAsync < HostStatus > ( ) ;
353
386
}
354
387
388
+ public string GenerateAdminJwtToken ( )
389
+ {
390
+ var tokenHandler = new JwtSecurityTokenHandler ( ) ;
391
+ string defaultKey = Util . GetDefaultKeyValue ( ) ;
392
+ var key = Encoding . ASCII . GetBytes ( defaultKey ) ;
393
+ var tokenDescriptor = new SecurityTokenDescriptor
394
+ {
395
+ Audience = string . Format ( ScriptConstants . AdminJwtValidAudienceFormat , Environment . GetEnvironmentVariable ( EnvironmentSettingNames . AzureWebsiteName ) ) ,
396
+ Issuer = string . Format ( ScriptConstants . AdminJwtValidIssuerFormat , Environment . GetEnvironmentVariable ( EnvironmentSettingNames . AzureWebsiteName ) ) ,
397
+ Expires = DateTime . UtcNow . AddHours ( 1 ) ,
398
+ SigningCredentials = new SigningCredentials ( new SymmetricSecurityKey ( key ) , SecurityAlgorithms . HmacSha256Signature )
399
+ } ;
400
+ var token = tokenHandler . CreateToken ( tokenDescriptor ) ;
401
+ string tokenHeaderValue = tokenHandler . WriteToken ( token ) ;
402
+
403
+ return tokenHeaderValue ;
404
+ }
405
+
355
406
public void Dispose ( )
356
407
{
357
408
if ( ! _isDisposed )
0 commit comments