I am using VS Code to develop an Azure function with Java 11. I am able to authenticate using VisualStudioCodeCredential but when I try to use the DefaultAzureCredential class I get the below error. It is my understanding that for this app to run locally and in the Azure hosted environment that I need the DefaultAzureCredential. Why does this happen and how do I fix it? Is there a better/preferred way to do the authentication?
Caused by: com.azure.core.exception.ClientAuthenticationException: DefaultAzureCredential
authentication failed. ---> IntelliJCredential authentication failed. Error Details:
Unrecognized field "tenantId" (class
com.azure.identity.implementation.IntelliJAuthMethodDetails), not marked as ignorable (4 known
properties: "authMethod", "azureEnv", "accountEmail", "credFilePath"])
Here is my code. The error occurs when I try to get the secret from the vault.
secretClient = new SecretClientBuilder().vaultUrl(System.getenv("KeyVaultURL"))
.credential(new DefaultAzureCredentialBuilder().build()).buildClient();
String secretValue= secretClient.getSecret("secretValue").getValue();
Using VisualStudioCodeCredential works:
secretClient = new SecretClientBuilder().vaultUrl(System.getenv("KeyVaultURL"))
.credential(new VisualStudioCodeCredential().build()).buildClient();
String secretValue= secretClient.getSecret("secretValue").getValue();
Links to some of the docs that I have used for reference.
https://learn.microsoft.com/en-us/java/api/overview/azure/identity-readme?view=azure-java-stable
https://learn.microsoft.com/en-us/azure/developer/java/sdk/identity#key-concepts
https://learn.microsoft.com/en-us/azure/developer/java/sdk/identity-azure-hosted-auth#default-azure-credential
The issue was occurring due to how DefaultAzureCredential chooses the authentication method. During runtime an error occurred because the app was unable to authenticate using IntelliJ authentication even though the app was running from Visual Studio Code.
Default Azure credential
The DefaultAzureCredential is appropriate for most scenarios where the application ultimately runs in the Azure Cloud. DefaultAzureCredential combines credentials that are commonly used to authenticate when deployed, with credentials that are used to authenticate in a development environment. The DefaultAzureCredential will attempt to authenticate via the following mechanisms in order.
Microsoft provides a way to get around this with the ChainedTokenCredential class.
The ChainedTokenCredential class provides the ability to link together multiple credential instances to be tried sequentially when authenticating. The following example demonstrates creating a credential which will attempt to authenticate using managed identity, and fall back to certificate authentication if a managed identity is unavailable in the current environment. This example authenticates an EventHubClient from the azure-eventhubs client library using the ChainedTokenCredential. There's also a compilable sample to create a Key Vault secret client you can copy-paste.
Using the ChainedTokenCredential I was able to change the order to check ManagedIdentityCredential and then VisualStudioCodeCredential.
Related
I am using the Java AWS IoT SDK, and i'm I'm stuck with a problem whereby I have to embed my AWS IAM access key and secret key credentials into my Java application code on my devices.
The credentials are just used initially to create the client in my code, then X.509 certificates are used after for the MQTT authentication and communication. .
I've heard of a way to avoid the need of embedding IAM credentials in the code by using AWSCredentialsProvider with tokens etc. However, I don't see any actual examples of how to achieve this without embedding credentials. Below is a snippet of my code showing how I create the client object using the credentials. Thanks.
String AWS_ACCESSKEY = "AKXXXXXXXXXXXXX"; // not real key
String AWS_SECRETKEY = "ABCXXXXXXXXXXXXXXXXXXXXXX"; // not real key
Regions AWS_REGION = Regions.US_EAST_2;
AWSIot client = AWSIotClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(new
BasicAWSCredentials(AWS_ACCESSKEY, AWS_SECRETKEY))).withRegion(AWS_REGION).build();
You can pass this credentials to normal application.properties file.
You just need to do 2 things.
Create public class AwsCredentials with annotations #ConfigurationProperties and #Configuration.
Pass Your access and secret to application.properties file
You can read more in this tutorial : click
Next when You want to use this properties in builder You need to call it like this:
AWSIot client = AWSIotClientBuilder.standard()
.withCredentials(
new AWSStaticCredentialsProvider(
new BasicAWSCredentials(
this.awsCredentials.getAccessKey(),
this.awsCredentials.getSecretKey()
)
)
)
.withRegion(AWS_REGION)
.build();
PS. You can export region to properties too.
You can use temporary security credentials instead of actual access keys. Do check this link.
https://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html
To get credentials to access AWS IoT (or other services) you could get temporary security credentials from Cognito Identity Pool. You can find the simplest way and steps needed to do get credentials here.
Also consider that, to get idToken (JWT) from Cognito user pool and then access and secret token Cognito Identity pool, you need to use AWS Java SDK in your mobile or desktop application. You can find more information about AWS JAVA SDK here and some samples here, here, .
I am developing a Google App Engine (Standard environment) application which uses Google Cloud Storage. I have used App Engine APIs for Cloud Storage until now, which provides a local emulation for the Cloud Storage using Datastore. As those APIs are getting obsolete now, I have decided to use the recommended APIs, however I am struggling with the credentials when running on the Local Server (I am already using the new Cloud Code plugin, not the old App Engine one).
I have created a service account and I have created and downloaded the key for it. If I would be running a normal Java app, I would be able to specify enviroment variables for the VM and I could provide the necessary -DGOOGLE_APPLICATION_CREDENTIALS=xxxxx.json parameters. The server provided by the Cloud Code does not seem to have any way how to provide environment variables, I can only provide VM options, therefore I do not know how can I provide the necessary environment to it, or how to pass the credentials to it in some other way. The only way I got it kind of working was using
gcloud auth application-default login
which has saved credentials in D:\Users\xxxx\AppData\Roaming\gcloud\application_default_credentials.json. This works, but any time I am debugging my application, I get following warning:
com.google.auth.oauth2.DefaultCredentialsProvider warnAboutProblematicCredentials
WARNING: Your application has authenticated using end user credentials from Google Cloud SDK. We recommend that most server applications use service accounts instead. If your application continues to use end user credentials from Cloud SDK, you might receive a "quota exceeded" or "API not enabled" error.
I am not sure how serious this warning is, but it sure sounds scary to me.
In my application I use this code (Scala, Java would be very similar) to create the service with the credentials:
val credentials = GoogleCredentials.getApplicationDefault
val storage = StorageOptions.newBuilder().setCredentials(credentials).build().getService
What is the proper way to pass service account credentials when running on a local Google App Engine server?
The issue with the big warning is that Google does not want you to use User Credentials in place of Service Account credentials. Google is locking down (restricting) what scopes/data third-party services (you) can request. My advice is to not use User Credentials anymore as they will eventually no longer work.
There are several methods to solve this.
Method 1: Setup the CLI to use a service account:
gcloud auth activate-service-account test#development.iam.gserviceaccount.com --key-file=test_google_account.json
Use the correct email address for the service account. This can be found in the Google Cloud console and also in the JSON file. Google libraries will find these credentials. On my website, I have written several articles on the details of services accounts, Application Default Credentials (ADC), etc.
Method 2: Specify the service account in your code
credentials = GoogleCredentials.fromStream(new FileInputStream(service_account_filename))
Create a flag or environment variable so that your code can if-else decide when running on your desktop to process credentials.
Method 3:
If the system (not the VM command line) environment variable GOOGLE_APPLICATION_CREDENTIALS is set, the libraries will use the filename that the variable points to for service account credentials. This file is a Google Cloud Service Account credentials file in JSON format.
Set this environment variable before you launch your IntelliJ.
My Document Links:
https://www.jhanley.com/google-cloud-application-default-credentials/
https://www.jhanley.com/google-cloud-setting-up-gcloud-with-service-account-credentials/
https://www.jhanley.com/google-cloud-creating-and-authorizing-service-account-credentials-with-the-cli/
I am new to Azure. I want to use Azure KeyVault to store secrets like passwords. I have successfully created All steps which mentioned in Microsoft website. And also able to get secrets (passwords from KeyVault) in our local environment by using Springboot application.properties .
But getting 403 Access denied error when I tried the same in Azure Cloud. It is not generated in local tomcat server. Please suggest me to resolve this issue.
Expected password, but getting 403.
You might need to
Enable system-assigned managed identity on an existing VM
Grant your VM access to a Secret stored in a Key Vault
Use Springboot key vault dependencies to get the secret.
In PowerShell run these commands to verify if key vault has right access permissions.
Get-AzureRmKeyVault -VaultName check what objectIds you see
Get-AzureRmADServicePrincipal -ObjectId check if your service's service principle (from AAD) is listed there.
you can also check out this link which i think may help you.
Following this tutorial: https://cloud.google.com/solutions/using-firebase-real-time-events-app-engine#securedata
I've got it working except that when I authenticate the custom token with Firebase, I get the following error:
Error: The custom token format is incorrect. Please check the documentation.
I have isolated the problem to the App Identity token signing. This is because the code works fine deployed to app-engine. It's just an issue when I try on devserver/localhost.
I have following the AppEngine documentation about setting up the default Service Account locally.
Setting the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of the .json service account keys. I've triple checked the variable is being set.
I tried the alternative method using the gcloud sdk, logging in as my owner account: gcloud beta auth application-default login. Still no luck.
To check I actually changed account, I use this method to get: AppIdentityServiceFactory.getAppIdentityService().getServiceAccountName();. In both configurations I detailed about, this method returns appname#localhost. I was expecting this to be the service account ID given in the .json. ie appname#appspot.gserviceaccount.com.
So I'm a bit at a loss how to debug this problem further, I assume the check I'm doing above is actually proving the validity of the configured service account. Perhaps its something unique to my setup?
Using App Engine Java, latest SDK 1.9.54
Run configuration launched with Maven 3 + IntelliJ
ArchLinux environment
I am trying to use the approach outlined in the following blog article to authenticate a cognito identity to S3 from Java:
https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-authentication-part-4-enhanced-flow/
I have successfully implemented the developer authentication provider and can retrieve a valid OpenId token for my cognito identity. That token works in both the iOS and Android SDKs when uploading/downloading files to S3. Unfortunately, I have not been able to successfully authenticate the same identity to S3 in my Java app. Here is the code I am using:
Map<String, String> logins = new HashMap();
logins.put("cognito-identity.amazonaws.com", cognitoOpenIdToken);
GetCredentialsForIdentityRequest getCredentialsRequest =
new GetCredentialsForIdentityRequest()
.withIdentityId(cognitoIdentityId)
.withLogins(logins);
AmazonCognitoIdentityClient cognitoIdentityClient =
new AmazonCognitoIdentityClient();
GetCredentialsForIdentityResult getCredentialsResult =
cognitoIdentityClient.getCredentialsForIdentity(getCredentialsRequest);
The call to getCredentialsForIdentity fails with the error "com.amazonaws.AmazonClientException: Unable to load AWS credentials from any provider in the chain". This method is documented as a public API that does not require authentication. However, I have noticed that the call succeeds if done from an environment where there are valid IAM credentials configured in the system variables. It fails in environments where that is not the case.
Am I missing something simple?
Have you tried initializing the AmazonCognitoIdentityClient in following manner?
new AmazonCognitoIdentityClient(new AnonymousAWSCredentials());
Otherwise, by design of AWS Java SDK, the service clients look for AWS credentials, because same client can be used for accessing Authenticated APIs as well.
maybe is not that you need to be as another IAM user... but that the user that is running you method has a "deny" on sts:* (or some other actions that you need)