hyperledger / fabric-test

A collection of utilities used to test the core Hyperledger Fabric projects
Apache License 2.0
151 stars 130 forks source link

trying to connect to a kubernetes cluster created with tools/operator using java SDK #304

Open ymolists opened 3 years ago

ymolists commented 3 years ago

I am super new to fabric. Can someone please point me to how i would go about connecting a java app using the fabric java SDK ? I can contribute a sample app as a PR if that would be something people can use.

I am trying to make sense of this fabric-samples java project. I noticed the operator generates connection profiles and ca certs for all orgs. However its not clicking how my client can talk to the cluster stood up by the operator using those generated files.

Can anyone help ?

ymolists commented 3 years ago
//        public static boolean USE_PROFILE = true;
    public static boolean USE_PROFILE = false;

    public static String BUILD_DIR = "build/fabric-000";
    public static String CRYPTO_DIR = BUILD_DIR + "/crypto-config";

    public static String ORG1_PEER = CRYPTO_DIR + "/peerOrganizations/org1";
    public static String ORG1_ORDERER = CRYPTO_DIR + "/ordererOrganizations/ordererorg1";

    public static String ORG1_CA_CERT = ORG1_PEER + "/ca/ca.org1-cert.pem";
//    public static String ORG1_CA_CERT =ORG1_ORDERER+"/ca/ca.ordererorg1-cert.pem";

    public static String ORG1_CONNECTION_PROFILE = "connection-profile/connection_profile_org1.yaml";
//    public static String ORG1_SERVER_CERT = "orderers/orderer0-ordererorg1.ordererorg1/tls/server.crt";

    private static NetworkConfig networkConfig;

    public static void main(String[] args) throws Exception {

        File yamlFile = Paths.get(BUILD_DIR, ORG1_CONNECTION_PROFILE).toFile();
        networkConfig = NetworkConfig.fromYamlFile(yamlFile);

        networkConfig.getOrdererNames().forEach(ordererName -> {
            try {
                System.out.println("orderer: " + ordererName);

                Properties ordererProperties = networkConfig.getOrdererProperties(ordererName);
                Properties testProp = getEndPointProperties("orderer", ordererName);
                ordererProperties.setProperty("clientCertFile", testProp.getProperty("clientCertFile"));
                ordererProperties.setProperty("clientKeyFile", testProp.getProperty("clientKeyFile"));
                networkConfig.setOrdererProperties(ordererName, ordererProperties);
            } catch (InvalidArgumentException e) {
                throw new RuntimeException(e);
            }
        });

        networkConfig.getPeerNames().forEach(peerName -> {
            try {
                System.out.println("peer: " + peerName);

                Properties peerProperties = networkConfig.getPeerProperties(peerName);
                Properties testProp = getEndPointProperties("peer", peerName);
                peerProperties.setProperty("clientCertFile", testProp.getProperty("clientCertFile"));
                peerProperties.setProperty("clientKeyFile", testProp.getProperty("clientKeyFile"));
                networkConfig.setPeerProperties(peerName, peerProperties);

            } catch (InvalidArgumentException e) {
                throw new RuntimeException(e);
            }
        });

        HFCAClient hfcaClient;

        if (USE_PROFILE) {
            //Check if we get access to defined CAs!
            NetworkConfig.OrgInfo org = networkConfig.getOrganizationInfo("org1");
            NetworkConfig.CAInfo caInfo = org.getCertificateAuthorities().get(0);
            Properties caProps = caInfo.getProperties();

            hfcaClient = HFCAClient.createNewInstance(caInfo);
            CryptoSuite cryptoSuite = CryptoSuiteFactory.getDefault().getCryptoSuite();
            hfcaClient.setCryptoSuite(cryptoSuite);
            caProps.put("allowAllHostNames", "true");
            System.out.println("hfcaClient CAName:" + hfcaClient.getCAName());

//            props.put("pemBytes", (byte[]) pemBytes);
//            Object pemBytes = caProps.get("pemBytes");
//            if (!(pemBytes instanceof byte[])) {
//                throw new RuntimeException("Expecting bytes in pemBytes");
//            }
        } else {
            File pemFile = Paths.get(ORG1_CA_CERT).toFile();
            if (!pemFile.exists()) {
                throw new RuntimeException(String.format("Missing pem file Could not find at location: %s", pemFile.getAbsolutePath()));
            }

            Properties props = new Properties();
            props.put("allowAllHostNames", "true");
            props.put("pemFile", pemFile.getAbsolutePath());

            hfcaClient = HFCAClient.createNewInstance("https://localhost:7054", props);
            CryptoSuite cryptoSuite = CryptoSuiteFactory.getDefault().getCryptoSuite();
            hfcaClient.setCryptoSuite(cryptoSuite);
        }

        HFCAInfo info = hfcaClient.info(); //makes actual REST call.
        System.out.println("info CAName:" + info.getCAName());

//        Collection<NetworkConfig.UserInfo> registrars = caInfo.getRegistrars();
//        NetworkConfig.UserInfo registrar = registrars.iterator().next();
//        registrar.setEnrollment(hfcaClient.enroll(registrar.getName(), registrar.getEnrollSecret()));
    }

