private async Task UpdateSecretsAsync(string thumbprintFromManifest, string x509StoreNameFromManifest, CancellationToken cancellationToken) { BackupRestoreTrace.TraceSource.WriteInfo(TraceType, String.Format("Updating secrets using the new thumbprint {0}", thumbprintFromManifest)); using (var transaction = this.StateManager.CreateTransaction()) { try { var policyStore = await BackupPolicyStore.CreateOrGetBackupPolicyStore(this); var workItemQueue = await WorkItemQueue.CreateOrGetWorkItemQueue(this); var policies = await policyStore.GetValuesAsync(Common.Constants.StoreTimeOut, cancellationToken, transaction); foreach (var policy in policies) { cancellationToken.ThrowIfCancellationRequested(); var updatedStorage = this.UpdateSecretInStorage(policy.Storage, thumbprintFromManifest, x509StoreNameFromManifest, cancellationToken); var newPolicy = policy.ToBuilder() .WithBackupStorage(updatedStorage) .UpdateUniqueId() .Build(); if (!await policyStore.UpdateValueAsync(policy.Name, policy, newPolicy, Common.Constants.StoreTimeOut, cancellationToken, transaction)) { throw new InvalidOperationException(String.Format("Failed to update secret for policy with name {0}", newPolicy.Name)); } if (newPolicy.BackupEnabledSet.Count > 0) { await workItemQueue.AddWorkItem( new UpdateEnablementWorkItem(newPolicy.BackupEnabledSet.ToList(), new WorkItemInfo { WorkItemType = WorkItemPropogationType.UpdateBackupPolicy, BackupPolicyUpdateGuid = newPolicy.UniqueId }), Common.Constants.StoreTimeOut, cancellationToken, transaction); } } // Update the config store var configStore = await ConfigStore.CreateOrGetConfigStore(this); await configStore.UpdateValueAsync(Common.Constants.SecretUpdateInProgress, String.Empty, Common.Constants.StoreTimeOut, cancellationToken, transaction); await configStore.UpdateValueAsync(Common.Constants.EncryptionCertThumbprintKey, thumbprintFromManifest, Common.Constants.StoreTimeOut, cancellationToken, transaction); await transaction.CommitAsync(); BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "All secrets updated with manifest {0}", thumbprintFromManifest); FabricEvents.Events.BRSSecretsUpdated(TraceType, thumbprintFromManifest); } catch (Exception ex) { BackupRestoreTrace.TraceSource.WriteExceptionAsWarning(TraceType, ex, "Exception encountered while updating secrets"); throw; } } }
public async Task InitializeAsync() { // Read the state and update the config in the store and trigger update callback if needed // Check if the secret certificate has been updated or not // Get the current certificate from store string thumbprintFromManifest, x509StoreNameFromManifest; var updateSecrets = false; var configStore = await ConfigStore.CreateOrGetConfigStore(this.statefulService); using (var transaction = this.statefulService.StateManager.CreateTransaction()) { var val = await configStore.GetValueAsync(Common.Constants.SecretUpdateInProgress, transaction); // Check explicitly if the configured secret in manifest and the secret stored in ConfigStore are same or not var thumbprintFromStore = await configStore.GetValueAsync(Common.Constants.EncryptionCertThumbprintKey, transaction); // Initialize and fetch the thumbprint configured in manifest this.GetConfigFromNativeConfigStore(out thumbprintFromManifest, out x509StoreNameFromManifest); if (String.IsNullOrEmpty(val)) { if (String.IsNullOrEmpty(thumbprintFromManifest)) { thumbprintFromManifest = null; } if (String.IsNullOrEmpty(thumbprintFromStore)) { thumbprintFromStore = null; } // Thumbprint for encryption cert has changed, let's update secrets if (!String.Equals(thumbprintFromManifest, thumbprintFromStore, StringComparison.InvariantCultureIgnoreCase)) { BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "The existing and new thumprints dont match, existing {0}, new {1}, triggering secrets udpate", thumbprintFromStore, thumbprintFromManifest); updateSecrets = true; } } else { BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "Detected update in progress flag, triggering secrets update"); // There is an update in progress, let's update secrets updateSecrets = true; } if (updateSecrets) { // Set secret update in progress flag by setting some random guid value. await configStore.UpdateValueAsync(Common.Constants.SecretUpdateInProgress, Guid.NewGuid().ToString(), transaction); } await transaction.CommitAsync(); } lock (Lock) { EncryprtionCertThumprint = thumbprintFromManifest; EncryptionCertStoreName = x509StoreNameFromManifest; } if (updateSecrets) { BackupRestoreTrace.TraceSource.WriteInfo(TraceType, "Invoking update cert callback"); // Trigger the update secrets callback this.updateCertCallback(thumbprintFromManifest, x509StoreNameFromManifest, this.runAsyncCancellationToken); } }