微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

与使用 Java 从 Azure Keyvault 获取证书相关的问题

如何解决与使用 Java 从 Azure Keyvault 获取证书相关的问题

我正在将我们的旧应用程序迁移到 Azure Cloud。在现有应用程序中,我们在启动时保护我们的 Jetty 服务器,因此我们使用 jks 文件来保护我们的 Jetty 服务器。

现在我们要迁移到 Azure Cloud,所以我们必须从 Azure keyvault 获取 .jks 文件。那么如何从 Azure keyvault 获取完整的 .jks 文件。我能够从 keyvault 获取机密,但无法获取证书(我在 Azure keyvault 中上传了该证书)。我不确定我们是否有任何提供证书文件的 API。

下面是我用来获取机密和证书的代码

import com.microsoft.aad.adal4j.AuthenticationContext;
import com.microsoft.aad.adal4j.AuthenticationResult;
import com.microsoft.aad.adal4j.ClientCredential;
import com.microsoft.azure.keyvault.keyvaultClient;
import com.microsoft.azure.keyvault.authentication.keyvaultCredentials;
import com.microsoft.azure.keyvault.models.CertificateBundle;
import com.microsoft.azure.keyvault.models.SecretBundle;

public class DemoTest {
    
    private static String vaultBase = "https://abc.vault.azure.net/";
    private static String ClientId = "*******************";
    private static String clientKey = "*****************";
    
    
    public static void main(String[] args) {
        
        keyvaultClient keyvaultClient = GetkeyvaultClient();
        SecretBundle getSecret=keyvaultClient.getSecret(vaultBase,"mysecretkey");
        SecretBundle getSecret1=keyvaultClient.getSecret(vaultBase,"DB-PASSWORD-POC");
        SecretBundle getSecret2=keyvaultClient.getSecret(vaultBase,"certificate-value");
//      SecretBundle getSecret2=keyvaultClient.getSecret(vaultBase,"DB-PASSWORD-DEV");
        CertificateBundle getCertificate=keyvaultClient.getCertificate(vaultBase,"abcprod");
        CertificateBundle bundle = keyvaultClient.getCertificate("https://abc.vault.azure.net/certificates/abcprod/********386c9403bab8337ce21d27495");
        System.out.println(getSecret.value());
        System.out.println(getSecret1.value());
        System.out.println(getSecret2.value());
//      System.out.println(getCertificate.contentType());
//      System.out.println(getCertificate.id());
//      System.out.println(getCertificate.kid());
//      System.out.println(getCertificate.toString());
//      System.out.println(getCertificate.attributes().toString());
//      System.out.println(getCertificate.keyIdentifier().name());
//      System.out.println(getCertificate.sid());
//      System.out.println(getCertificate.certificateIdentifier().baseIdentifier());
//      System.out.println(bundle.cer());
//      System.out.println(bundle);
        
    }


