@@ -68,17 +68,23 @@ public override async Task WriteAsync(ScriptSecretsType type, string functionNam
68
68
Dictionary < string , string > dictionary = GetDictionaryFromScriptSecrets ( secrets , functionName ) ;
69
69
70
70
// Delete existing keys
71
- string prefix = ( type == ScriptSecretsType . Host ) ? HostPrefix : FunctionPrefix + Normalize ( functionName ) ;
71
+ List < IEnumerable < SecretItem > > secretsPages = await GetKeyVaultSecretsPagesAsync ( _keyVaultClient . Value , GetVaultBaseUrl ( ) ) ;
72
72
List < Task > deleteTasks = new List < Task > ( ) ;
73
- foreach ( SecretItem item in await _keyVaultClient . Value . GetSecretsAsync ( GetVaultBaseUrl ( ) ) )
73
+ string prefix = ( type == ScriptSecretsType . Host ) ? HostPrefix : FunctionPrefix + Normalize ( functionName ) ;
74
+
75
+ foreach ( SecretItem item in FindSecrets ( secretsPages , x => x . Identifier . Name . StartsWith ( prefix ) ) )
74
76
{
75
- // Delete only keys which are no longer exist in passed secrets
76
- if ( item . Identifier . Name . StartsWith ( prefix ) && ! dictionary . Keys . Contains ( item . Identifier . Name ) )
77
+ // Delete only keys which no longer exist in passed-in secrets
78
+ if ( ! dictionary . Keys . Contains ( item . Identifier . Name ) )
77
79
{
78
80
deleteTasks . Add ( _keyVaultClient . Value . DeleteSecretAsync ( GetVaultBaseUrl ( ) , item . Identifier . Name ) ) ;
79
81
}
80
82
}
81
- await Task . WhenAll ( deleteTasks ) ;
83
+
84
+ if ( deleteTasks . Any ( ) )
85
+ {
86
+ await Task . WhenAll ( deleteTasks ) ;
87
+ }
82
88
83
89
// Set new secrets
84
90
List < Task > setTasks = new List < Task > ( ) ;
@@ -112,28 +118,28 @@ public override Task<string[]> GetSecretSnapshots(ScriptSecretsType type, string
112
118
113
119
private async Task < ScriptSecrets > ReadHostSecrets ( )
114
120
{
115
- IPage < SecretItem > secretItems = await _keyVaultClient . Value . GetSecretsAsync ( GetVaultBaseUrl ( ) ) ;
121
+ List < IEnumerable < SecretItem > > secretsPages = await GetKeyVaultSecretsPagesAsync ( _keyVaultClient . Value , GetVaultBaseUrl ( ) ) ;
116
122
List < Task < SecretBundle > > tasks = new List < Task < SecretBundle > > ( ) ;
117
123
118
124
// Add master key task
119
- SecretItem masterItem = secretItems . FirstOrDefault ( x => x . Identifier . Name . StartsWith ( MasterKey ) ) ;
120
- if ( masterItem != null )
125
+ List < SecretItem > masterItems = FindSecrets ( secretsPages , x => x . Identifier . Name . StartsWith ( MasterKey ) ) ;
126
+ if ( masterItems . Count > 0 )
121
127
{
122
- tasks . Add ( _keyVaultClient . Value . GetSecretAsync ( GetVaultBaseUrl ( ) , masterItem . Identifier . Name ) ) ;
128
+ tasks . Add ( _keyVaultClient . Value . GetSecretAsync ( GetVaultBaseUrl ( ) , masterItems [ 0 ] . Identifier . Name ) ) ;
123
129
}
124
130
else
125
131
{
126
132
return null ;
127
133
}
128
134
129
135
// Add functionKey tasks
130
- foreach ( SecretItem item in secretItems . Where ( x => x . Identifier . Name . StartsWith ( FunctionKeyPrefix ) ) )
136
+ foreach ( SecretItem item in FindSecrets ( secretsPages , x => x . Identifier . Name . StartsWith ( FunctionKeyPrefix ) ) )
131
137
{
132
138
tasks . Add ( _keyVaultClient . Value . GetSecretAsync ( GetVaultBaseUrl ( ) , item . Identifier . Name ) ) ;
133
139
}
134
140
135
141
// Add systemKey tasks
136
- foreach ( SecretItem item in secretItems . Where ( x => x . Identifier . Name . StartsWith ( SystemKeyPrefix ) ) )
142
+ foreach ( SecretItem item in FindSecrets ( secretsPages , x => x . Identifier . Name . StartsWith ( SystemKeyPrefix ) ) )
137
143
{
138
144
tasks . Add ( _keyVaultClient . Value . GetSecretAsync ( GetVaultBaseUrl ( ) , item . Identifier . Name ) ) ;
139
145
}
@@ -168,13 +174,15 @@ private async Task<ScriptSecrets> ReadHostSecrets()
168
174
169
175
private async Task < ScriptSecrets > ReadFunctionSecrets ( string functionName )
170
176
{
171
- IPage < SecretItem > secretItems = await _keyVaultClient . Value . GetSecretsAsync ( GetVaultBaseUrl ( ) ) ;
177
+ List < IEnumerable < SecretItem > > secretsPages = await GetKeyVaultSecretsPagesAsync ( _keyVaultClient . Value , GetVaultBaseUrl ( ) ) ;
172
178
List < Task < SecretBundle > > tasks = new List < Task < SecretBundle > > ( ) ;
173
179
string prefix = $ "{ FunctionPrefix } { Normalize ( functionName ) } --";
174
- foreach ( SecretItem item in secretItems . Where ( x => x . Identifier . Name . StartsWith ( prefix , StringComparison . OrdinalIgnoreCase ) ) )
180
+
181
+ foreach ( SecretItem item in FindSecrets ( secretsPages , x => x . Identifier . Name . StartsWith ( prefix , StringComparison . OrdinalIgnoreCase ) ) )
175
182
{
176
183
tasks . Add ( _keyVaultClient . Value . GetSecretAsync ( GetVaultBaseUrl ( ) , item . Identifier . Name ) ) ;
177
184
}
185
+
178
186
if ( ! tasks . Any ( ) )
179
187
{
180
188
return null ;
@@ -195,6 +203,40 @@ private async Task<ScriptSecrets> ReadFunctionSecrets(string functionName)
195
203
return functionSecrets ;
196
204
}
197
205
206
+ public static async Task < List < IEnumerable < SecretItem > > > GetKeyVaultSecretsPagesAsync ( KeyVaultClient keyVaultClient , string keyVaultBaseUrl )
207
+ {
208
+ IPage < SecretItem > secretItems = await keyVaultClient . GetSecretsAsync ( keyVaultBaseUrl ) ;
209
+ List < IEnumerable < SecretItem > > secretsPages = new List < IEnumerable < SecretItem > > ( ) { secretItems } ;
210
+
211
+ while ( ! string . IsNullOrEmpty ( secretItems . NextPageLink ) )
212
+ {
213
+ secretItems = await keyVaultClient . GetSecretsNextAsync ( secretItems . NextPageLink ) ;
214
+ secretsPages . Add ( secretItems ) ;
215
+ }
216
+
217
+ return secretsPages ;
218
+ }
219
+
220
+ public static List < SecretItem > FindSecrets ( List < IEnumerable < SecretItem > > secretsPages , Func < SecretItem , bool > comparison = null )
221
+ {
222
+ // if no comparison is provided, every item is a match
223
+ if ( comparison == null )
224
+ {
225
+ comparison = x => true ;
226
+ }
227
+
228
+ var secretItems = new List < SecretItem > ( ) ;
229
+ foreach ( IEnumerable < SecretItem > secretsPage in secretsPages )
230
+ {
231
+ foreach ( SecretItem secretItem in secretsPage . Where ( x => comparison ( x ) ) )
232
+ {
233
+ secretItems . Add ( secretItem ) ;
234
+ }
235
+ }
236
+
237
+ return secretItems ;
238
+ }
239
+
198
240
private string GetVaultBaseUrl ( )
199
241
{
200
242
return $ "https://{ _vaultName } .vault.azure.net";
0 commit comments