I have this code snippet:
I need to get the parameters:
keyIdentifier is easy enough:
clientId is also easy to find:
clientSecret - where do I get this??
Your screenshot is of a Managed Identity, there is no client secret that you can use.
It uses certificates internally, but that is not really relevant here.
My recommendation would be to use the Azure.Identity library to acquire tokens with DefaultAzureCredential.
And also use the newer KeyVault libraries e.g.:
https://www.nuget.org/packages/Azure.Security.KeyVault.Secrets/4.1.0
https://www.nuget.org/packages/Azure.Security.KeyVault.Keys/4.1.0
DefaultAzureCredential can use a system-assigned Managed Identity automatically and your user account in local development environments.
It tries multiple approaches and uses the one that works.
Related
How do I determine the Client Id of a user-assigned managed identity to an app service or function running on Azure? It's possible to assign multiple user-assigned managed identities and I'd like to get a list of the ones assigned to my app at runtime.
The goal of this is to avoid having to store the client id of the managed user identity in configuration for use in creating a DefaultAzureCredential for accessing KeyVault and other resources.
Right now my code looks like the following:
string managedIdentityClientId = Environment.GetEnvironmentVariable("ManagedIdentityClientId", EnvironmentVariableTarget.Process);
var options = new DefaultAzureCredentialOptions { ManagedIdentityClientId = managedIdentityClientId };
var keyVaultCredentials = new DefaultAzureCredential(options);
I'd like to avoid storing the ManagedIdentityClientId in app settings and simply read it from the configured app service if possible.
There is no way to get the client id of the user-assigned managed identity at runtime without credentials.
Even if you can use another way e.g. call the REST API in the code to get them, you will also need to use another credential(e.g. service principal), means you also need to expose the client id and secret in the code or store them in the app setting, this makes no sense.
So in your case, I think storing the client id in the app setting is the most feasible way to use MSI.
Since you can have multiple user-assigned managed identities on your Azure resource, there is no way to directly infer which user-assigned identity should be used and thus you need to specify it.
For system-assigned managed identities, you don't need to specify the clientId because you can only have 1 system-assigned per resource.
"I'd like to avoid storing the ManagedIdentityClientId in app settings and simply read it from the configured app service if possible."
Even if you could enlist all the user-assigned assigned to a resource, you'd have to have logic to pick the right one from the list. It is just easier to be explicitly specify the clientId via Config.
I have a pretty standard application written in Java which also runs queries against a DB. The application resides on GCP and the DB on Atlas.
For understandable reasons, I don't want to keep the username and password for the DB in the code.
So option number 1 that I had in mind, is to pass the username and password as environment variables to the application container in GCP.
Option number 2 is using Secret Manager in GCP and store my username and password there, and pass the GCP Credentials as an environment variable to the application container in GCP.
My question is, what is the added value of option number 2 if it has any? It seems that option 2 is even worse from a security aspect since if some hacker gets the google credentials, it has access to all of the secrets stored in the Secret Manager.
I don't know what are the best practices and what is advised to do in such cases. Thank you for your help.
Having credentials in GCP secret manager will help you to keep track of all the secrets and changes in a centralized location and access globally from any of your app.
For a standard application where one JAVA is connecting to a DB, may not add much values.
You may look into kubernetes secret for that reason.
If your application resides in GCP, you don't need a service account key file (which is your security concern, and you are right. I wrote an article on this)
TL;DR use ADC (Application Default Credential) to automatically get the service account credential provided automatically on Google Cloud Component (look at metadata server for more details).
Then grant this component identity (by default or user defined, when supported), i.e. the service account email, to access to your secrets.
And that's all! You haven't secrets in your code and your environment variable, neither the login/password, nor the service account key file.
If you have difficulties to use ADC in Java, don't hesitate to share your code. I will be able to help your to achieve this.
To use Secret Manager on Google Cloud you need to install the Secret Manager Java SDK Libraries. This documentation shows how to get started with the Cloud Client Libraries for the Secret Manager API, you only need to go to the Java section.
This Libraries helps you to access your keys in order that it can be used by your app.
The following link shows how to get details about a secret by viewing its metadata. Keep in mind that viewing a secret's metadata requires the Secret Viewer role (roles/secretmanager.viewer) on the secret, project, folder, or organization.
I recommend you to create a special Service Account to handle the proper permissions for your app, because if you don’t have a SA defined, the default SA is what is going to generate the request, and it is not secure. you can learn more about how to create a service account in this link
On the other hand, you can find an example on how you can use the following guide that contains a good example of finding your credentials automatically, that's more convenient and secure than manually passing credentials.
I would like to create ARM Template
create a resource group that contains KeyVault;
generate new secret with predefined name, e.g AdminPassword.
Use the password in other resources, e.g Master password when creating a SQL Database.
When redeploying the template and KeyVault and the AdminPassword secret already exist, existing secret should be used.
I have found samples where KeyVault secret is used as a parameter, however this is different, because KeyVault does not exist at the time parameters are resolved.
Can you write sample ARM teplate that creates KeyVault and then uses sectets from it?
if you generate a secret in an arm template - it makes no sense to retrieve it from the key vault, if you pass the secret to the template - again it makes no sense to retrieve it, just use it. either way, if you are really keen on making your life harder you can probably hack something in the arm template using conditions and nested templates
It depends on how secure you want the password to be...
If you want a subsequent deployment to use the same password value, then it has to be deterministic. If it's deterministic then anyone with access to the deployment can determine the password.
If you want the password to be random, then the template will generate a random one each time so a subsequent deployment would create a new password.
You could use a user provided seed for the password generation as a parameter (and use uniqueString() which is idempotent) and then only someone who knows the seed and has access to the deployment could determine the password. Note that your seed would have to be a secureString parameter type. But at this point a better practice would be to separate the steps of password generation and resource deployment.
You can generate the password in the ARM Template using uniqueString.
Then create your KeyVault and the Secret. On the outputs of the KeyVault template you can then get the URI of the Secret which can be injected into the App Configuration of another resource such as a Web App. https://learn.microsoft.com/en-us/azure/app-service/app-service-key-vault-references
"outputs": {
"dbSecretUri": {
"value": "[reference(resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), 'yourSecretName')).secretUriWithVersion]"
}
}
Your web app will need Managed Identity enabled and the KeyVault will need to have an Access Policy that allows that app to connect to the vault.
Is it common practice to store the EH Connection string, clientid and secret in Key Vault?
Do you then refer the producer client to retrieve from Key Vault stored
MSFT documentation is a bit more focused on web apps to me.
My noddy interpretation
Storing your secrets like connection strings in something like KeyVault is generally always a good idea.
For your particular scenario this seems valid as well. Even better would be, though, if you could use Azure AD authentication directly against the Event Hub. This depends on whether the client SDK you use does support it yet.
I want to get the availability of azure resources. Right now I am using:
GET "https://management.azure.com/{}/providers/Microsoft.ResourceHealth/
availabilityStatuses/current?api-version=2015-01-01" api for which I need to get jwt.
Is there any Python SDK way to do the same thing as in
https://learn.microsoft.com/en-us/python/api/overview/azure/monitoring?view=azure-python
I want to use something similar to:
credentials = ServicePrincipalCredentials(
client_id=client_id,
secret=secret_key,
tenant=tenant_id,
cloud_environment=AZURE_PUBLIC_CLOUD
)
client = MonitorManagementClient(
credentials,
subscription_id
)
Rather than generating jwt token and running the API, I wish to use pythonic way where I can use client_id, secret, tenant and cloud_environment.
There is no SDK as of now, but seeing your issue I created an issue in the Azure SDK repo:
https://github.com/Azure/azure-sdk-for-python/issues/8343
We actually generate SDK from a service meta-description, and we have access to this one, so we should be able to generate this SDK for you.
Please follow-up on the Github issue ticket
(I work at MS in the Azure SDK team)