com.cloudbees.tftwoway.Client.java Source code

Java tutorial

Introduction

Here is the source code for com.cloudbees.tftwoway.Client.java

Source

/*
 * The MIT License
 *
 * Copyright (c) 2017, CloudBees, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.cloudbees.tftwoway;

import org.apache.commons.io.IOUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.io.pem.PemReader;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;

/**
 * @author <a href="mailto:tom.fennelly@gmail.com">tom.fennelly@gmail.com</a>
 */
public class Client {

    //
    // How to use:
    //  1. Run the nginx script (in the root) or the jetty-server project.
    //  2. Run this classes main method, with the CWD being the root of the project.
    //

    private static final String PRIVATE_KEY = "./certs/client.key";
    private static final String CERTIFICATE = "./certs/client.crt";
    private static final String CACERT = "./certs/ca.crt";

    // You'll need to map 127.0.0.1 to example.com in /etc/hosts (or equivalent).
    private static final String SERVER_ADDRESS = "https://example.com:8443";

    static {
        // BouncyCastle is needed in order to read the private RSA keys.
        // JDK not able to read unless they are PKCS#8 encoded.
        Security.addProvider(new BouncyCastleProvider());
    }

    public static void main(String[] args) throws Exception {
        URL url = new URL(SERVER_ADDRESS);
        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();

        SSLContext sslContext = createSSLContext();
        connection.setSSLSocketFactory(sslContext.getSocketFactory());

        connection.connect();

        int responseCode = connection.getResponseCode();
        String response = IOUtils.toString(connection.getInputStream(), connection.getContentEncoding());
        System.out.println(responseCode);
        System.out.println(response);
    }

    private static SSLContext createSSLContext() throws Exception {
        KeyManager[] serverKeyManagers = getKeyManager();
        TrustManager[] serverTrustManagers = getTrustManager();

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(serverKeyManagers, serverTrustManagers, new SecureRandom());

        return sslContext;
    }

    public static KeyManager[] getKeyManager() throws Exception {
        KeyManagerFactory keyManagerFactory = KeyManagerFactory
                .getInstance(KeyManagerFactory.getDefaultAlgorithm());
        KeyStore store = KeyStore.getInstance("JKS");

        PrivateKey clientKey = loadRSAKey(PRIVATE_KEY);
        X509Certificate clientCert = loadX509Key(CERTIFICATE);

        store.load(null);
        store.setKeyEntry("key", clientKey, "123123".toCharArray(), new Certificate[] { clientCert });

        keyManagerFactory.init(store, "123123".toCharArray());

        return keyManagerFactory.getKeyManagers();
    }

    public static TrustManager[] getTrustManager() throws Exception {
        TrustManagerFactory trustManagerFactory = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
        KeyStore store = KeyStore.getInstance("JKS");

        store.load(null);
        X509Certificate cacerts = loadX509Key(CACERT);
        store.setCertificateEntry("cert", cacerts);

        trustManagerFactory.init(store);

        return trustManagerFactory.getTrustManagers();
    }

    private static PrivateKey loadRSAKey(String path) throws Exception {
        try (InputStream fis = new FileInputStream(path)) {
            try (PemReader pemReader = new PemReader(new InputStreamReader(fis))) {
                byte[] pemBytes = pemReader.readPemObject().getContent();

                KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
                KeySpec spec = new PKCS8EncodedKeySpec(pemBytes);

                return keyFactory.generatePrivate(spec);
            }
        }
    }

    private static X509Certificate loadX509Key(String path) throws Exception {
        try (FileInputStream fis = new FileInputStream(path)) {
            return (X509Certificate) CertificateFactory.getInstance("X.509")
                    .generateCertificate(new BufferedInputStream(fis));
        }
    }
}