in both cases (when i enable using the profile or when i use the pem file directly i get this :

orderer: orderer0-ordererorg1
peer: peer0-org1
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:325)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:268)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:263)
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1340)
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(CertificateMessage.java:1215)
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1158)
    at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:445)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:423)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:182)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171)
    at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1475)
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1381)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:441)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:412)
    at org.apache.http.conn.ssl.SSLSocketFactory.createLayeredSocket(SSLSocketFactory.java:570)
    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:554)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
    at org.hyperledger.fabric_ca.sdk.HFCAClient.httpPost(HFCAClient.java:1326)
    at org.hyperledger.fabric_ca.sdk.HFCAClient.info(HFCAClient.java:559)
    at application.java.Network.main(Network.java:104)
lindluni commented 3 years ago

@mbwhite Im not sure what unable to find valid certification path to requested target means in the error stack, is it looking for a truststore rather than a single pem?

Any chance you can provide some insight here, as I don't think it's an actual issue with the network we generate from the operator tool.

I'll end by saying I've never actually used the Java SDK, so my insight here is limited.

mbwhite commented 3 years ago

@bestbeforetoday might be the best placed if I'm honest from a client SDK perspective.

@ymolists to clarify were you deploying Fabric into K8S using your own deployments?

lindluni commented 3 years ago

Thank Matthew. He is using our Fabric-Test tool to deploy the network. I know interacting with the network with the Node SDK works with no caveats, but I've never used the Java SDK for anything.

ymolists commented 3 years ago

@mbwhite as @Iindluni said am using fabric-test/tools/operator to deploy the cluster on k8s.

i observed the following on the ca-org1 pod

ca
2021/03/11 17:31:12 [INFO] The issuer key was successfully stored. The public key is at: /etc/hyperledger/fabric-ca-server/IssuerPublicKey, secret key is at: /etc/hyperledger/fabric-ca-server/msp/keystore/IssuerSecretKey
ca
2021/03/11 17:31:12 [DEBUG] Intializing revocation authority for issuer 'ca0-org1'
ca
2021/03/11 17:31:12 [DEBUG] Initialize Idemix issuer revocation key material
ca
2021/03/11 17:31:12 [INFO] Idemix issuer revocation public and secret keys were generated for CA 'ca0-org1'
ca
2021/03/11 17:31:12 [INFO] The revocation key was successfully stored. The public key is at: /etc/hyperledger/fabric-ca-server/IssuerRevocationPublicKey, private key is at: /etc/hyperledger/fabric-ca-server/msp/keystore/IssuerRevocationPrivateKey
ca
2021/03/11 17:31:12 [DEBUG] Intializing nonce manager for issuer 'ca0-org1'
ca
2021/03/11 17:31:12 [INFO] Home directory for default CA: /etc/hyperledger/fabric-ca-server
ca
2021/03/11 17:31:12 [DEBUG] 1 CA instance(s) running on server
ca
2021/03/11 17:31:12 [INFO] Operation Server Listening on 127.0.0.1:9443
ca
2021/03/11 17:31:12 [DEBUG] TLS is enabled
ca
2021/03/11 17:31:12 [DEBUG] TLS Certificate: /etc/hyperledger/fabric/artifacts/tlsca.org1-cert.pem, TLS Key: /etc/hyperledger/fabric/artifacts/tlsca-priv_sk
ca
2021/03/11 17:31:12 [DEBUG] Could not load TLS certificate with BCCSP: Could not find matching private key for SKI: Failed getting key for SKI [[243 56 28 210 58 129 20 52 139 112 209 223 11 153 56 252 91 213 147 18 125 184 245 193 9 67 8 183 128 57 154 255]]: Key with SKI f3381cd23a8114348b70d1df0b9938fc5bd593127db8f5c1094308b780399aff not found in /etc/hyperledger/fabric-ca-server/msp/keystore
ca
2021/03/11 17:31:12 [DEBUG] Attempting fallback with certfile /etc/hyperledger/fabric/artifacts/tlsca.org1-cert.pem and keyfile /etc/hyperledger/fabric/artifacts/tlsca-priv_sk
ca
2021/03/11 17:31:12 [DEBUG] Client authentication type requested: noclientcert
ca
2021/03/11 17:31:12 [INFO] Listening on https://0.0.0.0:7054

it seems like the container is not able to load the ca cert file and defaulting to use the tls cert instead. ? After i noticed that i changed my above java code to use the tls cert instead of the ca cert i was using and voila !

here is where i used the the tls certs in the new code

I checked the cert saved in the connection profile by the fabric-test tool is using the ca cert not the tls cert ? that section of the code is failing for now.