Generate Azure KeyVault SecretIdentifier (Url) with Version - c#

We are creating secrets dynamically in azure key vault and now we want to get Secret Identifier / Uri with version so that secrets can be retrieved ?
Is there any built in method or easy way to generate Secret Identifier ? Mainly I am getting challenge to retrieve secret version.
Sample : https://YourVaultName.vault.azure.net/keys/YourKeyName/01234567890123456789012345678901
We are using keyvaultclient C# class to manage keyVault in our application

To get the current version of the secret, you could use GetSecretAsync .
I use Microsoft.Azure.Services.AppAuthentication to create a keyvault client, sample here.
var azureServiceTokenProvider1 = new AzureServiceTokenProvider();
var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider1.KeyVaultTokenCallback));
var secret = kv.GetSecretAsync("https://<keyvault-name>.vault.azure.net/", "<secret-name>").GetAwaiter().GetResult();
Console.WriteLine(secret.SecretIdentifier.Version);
If you want to get all the versions of the secret, you could use GetSecretVersionsAsync.
var versions = kv.GetSecretVersionsAsync("https://<keyvault-name>.vault.azure.net/", "<secret-name>").GetAwaiter().GetResult();

Related

Using C#, how to programmatically enable Azure Key Vault secret?

I need to programmatically enable / disable Azure Key Vault secrets in C#. I am able to disable a secret but I cannot figure out how to enable it. Here is the code:
//Setup client from Azure.Security.KeyVault.Secrets version 4.4.0
string keyVaultUrl = "…";
string tenantId = "…";
string clientId = "…";
string clientSecret = "…";
ClientSecretCredential credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
_client = new SecretClient(new Uri(keyVaultUrl), credential);
//I am able to disable a secret
Azure.Response<KeyVaultSecret> response = await _client.GetSecretAsync(secretName, version: null, cancellationToken);
KeyVaultSecret secret = response.Value;
secret.Properties.Enabled = false;
_client.UpdateSecretProperties(secret.Properties);
//I am not able to enable a secret. Get error "Value cannot be null. (Parameter 'Version')"
AsyncPageable<SecretProperties> secretPropertiesCollection = _client.GetPropertiesOfSecretsAsync(cancellationToken);
await foreach (SecretProperties secretProperties in secretPropertiesCollection)
{
if (secretProperties.Name.ToUpperInvariant() == secretName.ToUpperInvariant())
{
secretProperties.Enabled = true;
_client.UpdateSecretProperties(secretProperties);
return;
}
}
I work on the Java offering for the Key Vault SDK but can shed some light on this. It looks that the UpdateSecretProperties method expects a version of the secret to be included in the SecretProperties passed to it. We don't do this in Java so I would have to have a chat with my C# counterpart to figure if this is a bug or the intended behavior. That said, you should still be able to enable a disabled secret programatically. If you know the name of the secret in question, you can call a SecretClient.GetPropertiesOfSecretVersions() method to obtain the SecretProperties of each version of the secret, which also include the version itself. You can then update the Enabled property to true and use the UpdateSecretProperties as you originally intended.
I'm not a C# expert but I think this is what it should look like:
AsyncPageable<SecretProperties> secretPropertiesCollection =
_client.GetPropertiesOfSecretVersionsAsync("secretName", cancellationToken);
await foreach (SecretProperties secretProperties in secretPropertiesCollection)
{
secretProperties.Enabled = true;
_client.UpdateSecretProperties(secretProperties);
return;
}
Alternatively, if you still have a handle for the original KeyVaultSecret object, you can set its Enabled property back to true and use the SetSecret() operation to update it, although this would not create a new version for the secret as opposed to the option I laid out above.
"Value cannot be null. (Parameter 'Version')
As commented by #Ralf, This is a known exception caused when the UpdateSecretProperties() method is returned with a null version which is because the GetPropertiesOfSecrets() method doesn't return individual secret's versions which is returned as null.
Individual secret versions are not listed in the response. This operation requires the secrets/list permission.
Currently, the get() permissions only work for enabled secrets. The only way that worked for me is to enable the secrets from portal.

How to retrieve Secret from Azure Key Vault using DefaultAzureCredential

