@@ -68,17 +68,23 @@ public override async Task WriteAsync(ScriptSecretsType type, string functionNam
6868 Dictionary < string , string > dictionary = GetDictionaryFromScriptSecrets ( secrets , functionName ) ;
6969
7070 // Delete existing keys
71- string prefix = ( type == ScriptSecretsType . Host ) ? HostPrefix : FunctionPrefix + Normalize ( functionName ) ;
71+ List < IEnumerable < SecretItem > > secretsPages = await GetKeyVaultSecretsPagesAsync ( _keyVaultClient . Value , GetVaultBaseUrl ( ) ) ;
7272 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 ) ) )
7476 {
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 ) )
7779 {
7880 deleteTasks . Add ( _keyVaultClient . Value . DeleteSecretAsync ( GetVaultBaseUrl ( ) , item . Identifier . Name ) ) ;
7981 }
8082 }
81- await Task . WhenAll ( deleteTasks ) ;
83+
84+ if ( deleteTasks . Any ( ) )
85+ {
86+ await Task . WhenAll ( deleteTasks ) ;
87+ }
8288
8389 // Set new secrets
8490 List < Task > setTasks = new List < Task > ( ) ;
@@ -112,28 +118,28 @@ public override Task<string[]> GetSecretSnapshots(ScriptSecretsType type, string
112118
113119 private async Task < ScriptSecrets > ReadHostSecrets ( )
114120 {
115- IPage < SecretItem > secretItems = await _keyVaultClient . Value . GetSecretsAsync ( GetVaultBaseUrl ( ) ) ;
121+ List < IEnumerable < SecretItem > > secretsPages = await GetKeyVaultSecretsPagesAsync ( _keyVaultClient . Value , GetVaultBaseUrl ( ) ) ;
116122 List < Task < SecretBundle > > tasks = new List < Task < SecretBundle > > ( ) ;
117123
118124 // 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 )
121127 {
122- tasks . Add ( _keyVaultClient . Value . GetSecretAsync ( GetVaultBaseUrl ( ) , masterItem . Identifier . Name ) ) ;
128+ tasks . Add ( _keyVaultClient . Value . GetSecretAsync ( GetVaultBaseUrl ( ) , masterItems [ 0 ] . Identifier . Name ) ) ;
123129 }
124130 else
125131 {
126132 return null ;
127133 }
128134
129135 // 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 ) ) )
131137 {
132138 tasks . Add ( _keyVaultClient . Value . GetSecretAsync ( GetVaultBaseUrl ( ) , item . Identifier . Name ) ) ;
133139 }
134140
135141 // 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 ) ) )
137143 {
138144 tasks . Add ( _keyVaultClient . Value . GetSecretAsync ( GetVaultBaseUrl ( ) , item . Identifier . Name ) ) ;
139145 }
@@ -168,13 +174,15 @@ private async Task<ScriptSecrets> ReadHostSecrets()
168174
169175 private async Task < ScriptSecrets > ReadFunctionSecrets ( string functionName )
170176 {
171- IPage < SecretItem > secretItems = await _keyVaultClient . Value . GetSecretsAsync ( GetVaultBaseUrl ( ) ) ;
177+ List < IEnumerable < SecretItem > > secretsPages = await GetKeyVaultSecretsPagesAsync ( _keyVaultClient . Value , GetVaultBaseUrl ( ) ) ;
172178 List < Task < SecretBundle > > tasks = new List < Task < SecretBundle > > ( ) ;
173179 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 ) ) )
175182 {
176183 tasks . Add ( _keyVaultClient . Value . GetSecretAsync ( GetVaultBaseUrl ( ) , item . Identifier . Name ) ) ;
177184 }
185+
178186 if ( ! tasks . Any ( ) )
179187 {
180188 return null ;
@@ -195,6 +203,40 @@ private async Task<ScriptSecrets> ReadFunctionSecrets(string functionName)
195203 return functionSecrets ;
196204 }
197205
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+
198240 private string GetVaultBaseUrl ( )
199241 {
200242 return $ "https://{ _vaultName } .vault.azure.net";
0 commit comments