Reputation: 65
I am trying to get secret from azure keyvault. When i run class independently from main method it returns secret but when i integrated this same code in servlet application at code line future.get(); here it gets blocks it do not proceed further like a deadlock it keeps waiting and sometime get java.util.concurrent.ExecutionException: java.lang.ClassCastException: java.lang.String cannot be cast to java.util.List and com.microsoft.azure.keyvault.models.KeyVaultErrorException: Status code 401, {"error":{"code":"Unauthorized","message":"AKV10001: Unable to parse JWT token: expected 3 compact JSON elements, found 1."}} at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) .Please help me on this.
public class KeyVaultTest {
private static AuthenticationResult getAccessToken(String authorization, String resource) throws InterruptedException, ExecutionException, MalformedURLException {
String clientId = "XXX"; // Client ID
String clientSecret = "XXX"; //Client Secret
AuthenticationResult result = null;
//Starts a service to fetch access token.
ExecutorService service = null;
try {
service = Executors.newFixedThreadPool(1);
AuthenticationContext context = new AuthenticationContext(authorization, false, service);
Future<AuthenticationResult> future = null;
//Acquires token based on client ID and client secret.
if (clientSecret != null && clientSecret != null) {
ClientCredential credentials = new ClientCredential(clientId, clientSecret);
future = context.acquireToken(resource, credentials, null);
}
result = future.get();
} finally {
service.shutdown();
}
if (result == null) {
throw new RuntimeException("Authentication results were null.");
}
return result;
}
public static void main(String[] args) {
String vaultBase = "https://myapp-keyvault.vault.azure.net/";
KeyVaultClient keyVaultClient = new KeyVaultClient(new KeyVaultCredentials(){
@Override
public String doAuthenticate(String authorization, String resource, String scope) {
String token = null;
try {
AuthenticationResult authResult = getAccessToken(authorization, resource);
token = authResult.getAccessToken();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(token);
return token;
}
});
SecretBundle secretBundle = keyVaultClient.getSecret(vaultBase, "abc");
System.out.println(secretBundle.value());
}
Upvotes: 0
Views: 1162
Reputation: 25
your keyvault most likely has IPv4/CIDR restrictions. check your IP and make sure it's on that list OR make sure you route your traffic through an approved IP (VPN)
Upvotes: 0
Reputation: 23161
If you want to access Azure key vault in your servlet application, please refer to the following steps
#create service pricipal
az ad sp create-for-rbac -n "MyApp" --password "hVFkk965BuUv" --skip-assignment --sdk-auth
#set access policy
az keyvault set-policy -n <your-unique-keyvault-name> --spn <clientId-of-your-service-principal> --secret-permissions list get set delete purge
Application
a. SDK
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>adal4j</artifactId>
<version>1.6.5</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-keyvault</artifactId>
<version>1.2.4</version>
</dependency>
b. Servlet Class
@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public HelloServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String appId="42e0d080-b1f3-40cf-8db6-c4c522d988c4";
String appSecret="Gbx2eK64iqq_g_3NCA.ClJDfQpIjoae:";
KeyVaultClient keyVaultClient = new KeyVaultClient(new AzureKeyVaultCredential(appId,appSecret));
String vaultBaseUrl="https://testsql08.vault.azure.net/";
String secretName="sql";
SecretBundle secret =keyVaultClient.getSecret(vaultBaseUrl, secretName);
System.out.println(secret.value());
PrintWriter writer = response.getWriter();
writer.println("<h1>Hello " + secret.value() + "</h1>");
writer.close();
}
}
class AzureKeyVaultCredential extends KeyVaultCredentials {
private String appId;
private String appSecret;
public AzureKeyVaultCredential(String appId, String appSecret) {
this.appId = appId;
this.appSecret = appSecret;
}
@Override
public String doAuthenticate(String authorization, String resource, String scope) {
AuthenticationContext context = null;
AuthenticationResult result = null;
String token = "";
try {
context = new AuthenticationContext(authorization, false, Executors.newSingleThreadExecutor());
ClientCredential credential = new ClientCredential(this.appId, this.appSecret);
Future<AuthenticationResult> future = context.acquireToken(resource, credential, null);
result = future.get(3, TimeUnit.MINUTES);
token = result.getAccessToken();
} catch (Exception e) {
e.printStackTrace();
}
return token;
}
}
Upvotes: 0