@@ -20,6 +20,7 @@ public class KeysController : ApiController
20
20
{
21
21
private const string MasterKeyName = "_master" ;
22
22
23
+ private static readonly Lazy < Dictionary < string , string > > EmptyKeys = new Lazy < Dictionary < string , string > > ( ( ) => new Dictionary < string , string > ( ) ) ;
23
24
private readonly WebScriptHostManager _scriptHostManager ;
24
25
private readonly ISecretManager _secretManager ;
25
26
private readonly TraceWriter _traceWriter ;
@@ -45,39 +46,54 @@ public async Task<IHttpActionResult> Get(string name)
45
46
}
46
47
47
48
[ HttpGet ]
48
- [ Route ( "admin/host/keys" ) ]
49
+ [ Route ( "admin/host/{ keys:regex(^(keys|functionkeys|systemkeys)$)} " ) ]
49
50
public async Task < IHttpActionResult > Get ( )
50
51
{
51
- var hostSecrets = await _secretManager . GetHostSecretsAsync ( ) ;
52
- return GetKeysResult ( hostSecrets . FunctionKeys ) ;
52
+ string hostKeyScope = GetHostKeyScopeForRequest ( ) ;
53
+
54
+ Dictionary < string , string > keys = await GetHostSecretsByScope ( hostKeyScope ) ;
55
+ return GetKeysResult ( keys ) ;
53
56
}
54
57
55
58
[ HttpPost ]
56
59
[ Route ( "admin/functions/{name}/keys/{keyName}" ) ]
57
- public Task < IHttpActionResult > Post ( string name , string keyName ) => AddOrUpdateFunctionSecretAsync ( keyName , null , name ) ;
60
+ public Task < IHttpActionResult > Post ( string name , string keyName ) => AddOrUpdateSecretAsync ( keyName , null , name , ScriptSecretsType . Function ) ;
58
61
59
62
[ HttpPost ]
60
- [ Route ( "admin/host/keys/{keyName}" ) ]
61
- public Task < IHttpActionResult > Post ( string keyName ) => AddOrUpdateFunctionSecretAsync ( keyName , null ) ;
63
+ [ Route ( "admin/host/{ keys:regex(^(keys|functionkeys|systemkeys)$)} /{keyName}" ) ]
64
+ public Task < IHttpActionResult > Post ( string keyName ) => AddOrUpdateSecretAsync ( keyName , null , GetHostKeyScopeForRequest ( ) , ScriptSecretsType . Host ) ;
62
65
63
66
[ HttpPut ]
64
67
[ Route ( "admin/functions/{name}/keys/{keyName}" ) ]
65
- public Task < IHttpActionResult > Put ( string name , string keyName , Key key ) => PutKeyAsync ( keyName , key , name ) ;
68
+ public Task < IHttpActionResult > Put ( string name , string keyName , Key key ) => PutKeyAsync ( keyName , key , name , ScriptSecretsType . Function ) ;
66
69
67
70
[ HttpPut ]
68
- [ Route ( "admin/host/keys/{keyName}" ) ]
69
- public Task < IHttpActionResult > Put ( string keyName , Key key ) => PutKeyAsync ( keyName , key ) ;
71
+ [ Route ( "admin/host/{ keys:regex(^(keys|functionkeys|systemkeys)$)} /{keyName}" ) ]
72
+ public Task < IHttpActionResult > Put ( string keyName , Key key ) => PutKeyAsync ( keyName , key , GetHostKeyScopeForRequest ( ) , ScriptSecretsType . Host ) ;
70
73
71
74
[ HttpDelete ]
72
75
[ Route ( "admin/functions/{name}/keys/{keyName}" ) ]
73
- public Task < IHttpActionResult > Delete ( string name , string keyName ) => DeleteFunctionSecretAsync ( keyName , name ) ;
76
+ public Task < IHttpActionResult > Delete ( string name , string keyName ) => DeleteFunctionSecretAsync ( keyName , name , ScriptSecretsType . Function ) ;
74
77
75
78
[ HttpDelete ]
76
- [ Route ( "admin/host/keys/{keyName}" ) ]
77
- public Task < IHttpActionResult > Delete ( string keyName ) => DeleteFunctionSecretAsync ( keyName ) ;
79
+ [ Route ( "admin/host/{keys:regex(^(keys|functionkeys|systemkeys)$)}/{keyName}" ) ]
80
+ public Task < IHttpActionResult > Delete ( string keyName ) => DeleteFunctionSecretAsync ( keyName , GetHostKeyScopeForRequest ( ) , ScriptSecretsType . Host ) ;
81
+
82
+ private string GetHostKeyScopeForRequest ( )
83
+ {
84
+ string keyScope = ControllerContext . RouteData . Values . GetValueOrDefault < string > ( "keys" ) ;
85
+
86
+ if ( string . Equals ( keyScope , "keys" , StringComparison . OrdinalIgnoreCase ) )
87
+ {
88
+ keyScope = HostKeyScopes . FunctionKeys ;
89
+ }
90
+
91
+ return keyScope ;
92
+ }
78
93
79
94
private IHttpActionResult GetKeysResult ( IDictionary < string , string > keys )
80
95
{
96
+ keys = keys ?? EmptyKeys . Value ;
81
97
var keysContent = new
82
98
{
83
99
keys = keys . Select ( k => new { name = k . Key , value = k . Value } )
@@ -88,35 +104,34 @@ private IHttpActionResult GetKeysResult(IDictionary<string, string> keys)
88
104
return Ok ( keyResponse ) ;
89
105
}
90
106
91
- private async Task < IHttpActionResult > PutKeyAsync ( string keyName , Key key , string functionName = null )
107
+ private async Task < IHttpActionResult > PutKeyAsync ( string keyName , Key key , string keyScope , ScriptSecretsType secretsType )
92
108
{
93
109
if ( key ? . Value == null )
94
110
{
95
111
return BadRequest ( "Invalid key value" ) ;
96
112
}
97
113
98
- return await AddOrUpdateFunctionSecretAsync ( keyName , key . Value , functionName ) ;
114
+ return await AddOrUpdateSecretAsync ( keyName , key . Value , keyScope , secretsType ) ;
99
115
}
100
116
101
- private async Task < IHttpActionResult > AddOrUpdateFunctionSecretAsync ( string keyName , string value , string functionName = null )
117
+ private async Task < IHttpActionResult > AddOrUpdateSecretAsync ( string keyName , string value , string keyScope , ScriptSecretsType secretsType )
102
118
{
103
- if ( functionName != null &&
104
- ! _scriptHostManager . Instance . IsFunction ( functionName ) )
119
+ if ( secretsType == ScriptSecretsType . Function && keyScope != null && ! _scriptHostManager . Instance . IsFunction ( keyScope ) )
105
120
{
106
121
return NotFound ( ) ;
107
122
}
108
123
109
124
KeyOperationResult operationResult ;
110
- if ( functionName == null && string . Equals ( keyName , MasterKeyName , StringComparison . OrdinalIgnoreCase ) )
125
+ if ( secretsType == ScriptSecretsType . Host && string . Equals ( keyName , MasterKeyName , StringComparison . OrdinalIgnoreCase ) )
111
126
{
112
127
operationResult = await _secretManager . SetMasterKeyAsync ( value ) ;
113
128
}
114
129
else
115
130
{
116
- operationResult = await _secretManager . AddOrUpdateFunctionSecretAsync ( keyName , value , functionName ) ;
131
+ operationResult = await _secretManager . AddOrUpdateFunctionSecretAsync ( keyName , value , keyScope , secretsType ) ;
117
132
}
118
133
119
- _traceWriter . VerboseFormat ( Resources . TraceKeysApiSecretChange , keyName , functionName ?? "host" , operationResult . Result ) ;
134
+ _traceWriter . VerboseFormat ( Resources . TraceKeysApiSecretChange , keyName , keyScope ?? "host" , operationResult . Result ) ;
120
135
121
136
switch ( operationResult . Result )
122
137
{
@@ -139,22 +154,38 @@ private async Task<IHttpActionResult> AddOrUpdateFunctionSecretAsync(string keyN
139
154
}
140
155
}
141
156
142
- private async Task < IHttpActionResult > DeleteFunctionSecretAsync ( string keyName , string functionName = null )
157
+ private async Task < Dictionary < string , string > > GetHostSecretsByScope ( string secretsScope )
158
+ {
159
+ var hostSecrets = await _secretManager . GetHostSecretsAsync ( ) ;
160
+
161
+ if ( string . Equals ( secretsScope , HostKeyScopes . FunctionKeys , StringComparison . OrdinalIgnoreCase ) )
162
+ {
163
+ return hostSecrets . FunctionKeys ;
164
+ }
165
+ else if ( string . Equals ( secretsScope , HostKeyScopes . SystemKeys , StringComparison . OrdinalIgnoreCase ) )
166
+ {
167
+ return hostSecrets . SystemKeys ;
168
+ }
169
+
170
+ return null ;
171
+ }
172
+
173
+ private async Task < IHttpActionResult > DeleteFunctionSecretAsync ( string keyName , string keyScope , ScriptSecretsType secretsType )
143
174
{
144
175
if ( keyName == null || keyName . StartsWith ( "_" ) )
145
176
{
146
177
// System keys cannot be deleted.
147
178
return BadRequest ( "Invalid key name." ) ;
148
179
}
149
180
150
- if ( ( functionName != null && ! _scriptHostManager . Instance . IsFunction ( functionName ) ) ||
151
- ! await _secretManager . DeleteSecretAsync ( keyName , functionName ) )
181
+ if ( ( secretsType == ScriptSecretsType . Function && ! _scriptHostManager . Instance . IsFunction ( keyScope ) ) ||
182
+ ! await _secretManager . DeleteSecretAsync ( keyName , keyScope , secretsType ) )
152
183
{
153
184
// Either the function or the key were not found
154
185
return NotFound ( ) ;
155
186
}
156
187
157
- _traceWriter . VerboseFormat ( Resources . TraceKeysApiSecretChange , keyName , functionName ?? "host" , "Deleted" ) ;
188
+ _traceWriter . VerboseFormat ( Resources . TraceKeysApiSecretChange , keyName , keyScope ?? "host" , "Deleted" ) ;
158
189
159
190
return StatusCode ( HttpStatusCode . NoContent ) ;
160
191
}
0 commit comments