add openhack files

This commit is contained in:
Ryan Peters
2022-11-03 16:41:13 -04:00
commit b2c9f7e29f
920 changed files with 118861 additions and 0 deletions

View File

@ -0,0 +1 @@
local.settings.json

View File

@ -0,0 +1,28 @@
// Default URL for triggering event grid function in the local environment.
// http://localhost:7071/runtime/webhooks/EventGrid?functionName={functionname}
using Microsoft.Extensions.Logging;
using Microsoft.Azure.WebJobs.Extensions.EventGrid;
using Azure.Messaging.EventGrid;
using Microsoft.Azure.WebJobs;
using System.Text.RegularExpressions;
namespace Microsoft.KeyVault
{
public static class AKVSQLRotation
{
[FunctionName("AKVSQLRotation")]
public static void Run([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log)
{
log.LogInformation("C# Event trigger function processed a request.");
var secretName = eventGridEvent.Subject;
var secretVersion = Regex.Match(eventGridEvent.Data.ToString(), "Version\":\"([a-z0-9]*)").Groups[1].ToString();
var keyVaultName = Regex.Match(eventGridEvent.Topic, ".vaults.(.*)").Groups[1].ToString();
log.LogInformation($"Key Vault Name: {keyVaultName}");
log.LogInformation($"Secret Name: {secretName}");
log.LogInformation($"Secret Version: {secretVersion}");
SecretRotator.RotateSecret(log, secretName, keyVaultName);
}
}
}

View File

@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
namespace Microsoft.KeyVault
{
public static class AKVSQLRotationHttp
{
[FunctionName("AKVSQLRotationHttp")]
public static IActionResult Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
string keyVaultName = req.Query["KeyVaultName"];
string secretName = req.Query["SecretName"];
if (string.IsNullOrEmpty(keyVaultName) || string.IsNullOrEmpty(secretName))
{
return new BadRequestObjectResult("Please pass a KeyVaultName and SecretName on the query string");
}
log.LogInformation(req.ToString());
log.LogInformation("C# Http trigger function processed a request.");
SecretRotator.RotateSecret(log, secretName, keyVaultName);
return new OkObjectResult($"Secret Rotated Successfully");
}
}
}

View File

@ -0,0 +1,14 @@
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS installer-env
COPY . /src/dotnet-function-app
RUN cd /src/dotnet-function-app && \
mkdir -p /home/site/wwwroot && \
dotnet publish *.csproj --output /home/site/wwwroot
# To enable ssh & remote debugging on app service change the base image to the one below
# FROM mcr.microsoft.com/azure-functions/dotnet:3.0-appservice
FROM mcr.microsoft.com/azure-functions/dotnet:3.0-slim
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
AzureFunctionsJobHost__Logging__Console__IsEnabled=true
COPY --from=installer-env ["/home/site/wwwroot", "/home/site/wwwroot"]

