I’m new to using C# in Azure and I’m running an inline C# script in an Azure Logic Apps workflows to read a Key Vault secret into a variable from within a ‘CSharp Script Code’ object in an Azure Workflow. But nothing I’ve read on the internet appears to work. Should this be a simple one-line command as I’ve been told?
I have a secret named ‘HMAC’ connected to the HMACKey name in the workflow and was told to use the code string secretKey = await {Azure Key Vault Client}.GetSecretAsync({Azure Key Vault Url}, {Azure Secret})
to retrieve this.
I’m assuming {Key Vault Url} means the first part of the URI for the Secret Identifier, which in my test case is ‘https://hmactesting.vault.azure.net’, and the secret is the name of the secret ‘HMAC’ in this case.
But what is meant by {Azure Key Vault Client} in this instance? Is this a ‘new KeyVaultClient()’ type that I have to declare and authorise in the inline code, or does this already exist as an environment variable within the workflow that I can attach to and use?
I’ve searched the net but can’t find anything specifically relating to how to do this from within an inline ‘CSharp Script Code’ object in an Azure Workflow?
I believe the strings for ‘KeyVaultUrl’ and ‘secret’ are correct in the command, which leaves the {Azure Key Vault Client} object. Is this something still I have to create in the code? I’ve seen examples of C# code where this is created, but those were not using the Azure workflow and C# scripting object.
I can already see the secret I’m trying to read when I set it up as an object in the workflow, so can I connect to this from within the C# script?
My full test script is as follows:
// Add the required libraries
#r "Newtonsoft.Json"
#r "Microsoft.Azure.Workflows.Scripting"
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Workflows.Scripting;
using Newtonsoft.Json.Linq;
using System;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
/// <summary>
/// Executes the inline csharp code.
/// </summary>
/// <param name="context">The workflow context.</param>
/// <remarks> This is the entry-point to your code. The function signature should remain unchanged.</remarks>
public static async Task<Results> Run(WorkflowContext context, ILogger log)
{
//String Variables (for clarity)
string KeyVaultUrl = "https://hmactesting.vault.azure.net";
string secret = "HMAC";
string compare = string.Empty;
string _origonalMessage = string.Empty;
string _origonalHmac = string.Empty;
string _calculatedHmac = string.Empty;
////Define the trigger output.
var triggerOutputs = (await context.GetTriggerResults().ConfigureAwait(false)).Outputs;
//string kvSecret = await kVClient.GetSecretAsync(azureKeyVaultUrl, secret);
////Set the local HMAC key from the Azure Key Vault.
string secretKey = "HMAC-TEST"; // <--Temporary for testing.
//I need to get the above value from the 'HMAC' secret in the 'HMACTesting' Key Vault
//The example I was given was to use: string secretKey = await {Azure Key Vault Client}.GetSecretAsync({Azure Key Vault Url}, {Azure secret});
//Assuming I have the correct {Key Vault Url} I need to know what is meant by {Key Vault Client} do I need to build this?
//var key = await ((WHAT?)).GetSecretAsync(KeyVaultUrl, secret) // <-- Should this work? If yes, could it be a permissions thing? Although I can see the secret contents when using an object on the workflow.
////Set the whole JSON body text from the trigger.
var origonalMessage = triggerOutputs["body"].ToString();
_origonalMessage = origonalMessage;
////Set the remote HMAC encripted text from the Azure header. (needs to be the input header)
var receievedHmac = triggerOutputs?["headers"]?["HMACEncripted"]?.ToString();
_origonalHmac = receievedHmac;
////Encript the body text with the local HMAC key and compaire with the remote Encripted text.
//convert key and message to byte arrays
byte[] keyBytes = Encoding.UTF8.GetBytes(secretKey);
byte[] messageBytes = Encoding.UTF8.GetBytes(origonalMessage);
//Create an HMAC SHA256 instance with the local key
using (HMACSHA256 hmac = new HMACSHA256(keyBytes))
{
//Compute the HMAC and convert it to a string
byte[] hashBytes = hmac.ComputeHash(messageBytes);
var localHmac = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
_calculatedHmac = localHmac;
}
//Compare the computed HMAC with the received HMAC
string testString = "GAURAV";
if (_calculatedHmac.Equals(receievedHmac, StringComparison.OrdinalIgnoreCase))
{
compare = "Match";
}
else
{
compare = "noMatch";
;
}
return new Results
{
Message = compare
};
}
public class Results
{
public string Message {get; set;}
}
The rest of this works as expected apart from getting the key vault value. Is there a straightforward way to read the secret from the key vault?
I realise this is probably a very simple question but just can’t find anything relatable to the inline C# code when searching.
Any help would be appreciated.
2
Answers
Execute CSharp Script Code action in standard logic app is currently in preview and reference of some assemblies might not be supported at this moment.
I have used the Environment Variable approach to fetch the secret value from key vault.
In order to do so, first you need to grant the secret permissions to the logic app’s managed identity in key vault’s Access policies or you can grant RBAC role too.
Then, add the key vault reference in
@Microsoft.KeyVault(SecretUri=https://{keyvaultName}.vault.azure.net/secrets/{secretName})
format as shown below.Your approach is a very long winded way to get the secret value. LogicApps is a low code environment for a reason so why write code to do this?
Firstly, use the first answer as a reference for how to setup the managed identity to have access to the keyvault and the secret, that’s number one.
Now, rather than using the inline C# operation, you should just get the value directly via the
appsetting
function.https://techcommunity.microsoft.com/blog/integrationsonazureblog/programmatically-accessing-app-settings-from-logic-apps-expressions/3680407
Literally just create the expression in a
Compose
orInitialize Variable
operation.So for completion, create the environment variable using the reference notation as specified in the fourth point in the first answer and then you can use the
appsetting
function in an expression by simply passing in the name of that environment variable and it will give you the value.e.g. …
appsetting('HMACKey')
Additional reference … https://learn.microsoft.com/en-us/azure/app-service/app-service-key-vault-references?tabs=azure-cli