Skip to content

Instantly share code, notes, and snippets.

@justinyoo
Created November 26, 2019 10:41
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save justinyoo/1b7ee5e2fb0829bf74dfdfd2ee2f6c72 to your computer and use it in GitHub Desktop.
Backup & Restore Key Vault Secrets via Azure Functions
public async Task<List<BackupSecretResult>> BackupSecretsAsync(List<string> secrets)
{
// Declares a KeyVaultClient instance.
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var kv = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(
azureServiceTokenProvider.KeyVaultTokenCallback));
// Performs the backup and add the result into the list.
var results = new List<BackupSecretResult>();
var baseUri = "https://my-keyvault.vault.azure.net/";
foreach (var name in secrets)
{
var result = await kv.BackupSecretAsync(baseUri, name)
.ConfigureAwait(false);
results.Add(result);
}
// Returns the backup results.
return results;
}
[FunctionName(nameof(BackupSecrets))]
public async Task<IActionResult> BackupSecrets(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "secrets/backup")] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
// Gets the list of secrets.
var secrets = await this.GetSecretsAsync().ConfigureAwait(false);
// Performs the backup.
var results = await this.BackupSecretsAsync(secrets).ConfigureAwait(false);
// Uploads the backup data.
var uploaded = await this.UploadAsync(results).ConfigureAwait(false);
return new OkObjectResult(results);
}
public async Task<List<BackupSecretResult>> DownloadAsync(string timestamp)
{
// Declares the BlobClient instance.
var connectionString = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
var client = CloudStorageAccount.Parse(connectionString)
.CreateCloudBlobClient();
// Gets the Blob container.
var containerName = "backups";
var container = client.GetContainerReference(containerName);
// Gets the Blob.
var blobName = $"{timestamp}.json";
var blob = container.GetBlockBlobReference(blobName);
// Downloads the Blob content.
var downloaded = await blob.DownloadTextAsync().ConfigureAwait(false);
// Deserialises the contents.
var results = JsonConvert.DeserializeObject<List<BackupSecretResult>>(downloaded);
// Returns the result.
return results;
}
public async Task<List<string>> GetSecretsAsync()
{
// Declares a KeyVaultClient instance.
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var kv = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(
azureServiceTokenProvider.KeyVaultTokenCallback));
// Gets the list of secrets.
var baseUri = "https://myu-keyvault.vault.azure.net/";
var secrets = await kv.GetSecretsAsync(baseUri)
.ConfigureAwait(false);
// Returns the list of secret names.
return secrets.Select(p => p.Identifier.Name).ToList();
}
public async Task<List<string>> RestoreSecretsAsync(string key, List<BackupSecretResult> secrets)
{
// Declares a KeyVaultClient instance.
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var kv = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(
azureServiceTokenProvider.KeyVaultTokenCallback));
// Performs the restore and add the result into the list.
var results = new List<SecretBundle>();
var baseUri = "https://my-keyvault.vault.azure.net/";
foreach (var secret in secrets)
{
var result = await kv.RestoreSecretAsync(baseUri, secret.Value)
.ConfigureAwait(false);
results.Add(result);
}
// Returns the list of secret names.
return results.Select(p => p.SecretIdentifier.Name).ToList();
}
[FunctionName(nameof(RestoreSecrets))]
public async Task<IActionResult> RestoreSecrets(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "secrets/restore/{timestamp}")] HttpRequest req,
string timestamp,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
// Downloads the backup of the given timestamp.
var secrets = await this._blob.DownloadAsync(timestamp).ConfigureAwait(false);
// Performs the restore from the backup.
var results = await this._secret.RestoreSecretsAsync("restore", secrets).ConfigureAwait(false);
return new OkObjectResult(results);
}
public async Task<bool> UploadAsync(List<BackupSecretResult> results)
{
// Declares the BlobClient instance.
var connectionString = Environment.GetEnvironmentVariable("AzureWebJobsStorage");
var blob = CloudStorageAccount.Parse(connectionString)
.CreateCloudBlobClient();
// Gets the Blob container.
var containerName = "backups";
var container = blob.GetContainerReference(containerName);
await container.CreateIfNotExistsAsync().ConfigureAwait(false);
// Gets the Blob.
var blobName = $"{DateTimeOffset.UtcNow.ToString("yyyyMMdd")}.json";
var blob = container.GetBlockBlobReference(blobName);
// Serialises the backup result.
var serialised = JsonConvert.SerializeObject(results);
// Uploads the backup result to Blob Storage.
await blob.UploadTextAsync(serialised).ConfigureAwait(false);
// Returns true, if everything is OK.
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment