0

I have a Azure Function In Java. Using Managed Identity and Key Vault reference, I have added a configuration in function app to access the key vault secret and certificate. The secret is referenced correctly and I am able to access its value in Azure Function.

When accessing the certificate from Azure Key Vault, using System.getenv(, I get a string which is encoded. How can I convert that string into a valid certificate in pfx or pem format.

Is there any other way to securely access certificate from Azure Key Vault in the Azure function using Java as runtime language.

the_eagle
  • 31
  • 4
  • Hello @the_eagle, may I know if you have referred this SO thread : https://stackoverflow.com/questions/55599001/azure-function-key-vault-reference-for-certificates – RamaraoAdapa Sep 06 '21 at 07:33
  • Hi @RamaraoAdapa-MT, I have referred this thread. The ans is for .NET. I tried a similar approach using Java (my runtime stack.) But I get an error. java.security.cert.CertificateParsingException: signed fields invalid at java.base/sun.security.x509.X509CertImpl.parse(X509CertImpl.java:1822) at java.base/sun.security.x509.X509CertImpl.(X509CertImpl.java:184) at java.base/sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:105) at java.base/java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:355) – the_eagle Sep 06 '21 at 13:41
  • byte[] encodedCert = Base64.getDecoder().decode(certB64); ByteArrayInputStream inputStream = new ByteArrayInputStream(encodedCert); X509Certificate cert = null; try { CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); cert = (X509Certificate)certFactory.generateCertificate(inputStream); } catch (CertificateException e) { e.printStackTrace(); } Above is my time code in Java. The value in certB64 is the string returned as config variable from Key vault – the_eagle Sep 06 '21 at 13:43
  • Please try with below code : byte[] encodedCert = Base64.getDecoder().decode(certB64.replaceAll(X509Factory.BEGIN_CERT, "").replaceAll(X509Factory.END_CERT, "")); ByteArrayInputStream inputStream = new ByteArrayInputStream(encodedCert); X509Certificate cert = null; try { CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); cert = (X509Certificate) certFactory.generateCertificate(inputStream); } catch (CertificateException e) { e.printStackTrace(); } Let me know if it works – RamaraoAdapa Sep 07 '21 at 06:08
  • Update: the code I have put decodes the string and generates a x509 cert correctly. The issue is when we have a managed identity activated and a proper access policy to Get Certificates, the base64 string that is returned is actually not valid. Online tools like cert decoder confirmed that. I am not sure what is returned through the configuration variable when we assign a managed identity and access policy as in this link https://stackoverflow.com/questions/55599001/azure-function-key-vault-reference-for-certificates. String certString = System.getenv("getCert"); – the_eagle Sep 08 '21 at 08:50
  • Please refer this to retrieve a certificate from keyvault : https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/keyvault/azure-security-keyvault-certificates#retrieve-a-certificate As per the question, How can I convert that string into a valid certificate in pfx or pem format is resolved. so, please update the question with the issue you are facing – RamaraoAdapa Sep 15 '21 at 06:43

1 Answers1

0

As per our discussion in the comment section, to convert the base 64 string into a valid certificate in pfx or pem format, please use below code :

byte[] encodedCert = Base64.getDecoder().decode(certB64.replaceAll(X509Factory.BEGIN_CERT, "").replaceAll(X509Factory.END_CERT, "")); 
ByteArrayInputStream inputStream = new ByteArrayInputStream(encodedCert); 
X509Certificate cert = null; 
try { 
CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); 
cert = (X509Certificate) certFactory.generateCertificate(inputStream);
} 
catch (CertificateException e) { 
e.printStackTrace(); 
}

You can refer this to retrieve a certificate from keyvault : https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/keyvault/azure-security-keyvault-certificates#retrieve-a-certificate

RamaraoAdapa
  • 2,837
  • 2
  • 5
  • 11
  • This code shows error on X509Factory. However, the code works. But a better way that i have figured is that each certificate has a secret if. Using client libraries we can get the secret id and fetch the certString using getSecret(). – the_eagle Sep 23 '21 at 15:50
  • Currently, one issue I am facing is that while deploying azure function the build fails if some variables are specified in configuration settings in Azure Function App portal. There are service principal credentials which I am taking as env variables. However while deploying locally, it does not picks up those values and hence non-null exception is there – the_eagle Sep 24 '21 at 13:32
  • this is the error message. The build fails java.lang.IllegalArgumentException: Must provide non-null values for clientId, tenantId, clientSecret properties in ClientSecretCredentialBuilder – the_eagle Sep 24 '21 at 13:33