Writing a Java client for Slice Federation Architecture (SFA)
This guide describes how to build a Java Client for Slice Federation Architecture (SFA). This is not a fully automated client but rather some hints to get you started. More on SFA can be found at http://svn.planet-lab.org/wiki/SFAGuide
To develop and use the client you will need:
- The apache Java XML RPC library http://ws.apache.org/xmlrpc/
- The private key that you use with PlanetLab? or SFA (and you use it to create the public key you have uploaded to PlanetLab?)
- The OpenSSL installed
Self-Signed Certificate and Server Trust
The following steps will show how to sign and create certificates for your client. Although they are on Windows OS they are easily applied to other OS.
Assume that we have a user tranoris@…
Get the private key that you use for PlanetLab? (in our example is tranoris.pkey)
First we Generate a certificate request (the client1plc.req). The following is just an example:
c:\OpenSSL-Win32\bin\openssl req -new -key tranoris.pkey -subj "/C=GR/ST=Achaia/CN=plc.uoppldef.tranoris/EMAILADDRESS=tranoris@myemail.org" -config "c:\OpenSSL-Win32\bin\openssl.cfg" -out client1plc.req
What you need to notice is the CN value, which needs to be like 'plc.<site login_base>.<username>'
Having the certificate request you will create the self-signed certificate client1plc.pem:
c:\OpenSSL-Win32\bin\openssl x509 -trustout -signkey tranoris.pkey -days 1825 -req -in client1plc.req -out client1plc.pem
Now you need to create the pkcs12 for java client:
c:\OpenSSL-Win32\bin\openssl pkcs12 -export -in client1plc.pem -inkey tranoris.pkey -out client1plc.p12 -name "FSToolkit cert"
Now we need our client to trust the PLC server that we will connect so we need to put this info in a keystore. You need to import the PLC server's public key to keystore. For example you can issue the following towards the registry_url ( In the example we have our server on 192.168.56.101. You can replace it with a productions server like "http://sfa.planet-lab.eu:12345")
openssl s_client -connect 192.168.56.101:12345
Save to a file the -----BEGIN?END CERTIFICATE----- parts e.g. to a file plc.crt (You can get this file also through Firefox)
Assuming that you have the java keytool in the path issue:
keytool -import -alias myplccrt -keystore myplc.keystore -file plc.crt
Type some password there at the prompts.
At this moment you will have in your directory (among others) the files: client1plc.p12 and myplc.keystore
Some Java code
The following Java code displays a sample of an SFA client. Notice the GetSelfCredential?(), ListRecords?(), ListResources?() and GetVersion?() methods. Change the System properties with your own values.
Notice especially the GetSelfCredential? method. You need to replace the certificate param with yours! You need to execute
openssl x509 -text -in client1plc.pem
and copy the corresponding certificate section in your code. (You can also save the file with .sscert extension)
/************************************************************************* Copyright 2011 Christos Tranoris, University of Patras Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *************************************************************************/ import java.io.Serializable; import java.net.MalformedURLException; import java.net.URL; import java.security.NoSuchAlgorithmException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.Vector; import javax.net.ssl.SSLContext; import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.client.XmlRpcClient; import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; import org.apache.xmlrpc.client.XmlRpcClientException; import org.apache.xmlrpc.client.XmlRpcSunHttpTransport; import org.apache.xmlrpc.client.XmlRpcSunHttpTransportFactory; public class SFAJavaClient { final static XmlRpcClient client = new XmlRpcClient(); final static XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); private static String SFAcredential; public static void main(String[] args) { System.setProperty("javax.net.ssl.keyStoreType", "pkcs12"); System.setProperty("javax.net.ssl.keyStore", "C:\\Users\\ctranoris\\Desktop\\_downloads\\tmp\\plckeys\\client1plc.p12"); System.setProperty("javax.net.ssl.keyStorePassword", "123456"); System.setProperty("javax.net.ssl.trustStoreType", "jks"); System.setProperty("javax.net.ssl.trustStore", "C:\\Users\\ctranoris\\Desktop\\_downloads\\tmp\\myplc.keystore"); // System.setProperty("javax.net.debug", "all"); //enable this for ssl // debugging System.setProperty("javax.net.ssl.trustStorePassword", "123456"); SSLContext sc = null; try { sc = SSLContext.getDefault(); // SSLContext.getInstance("TLS"); } catch (NoSuchAlgorithmException e1) { e1.printStackTrace(); } sc.getClientSessionContext().setSessionTimeout(0); // ////////// // Create empty HostnameVerifier This is to trust in SSL even if the CN // value is different from the requested url HostnameVerifier hv = new HostnameVerifier() { @Override public boolean verify(String arg0, SSLSession arg1) { return true; } }; HttpsURLConnection.setDefaultHostnameVerifier(hv); SFAcredential = GetSelfCredential(); // List displays all the Records in the Registry for a given authority // or subauthority. ListRecords(); ListResources(); GetVersion(); } private static void GetVersion() { System.out.println("GetVersion()"); Object result; Vector<Serializable> params = new Vector<Serializable>(); result = execXMLRPC_registry("GetVersion", params); } private static void ListResources() { System.out.println("ListResources()"); Object result; Vector<Serializable> params = new Vector<Serializable>(); // params.addElement( new String("plc.uopplcbase")); String cred = SFAcredential; params.addElement(cred); HashMap<String, String> auth = new HashMap<String, String>(); auth.put("type", "ProtoGENI"); auth.put("version", "2"); HashMap<String, HashMap<String, String>> geni_rspec_version = new HashMap<String, HashMap<String, String>>(); geni_rspec_version.put("geni_rspec_version", auth); params.addElement(geni_rspec_version); result = execXMLRPC_aggregate("ListResources", params); } private static String GetSelfCredential() { System.out.println("GetSelfCredential()"); Object result; Vector<Serializable> params = new Vector<Serializable>(); // NOTICE: // this Param comes out from command openssl x509 -text -in // client1plc.pem params.addElement(new String( "-----BEGIN CERTIFICATE-----\n" + "MIIC+DCCAeACCQC8vGomhquv7TANBgkqhkiG9w0BAQUFADA+MQswCQYDVQQGEwJH\n" + "UjEPMA0GA1UECAwGQWNoYWlhMR4wHAYDVQQDDBVwbGMudW9wcGxkZWYudHJhbm9y\n" + "aXMwHhcNMTExMTI5MTE0NDAyWhcNMTYxMTI3MTE0NDAyWjA+MQswCQYDVQQGEwJH\n" + "UjEPMA0GA1UECAwGQWNoYWlhMR4wHAYDVQQDDBVwbGMudW9wcGxkZWYudHJhbm9y\n" + "aXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxK/FuaB+XjuzbGE/A\n" + "s5s0yEn+pkr2UFsDWS/5HXIZ0qgNHBFMgYxU4V75qFojZSXdP5Kk07JEoa2Kwy6k\n" + "7XZGIW6sub6D+T3v2FOny98ygN6nUfEWRI8QV4OMrpBNtM1tgUomajYMhp0lHvQ2\n" + "pOBv1u3rsHgPygLcGtyYeNsNAkRpfz65XqaimUj/boqu7HXBl6yL1IIP9swdFivG\n" + "hoZWYGlpPpjvMmgaOTkFRlXCUFLE/WI9FMDXZramJB37EMY4kG6qYudKEasQfa8S\n" + "qi1nhlEp4L9cCpmI4b0C6oxf9pWcVNNZDzDFB6/AM7ahwKqzPmH4MvxB0EEJrJpv\n" + "XYV/AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAEY7QWQJvPPVpaJ5gequ/3Z8PkQM\n" + "qSgw9wC/os95CyjlHxlQm7JlREb04/B73AjTNQV6VJQIoan0oC3EHD73vvUDaJyz\n" + "V+g7pmFUK/+f2tvXwXKxef9ROPh71Ai6QkQpw1RRp+qtHKcs8IKplkfsvKqYThg7\n" + "FeiXIp1SIIclX6Z6IfKCWru/BYuSRVw+HrbbpTz4wgDufIYZivaVuODBQwwXUN9U\n" + "WC1yxbK0YugFupY9v+MPplrMBU3kpCNeTdoV7xYF28abaWlSHC+16704o4I10xae\n" + "AqPE2T+hDmlBrDbBLRFyc4XGumZuvCqs28uJiOylC+M2cELDE+D0wq1HNl0=\n" + "-----END CERTIFICATE-----")); params.addElement(new String("plc.uoppldef.tranoris")); params.addElement(new String("user")); result = execXMLRPC_registry("GetSelfCredential", params); return result.toString(); } private static void ListRecords() { System.out.println("ListRecords()"); Object result; Vector<Serializable> params = new Vector<Serializable>(); params.addElement(new String("plc.uopplcbase")); String cred = SFAcredential; params.addElement(cred); result = execXMLRPC_registry("List", params); } private static Object execXMLRPC_registry(String commandName, Vector<Serializable> params) { return execXMLRPC(commandName, params, "https://plc:12345"); } private static Object execXMLRPC_aggregate(String commandName, Vector<Serializable> params) { return execXMLRPC(commandName, params, "https://plc:12347"); } private static Object execXMLRPC(String commandName, Vector<Serializable> params, String url) { try { invalidateSessions(); config.setServerURL(new URL(url)); config.setReplyTimeout(10000); config.setContentLengthOptional(true); client.setConfig(config); client.setTypeFactory(new MyTypeFactory(client)); Object result; System.out.println("Tstep 3"); try { result = client.execute(commandName, params); if (result instanceof String) { System.out.println("The toString of result is: " + result.toString()); } else if (result instanceof Map) { Map map = (Map) result; Set<String> ks = map.keySet(); for (String k : ks) { if (map.get(k) instanceof Object[]) { System.out.println("-> The " + k + " are: "); printObjectArray((Object[]) map.get(k)); } else { System.out.println("-> The " + k + " is: " + map.get(k)); } } } else { printObjectArray((Object[]) result); } return result; } catch (XmlRpcClientException e) { // TODO Auto-generated catch block e.toString(); e.printStackTrace(); } catch (XmlRpcException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } private static void invalidateSessions() { SSLContext sc = null; try { sc = SSLContext.getDefault(); } catch (NoSuchAlgorithmException e1) { e1.printStackTrace(); } sc.getClientSessionContext().setSessionTimeout(0); sc.getClientSessionContext().setSessionCacheSize(0); Enumeration<byte[]> a = sc.getClientSessionContext().getIds(); if (a.hasMoreElements()) sc.getClientSessionContext().getSession(a.nextElement()) .invalidate(); } private static void printObjectArray(Object[] objects) { // Object[] objects = (Object[]) result; if (objects != null && objects.length > 0) { for (Object object : objects) { if (object instanceof Map) { Map map = (Map) object; Set<String> ks = map.keySet(); for (String k : ks) { if (map.get(k) instanceof Object[]) { System.out.println("-> The " + k + " are: "); printObjectArray((Object[]) map.get(k)); } else { System.out.println("-> The " + k + " is: " + map.get(k)); } } System.out.println("The toString is: " + map.toString()); } else { System.out.println(" " + object.toString()); } } } } }
you will also need this class:
import org.apache.ws.commons.util.NamespaceContextImpl; import org.apache.xmlrpc.common.TypeFactoryImpl; import org.apache.xmlrpc.common.XmlRpcController; import org.apache.xmlrpc.common.XmlRpcStreamConfig; import org.apache.xmlrpc.parser.NullParser; import org.apache.xmlrpc.parser.TypeParser; import org.apache.xmlrpc.serializer.NullSerializer; public class MyTypeFactory extends TypeFactoryImpl { public MyTypeFactory(XmlRpcController pController) { super(pController); } @Override public TypeParser getParser(XmlRpcStreamConfig pConfig, NamespaceContextImpl pContext, String pURI, String pLocalName) { if ("".equals(pURI) && NullSerializer.NIL_TAG.equals(pLocalName)) { return new NullParser(); } else { return super.getParser(pConfig, pContext, pURI, pLocalName); } } }
This is a screenshot from the Java program running in Eclipse listing resources:
Contact
for any questions send an e-mail to tranoris [at] ece.upatras.gr
Attachments (1)
- SFAClientJavaExample.jpg (165.2 KB) - added by ctranoris 12 years ago.
Download all attachments as: .zip