@@ -78,9 +78,19 @@ public async virtual Task<HostSecretsInfo> GetHostSecretsAsync()
78
78
await PersistSecretsAsync ( hostSecrets ) ;
79
79
}
80
80
81
- // Host secrets will be in the original persisted state at this point (e.g. encrypted),
82
- // so we read the secrets running them through the appropriate readers
83
- hostSecrets = ReadHostSecrets ( hostSecrets ) ;
81
+ try
82
+ {
83
+ // Host secrets will be in the original persisted state at this point (e.g. encrypted),
84
+ // so we read the secrets running them through the appropriate readers
85
+ hostSecrets = ReadHostSecrets ( hostSecrets ) ;
86
+ }
87
+ catch ( CryptographicException )
88
+ {
89
+ _traceWriter . Verbose ( Resources . TraceNonDecryptedHostSecretRefresh ) ;
90
+ _logger ? . LogDebug ( Resources . TraceNonDecryptedHostSecretRefresh ) ;
91
+ await PersistSecretsAsync ( hostSecrets , null , true ) ;
92
+ await RefreshSecretsAsync ( hostSecrets ) ;
93
+ }
84
94
85
95
// If the persistence state of any of our secrets is stale (e.g. the encryption key has been rotated), update
86
96
// the state and persist the secrets
@@ -132,8 +142,19 @@ public async virtual Task<IDictionary<string, string>> GetFunctionSecretsAsync(s
132
142
await PersistSecretsAsync ( secrets , functionName ) ;
133
143
}
134
144
135
- // Read all secrets, which will run the keys through the appropriate readers
136
- secrets . Keys = secrets . Keys . Select ( k => _keyValueConverterFactory . ReadKey ( k ) ) . ToList ( ) ;
145
+ try
146
+ {
147
+ // Read all secrets, which will run the keys through the appropriate readers
148
+ secrets . Keys = secrets . Keys . Select ( k => _keyValueConverterFactory . ReadKey ( k ) ) . ToList ( ) ;
149
+ }
150
+ catch ( CryptographicException )
151
+ {
152
+ string message = string . Format ( Resources . TraceNonDecryptedFunctionSecretRefresh , functionName ) ;
153
+ _traceWriter . Verbose ( message ) ;
154
+ _logger ? . LogDebug ( message ) ;
155
+ await PersistSecretsAsync ( secrets , functionName , true ) ;
156
+ await RefreshSecretsAsync ( secrets , functionName ) ;
157
+ }
137
158
138
159
if ( secrets . HasStaleKeys )
139
160
{
@@ -372,10 +393,27 @@ private Task RefreshSecretsAsync<T>(T secrets, string keyScope = null) where T :
372
393
return PersistSecretsAsync ( refreshedSecrets , keyScope ) ;
373
394
}
374
395
375
- private Task PersistSecretsAsync < T > ( T secrets , string keyScope = null ) where T : ScriptSecrets
396
+ private async Task PersistSecretsAsync < T > ( T secrets , string keyScope = null , bool isNonDecryptable = false ) where T : ScriptSecrets
376
397
{
398
+ ScriptSecretsType secretsType = secrets . SecretsType ;
377
399
string secretsContent = ScriptSecretSerializer . SerializeSecrets < T > ( secrets ) ;
378
- return _repository . WriteAsync ( secrets . SecretsType , keyScope , secretsContent ) ;
400
+ if ( isNonDecryptable )
401
+ {
402
+ string [ ] secretBackups = await _repository . GetSecretSnapshots ( secrets . SecretsType , keyScope ) ;
403
+
404
+ if ( secretBackups . Length >= ScriptConstants . MaximumSecretBackupCount )
405
+ {
406
+ string message = string . Format ( Resources . ErrorTooManySecretBackups , ScriptConstants . MaximumSecretBackupCount , string . IsNullOrEmpty ( keyScope ) ? "host" : keyScope ) ;
407
+ _traceWriter . Verbose ( message ) ;
408
+ _logger ? . LogDebug ( message ) ;
409
+ throw new InvalidOperationException ( message ) ;
410
+ }
411
+ await _repository . WriteSnapshotAsync ( secretsType , keyScope , secretsContent ) ;
412
+ }
413
+ else
414
+ {
415
+ await _repository . WriteAsync ( secretsType , keyScope , secretsContent ) ;
416
+ }
379
417
}
380
418
381
419
private HostSecrets ReadHostSecrets ( HostSecrets hostSecrets )
0 commit comments