I have setup my keyVault in Azure, and add the secret there. I am now following instructions from Microsoft located here.
My current code looks like below:
var keyVaultName = Environment.GetEnvironmentVariable("KEY_VAULT_NAME");
var kvUri = "https://" + keyVaultName + "vault.azure.net";
var client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
var secret = (await client.GetSecretAsync("my-secret-key")).Value.Value;
I already set up the environment variable (system setting) to hold the name of the key vault with the variable name KEY_VAULT_NAME.
With the code above I am getting a exceptions: The requested name is valid, but no data of the requested type was found
I have a feeling I am using DefaultAzureCredential wrongly and that there is something I am missing?
I ended up using this resource by Microsoft, which uses virtually identical code but also has details on setting up a managed identity for your web app and giving it access to the specific Key Vault.
The code in my question is also now working having set up that managed identity access.

How to sign using new keyvault client from azure.security.keyvault

I recently started to replace the old Azure KeyVault client from the Microsoft.Azure.KeyVaultnamespace with the newer one in Azure.Security.KeyVault.
This works without any issues when getting secrets and certificates, but I am not sure how to sign anymore
How do I sign using the new keyvault client?
Did you check Azure SDK Azure.Security.KeyVault.Keys package on github?
Example code from that source:
SignResult rsaSignDataResult = rsaCryptoClient.SignData(SignatureAlgorithm.RS256, data);
Debug.WriteLine($"Signed data using the algorithm {rsaSignDataResult.Algorithm}, with key {rsaSignDataResult.KeyId}. The resulting signature is {Convert.ToBase64String(rsaSignDataResult.Signature)}");
For azure key vault, we need to create a signature from a digest using the specified key.
So, you could refer to the below code to sign some arbitrary data and verify the signatures using the CryptographyClient with both the EC and RSA keys we created.
byte[] digest = null;
using (HashAlgorithm hashAlgo = SHA256.Create())
{
digest = hashAlgo.ComputeHash(data);
}
SignResult rsaSignResult = rsaCryptoClient.Sign(SignatureAlgorithm.RS256, digest);
If you want to sign certificate you could refer to this article.

Azure keyvault from on prem .net app without exposing clientid/clientsecret?

I've registered my app in azure AD and created a client secret and then created a vault and added a secret for the dbconnectionstring below. It works ok but I need the "client-id" and "client-secret" since the identity is managed as service principal. Is there a way to get thos values through an API so that my app doesn't have to save those in the config? It's kind of defeating the purpose since thos whole exercise was to avoid having to save connection strings in the web.config/appsettings.json; as now I can save those in the vault but I would need to save the clientid/secret in the config.
var kvClient = new KeyVaultClient(async (authority, resource, scope) =>
{
var context = new AuthenticationContext(authority);
var credential = new ClientCredential("client-id", "client-secret");
AuthenticationResult result = await context.AcquireTokenAsync(resource, credential);
return result.AccessToken;
});
try
{
var connStrENTT = kvClient.GetSecretAsync("https://myvault.vault.azure.net/", "DBConfigConnection").Result.Value;
}
Why do you need to acquire token via your code if you are using managed identity? Managed identity is supposed to hide this for you.
Please use the guidance provided in a sample like this to take the correct steps.

How to pass credentials to use ResourceManagementClient to get all resources from azure resource group c#?

I have install nuget Microsoft.Azure.Management.ResourceManager and have following code to get all existing resources based on Resource Group Name
var resouceManagementClient = new ResourceManagementClient(credentials) { SubscriptionId = "mySubscriptionId" };
var listResources =
resouceManagementClient.ResourceGroups.ListResources("Demo-ResourceGroup");
I'm not sure from where I can get credentials parameter value.
I do not have Azure Active Directory access , I think its must , can
we bypass azure AD?.
In my azure portal I have create a Resource Group - Demo-ResourceGroup
and have many resources created.
I want only list of all existing resources using c# code.
One way is by grabbing an access token from Azure AD and passing it in to a TokenCredentials class.
var authContext = new AuthenticationContext(string.Format("https://login.windows.net/{0}", tenantId));
var credential = new ClientCredential(applicationId, password);
AuthenticationResult token = authContext.AcquireTokenAsync("https://management.core.windows.net/", credential).Result;
var credentials = new TokenCredentials(token.AccessToken);
The set of credentials you use to request the acces token (in this case clientId/secret) will determine whether the application has the appropriate rights to enumerate the resources. This is a good MS docs page on how to register your application with AAD. In the example above, applicationId and password come from the application registration in AAD
Microsoft has a page describing other ways you can get tokens from AAD.

Categories