    private static keyvaultClient GetkeyvaultClient() {
        return 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();

                }
                return token;
            }
        });
    }
    
     public static AuthenticationResult getAccesstoken(String authorization,String resource) throws InterruptedException,ExecutionException,MalformedURLException {

            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 (ClientId != null && clientKey != null) {
                    ClientCredential credentials = new ClientCredential(ClientId,clientKey);
                    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 class ABCSubscriber {
        private static final int Port = 9090;
        private static final String KeyStoreType = "jks";
        private static final String KeyStoreFile = "/home/abc/xyz/subscriber.jks";
        private static final String KeyStorePassword = "******";
        private static final String KeyPassword = "*******";
        private static final String contextpath = "/";
        private static final String URLPattern = "/*";

        public static void main(String[] args) throws Exception {
              
        Server server = new Server();
        HttpConfiguration http_config = new HttpConfiguration();
        http_config.setSecureScheme("https");
        http_config.setSecurePort(Port);
        http_config.setRequestHeaderSize(8192);

        // HTTP connector
        ServerConnector http = new ServerConnector(server,new httpconnectionFactory(http_config));
        http.setPort(9091);
        http.setIdleTimeout(30000);

        // SSL Context Factory
        SslContextFactory sslContextFactory = new SslContextFactory();
        sslContextFactory.setKeyStoreType(KeyStoreType);
        sslContextFactory.setKeyStorePath(KeyStoreFile);
        sslContextFactory.setKeyStorePassword(KeyStorePassword);
        sslContextFactory.setKeyManagerPassword(KeyPassword);

        // sslContextFactory.setTrustStorePath(ncm.getKSFile());
        // sslContextFactory.setTrustStorePassword("changeit");
        sslContextFactory.setExcludeCipherSuites("SSL_RSA_WITH_DES_CBC_SHA","SSL_DHE_RSA_WITH_DES_CBC_SHA","SSL_DHE_DSS_WITH_DES_CBC_SHA","SSL_RSA_EXPORT_WITH_RC4_40_MD5","SSL_RSA_EXPORT_WITH_DES40_CBC_SHA","SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA","SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");

        // SSL HTTP Configuration
        HttpConfiguration https_config = new HttpConfiguration(http_config);
        https_config.addCustomizer(new SecureRequestCustomizer());

        // SSL Connector
        ServerConnector sslConnector = new ServerConnector(server,new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asstring()),new httpconnectionFactory(https_config));
        sslConnector.setPort(Port);
        server.addConnector(sslConnector);

        /**disable and enable protocols*/
                String[] includeProtocols = {"TLSv1.1","TLSv1.2"};
        sslContextFactory.addExcludeProtocols("TLSv1.0");
        sslContextFactory.setIncludeProtocols(includeProtocols);
     
        /**End disable and enable protocols*/

        // HTTPS Configuration
        ServerConnector https = new ServerConnector(server,new httpconnectionFactory(https_config));
        https.setPort(Port);
        https.setIdleTimeout(30000);
        //server.setConnectors(new Connector[] { http,https });
        server.setConnectors(new Connector[] {  https });
                ServletContextHandler ctxt = new ServletContextHandler(0);
                ctxt.setcontextpath(contextpath);
                server.setHandler(ctxt);

                ctxt.addServlet(new ServletHolder(new ABCServlet()),"/*");

                try {
                    server.start();
                } catch ( Exception e ) {
                        e.getLocalizedMessage();
                };
        server.join();

        }
}

那么,有什么办法可以从 Azure 密钥库中获取证书文件吗?如果不是那么我们如何使用证书来保护服务器?

有人可以帮我吗?

提前致谢!!!

解决方法

您需要下载证书的私钥作为秘密。使用更明显的 GetCertificate 获取密钥只会返回证书的公钥部分。

我知道在下面的代码示例中这是 C#,但这就是我从 Key Vault 中获取证书的方式,我希望您能了解如何在 Java 中执行相同操作:

        /// <summary>
        /// Helper method to get a certificate
        /// 
        /// Source https://github.com/heaths/azsdk-sample-getcert/blob/master/Program.cs
        /// </summary>
        /// <param name="certificateClient"></param>
        /// <param name="secretClient"></param>
        /// <param name="certificateName"></param>
        /// <returns></returns>
        private static X509Certificate2 GetCertificateAsync(CertificateClient certificateClient,SecretClient secretClient,string certificateName)
        {

            KeyVaultCertificateWithPolicy certificate = certificateClient.GetCertificate(certificateName);

            // Return a certificate with only the public key if the private key is not exportable.
            if (certificate.Policy?.Exportable != true)
            {
                return new X509Certificate2(certificate.Cer);
            }

            // Parse the secret ID and version to retrieve the private key.
            string[] segments = certificate.SecretId.AbsolutePath.Split('/',StringSplitOptions.RemoveEmptyEntries);
            if (segments.Length != 3)
            {
                throw new InvalidOperationException($"Number of segments is incorrect: {segments.Length},URI: {certificate.SecretId}");
            }

            string secretName = segments[1];
            string secretVersion = segments[2];

            KeyVaultSecret secret = secretClient.GetSecret(secretName,secretVersion);

            // For PEM,you'll need to extract the base64-encoded message body.
            // .NET 5.0 preview introduces the System.Security.Cryptography.PemEncoding class to make this easier.
            if ("application/x-pkcs12".Equals(secret.Properties.ContentType,StringComparison.InvariantCultureIgnoreCase))
            {
                byte[] pfx = Convert.FromBase64String(secret.Value);
                return new X509Certificate2(pfx);
            }

            throw new NotSupportedException($"Only PKCS#12 is supported. Found Content-Type: {secret.Properties.ContentType}");
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。