View File

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AzureFunctionsVersion>v3</AzureFunctionsVersion>
<RootNamespace>Microsoft.KeyVault</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Messaging.EventGrid" Version="4.7.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.EventGrid" Version="3.0.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.13" />
<PackageReference Include="Azure.Identity" Version="1.5.0" />
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.2.0" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="3.0.1" />
<PackageReference Include="Azure.Core" Version="1.20.0" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -0,0 +1,116 @@
using Azure.Security.KeyVault.Secrets;
using Microsoft.Data.SqlClient;
using System;
using Microsoft.Extensions.Logging;
using Azure.Identity;
using System.Security.Cryptography;
namespace Microsoft.KeyVault
{
public class SecretRotator
{
private const string CredentialIdTag = "CredentialId";
private const string ProviderAddressTag = "ProviderAddress";
private const string ValidityPeriodDaysTag = "ValidityPeriodDays";
public static void RotateSecret(ILogger log, string secretName, string keyVaultName)
{
//Retrieve Current Secret
var kvUri = "https://" + keyVaultName + ".vault.azure.net";
var client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
KeyVaultSecret secret = client.GetSecret(secretName);
log.LogInformation("Secret Info Retrieved");
//Retrieve Secret Info
var credentialId = secret.Properties.Tags.ContainsKey(CredentialIdTag) ? secret.Properties.Tags[CredentialIdTag] : "";
var providerAddress = secret.Properties.Tags.ContainsKey(ProviderAddressTag) ? secret.Properties.Tags[ProviderAddressTag] : "";
var validityPeriodDays = secret.Properties.Tags.ContainsKey(ValidityPeriodDaysTag) ? secret.Properties.Tags[ValidityPeriodDaysTag] : "";
log.LogInformation($"Provider Address: {providerAddress}");
log.LogInformation($"Credential Id: {credentialId}");
//Check Service Provider connection
CheckServiceConnection(secret);
log.LogInformation("Service Connection Validated");
//Create new password
var randomPassword = CreateRandomPassword();
log.LogInformation("New Password Generated");
//Add secret version with new password to Key Vault
CreateNewSecretVersion(client, secret, randomPassword);
log.LogInformation("New Secret Version Generated");
//Update Service Provider with new password
UpdateServicePassword(secret, randomPassword);
log.LogInformation("Password Changed");
log.LogInformation($"Secret Rotated Successfully");
}
private static void CreateNewSecretVersion(SecretClient client, KeyVaultSecret secret, string newSecretValue)
{
var credentialId = secret.Properties.Tags.ContainsKey(CredentialIdTag) ? secret.Properties.Tags[CredentialIdTag] : "";
var providerAddress = secret.Properties.Tags.ContainsKey(ProviderAddressTag) ? secret.Properties.Tags[ProviderAddressTag] : "";
var validityPeriodDays = secret.Properties.Tags.ContainsKey(ValidityPeriodDaysTag) ? secret.Properties.Tags[ValidityPeriodDaysTag] : "60";
//add new secret version to key vault
var newSecret = new KeyVaultSecret(secret.Name, newSecretValue);
newSecret.Properties.Tags.Add(CredentialIdTag, credentialId);
newSecret.Properties.Tags.Add(ProviderAddressTag, providerAddress);
newSecret.Properties.Tags.Add(ValidityPeriodDaysTag, validityPeriodDays);
newSecret.Properties.ExpiresOn = DateTime.UtcNow.AddDays(Int32.Parse(validityPeriodDays));
client.SetSecret(newSecret);
}
private static void UpdateServicePassword(KeyVaultSecret secret, string newpassword)
{
var userId = secret.Properties.Tags.ContainsKey(CredentialIdTag) ? secret.Properties.Tags[CredentialIdTag] : "";
var datasource = secret.Properties.Tags.ContainsKey(ProviderAddressTag) ? secret.Properties.Tags[ProviderAddressTag] : "";
var dbResourceId = secret.Properties.Tags.ContainsKey(ProviderAddressTag) ? secret.Properties.Tags[ProviderAddressTag] : "";
var dbName = dbResourceId.Split('/')[8];
var password = secret.Value;
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = $"{dbName}.database.windows.net";
builder.UserID = userId;
builder.Password = password;
//Update password
using (SqlConnection connection = new SqlConnection(builder.ConnectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand($"ALTER LOGIN {userId} WITH Password='{newpassword}';", connection))
{
command.ExecuteNonQuery();
}
}
}
private static string CreateRandomPassword()
{
const int length = 60;
byte[] randomBytes = new byte[length];
RNGCryptoServiceProvider rngCrypt = new RNGCryptoServiceProvider();
rngCrypt.GetBytes(randomBytes);
return Convert.ToBase64String(randomBytes);
}
private static void CheckServiceConnection(KeyVaultSecret secret)
{
var userId = secret.Properties.Tags.ContainsKey(CredentialIdTag) ? secret.Properties.Tags[CredentialIdTag] : "";
var dbResourceId = secret.Properties.Tags.ContainsKey(ProviderAddressTag) ? secret.Properties.Tags[ProviderAddressTag] : "";
var dbName = dbResourceId.Split('/')[8];
var password = secret.Value;
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = $"{dbName}.database.windows.net";
builder.UserID = userId;
builder.Password = password;
using (SqlConnection connection = new SqlConnection(builder.ConnectionString))
{
connection.Open();
}
}
}
}

View File

@ -0,0 +1,11 @@
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingExcludedTypes": "Request",
"samplingSettings": {
"isEnabled": true
}
}
}
}

View File

@ -0,0 +1,7 @@
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}