Eucalyptus.java 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package hudson.plugins.ec2;
  2. import hudson.Extension;
  3. import hudson.util.FormValidation;
  4. import hudson.util.IOException2;
  5. import java.io.IOException;
  6. import java.net.MalformedURLException;
  7. import java.net.URL;
  8. import java.security.GeneralSecurityException;
  9. import java.security.KeyManagementException;
  10. import java.security.NoSuchAlgorithmException;
  11. import java.security.cert.X509Certificate;
  12. import java.util.List;
  13. import javax.net.ssl.HostnameVerifier;
  14. import javax.net.ssl.HttpsURLConnection;
  15. import javax.net.ssl.SSLContext;
  16. import javax.net.ssl.SSLSession;
  17. import javax.net.ssl.TrustManager;
  18. import javax.net.ssl.X509TrustManager;
  19. import javax.servlet.ServletException;
  20. import org.dom4j.Document;
  21. import org.dom4j.DocumentException;
  22. import org.dom4j.Element;
  23. import org.dom4j.io.SAXReader;
  24. import org.kohsuke.stapler.DataBoundConstructor;
  25. import org.kohsuke.stapler.QueryParameter;
  26. import org.kohsuke.stapler.StaplerResponse;
  27. /**
  28. * Eucalyptus.
  29. *
  30. * @author Kohsuke Kawaguchi
  31. */
  32. public class Eucalyptus extends EC2Cloud {
  33. private transient Metadata metadata;
  34. public final URL url;
  35. @DataBoundConstructor
  36. public Eucalyptus(URL url, String accessId, String secretKey, String privateKey, String instanceCapStr, List<SlaveTemplate> templates) throws IOException {
  37. super("eucalyptus", accessId, secretKey, privateKey, instanceCapStr, templates);
  38. this.url = url;
  39. }
  40. private Metadata getMetadata() throws IOException {
  41. if (metadata==null)
  42. metadata = new Metadata(url);
  43. return metadata;
  44. }
  45. @Override
  46. public URL getEc2EndpointUrl() throws IOException {
  47. return getMetadata().ec2endpoint;
  48. }
  49. @Override
  50. public URL getS3EndpointUrl() throws IOException {
  51. return getMetadata().s3endpoint;
  52. }
  53. @Extension
  54. public static class DescriptorImpl extends EC2Cloud.DescriptorImpl {
  55. @Override
  56. public String getDisplayName() {
  57. return "Eucalyptus";
  58. }
  59. @Override
  60. public FormValidation doTestConnection(
  61. @QueryParameter URL url,
  62. @QueryParameter String accessId,
  63. @QueryParameter String secretKey,
  64. @QueryParameter String privateKey) throws IOException, ServletException {
  65. return super.doTestConnection(new Metadata(url).ec2endpoint,accessId,secretKey,privateKey);
  66. }
  67. @Override
  68. public FormValidation doGenerateKey(
  69. StaplerResponse rsp, @QueryParameter URL url, @QueryParameter String accessId, @QueryParameter String secretKey) throws IOException, ServletException {
  70. return super.doGenerateKey(rsp, new Metadata(url).ec2endpoint, accessId,secretKey);
  71. }
  72. }
  73. /**
  74. * Eucalyptus service endpoint metadata.
  75. */
  76. static class Metadata {
  77. final URL ec2endpoint,s3endpoint;
  78. Metadata(URL eucalyptus) throws IOException {
  79. if (!eucalyptus.getProtocol().equals("https"))
  80. throw new IOException("Expecting an HTTPS URL but got "+eucalyptus);
  81. URL metadataUrl = new URL(eucalyptus, "/register");
  82. try {
  83. HttpsURLConnection con = (HttpsURLConnection)metadataUrl.openConnection();
  84. makeIgnoreCertificate(con);
  85. Document metadata = new SAXReader().read(con.getInputStream());
  86. /*
  87. Metadata, as of Eucalyptus 1.5.2, looks like this:
  88. <Signature>
  89. <SignedInfo>
  90. <SignatureMethod>http://www.w3.org/2001/04/xmldsig-more#hmac-sha256</SignatureMethod>
  91. </SignedInfo>
  92. <SignatureValue>62595777525d7dbba4b5f361b3e9041d3d37e92611684557e67e85a9222a3ffb </SignatureValue>
  93. <Object>
  94. <CloudSchema>
  95. <Services type="array">
  96. <Service>
  97. <Name>ec2</Name>
  98. <EndpointUrl>http://eucalyptus.hudson-slaves.sfbay.sun.com:8773/services/Eucalyptus</EndpointUrl>
  99. <Resources type="array">
  100. ...
  101. </Resources>
  102. </Service>
  103. <Service>
  104. <Name>s3</Name>
  105. <EndpointUrl>http://eucalyptus.hudson-slaves.sfbay.sun.com:8773/services/Walrus</EndpointUrl>
  106. <Resources type="array">
  107. ...
  108. </Resources>
  109. </Service>
  110. </Services>
  111. <id>a002c56e-b994-4ed8-956b-b30eda9b6153</id> <CloudType>eucalyptus</CloudType>
  112. <CloudVersion>1.5.2</CloudVersion>
  113. <SchemaVersion>1.0</SchemaVersion>
  114. <Description>Public cloud in the new cluster</Description>
  115. </CloudSchema>
  116. */
  117. this.ec2endpoint = readURLFromMetadata(metadata, "ec2");
  118. this.s3endpoint = readURLFromMetadata(metadata, "s3");
  119. } catch (DocumentException e) {
  120. throw new IOException2("Failed to parse Eucalyptus metadata at "+metadataUrl,e);
  121. } catch (IOException e) {
  122. throw new IOException2("Failed to parse Eucalyptus metadata at "+metadataUrl,e);
  123. } catch (GeneralSecurityException e) {
  124. throw new IOException2("Failed to parse Eucalyptus metadata at "+metadataUrl,e);
  125. }
  126. }
  127. /**
  128. * Configures the given {@link HttpsURLConnection} so that it'll ignore all the HTTPS certificate checks,
  129. * as typical Eucalyptus implementation doesn't come with a valid certificate.
  130. */
  131. private void makeIgnoreCertificate(HttpsURLConnection con) throws NoSuchAlgorithmException, KeyManagementException {
  132. SSLContext sc = SSLContext.getInstance("SSL");
  133. TrustManager[] tma = {new X509TrustManager() {
  134. public X509Certificate[] getAcceptedIssuers() {
  135. return null;
  136. }
  137. public void checkClientTrusted(X509Certificate[] certs, String authType) {
  138. }
  139. public void checkServerTrusted(X509Certificate[] certs, String authType) {
  140. }
  141. }};
  142. sc.init(null, tma, null);
  143. con.setSSLSocketFactory(sc.getSocketFactory());
  144. con.setHostnameVerifier(new HostnameVerifier() {
  145. public boolean verify(String s, SSLSession sslSession) {
  146. return true; // everything goes
  147. }
  148. });
  149. }
  150. private URL readURLFromMetadata(Document metadata, String serviceName) throws MalformedURLException {
  151. Element e = (Element)metadata.selectSingleNode("//Service[Name/text()='" + serviceName + "']/EndpointUrl");
  152. if (e==null)
  153. throw new IllegalStateException("Service metadata didn't contain "+serviceName);
  154. return new URL(e.getTextTrim());
  155. }
  156. }
  157. }