2 * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may
5 * not use this file except in compliance with the License. You may obtain
6 * a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 * implied. See the License for the specific language governing
14 * permissions and limitations under the License.
16 package org.akraino.validation.ui.client.jenkins;
18 import java.io.IOException;
19 import java.net.HttpURLConnection;
20 import java.net.InetSocketAddress;
21 import java.net.MalformedURLException;
22 import java.net.Proxy;
24 import java.security.KeyManagementException;
25 import java.security.NoSuchAlgorithmException;
26 import java.security.cert.X509Certificate;
27 import java.util.ArrayList;
28 import java.util.Iterator;
29 import java.util.List;
32 import javax.annotation.Nonnull;
33 import javax.net.ssl.HostnameVerifier;
34 import javax.net.ssl.HttpsURLConnection;
35 import javax.net.ssl.SSLContext;
36 import javax.net.ssl.SSLSession;
37 import javax.net.ssl.TrustManager;
38 import javax.net.ssl.X509TrustManager;
39 import javax.ws.rs.core.MultivaluedMap;
41 import org.akraino.validation.ui.client.jenkins.resources.CrumbResponse;
42 import org.akraino.validation.ui.client.jenkins.resources.Parameter;
43 import org.akraino.validation.ui.client.jenkins.resources.Parameters;
44 import org.akraino.validation.ui.client.jenkins.resources.QueueJobItem;
45 import org.apache.commons.httpclient.HttpException;
46 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
48 import com.sun.jersey.api.client.Client;
49 import com.sun.jersey.api.client.ClientHandlerException;
50 import com.sun.jersey.api.client.ClientResponse;
51 import com.sun.jersey.api.client.UniformInterfaceException;
52 import com.sun.jersey.api.client.WebResource;
53 import com.sun.jersey.api.client.config.ClientConfig;
54 import com.sun.jersey.api.client.config.DefaultClientConfig;
55 import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
56 import com.sun.jersey.api.json.JSONConfiguration;
57 import com.sun.jersey.client.urlconnection.HTTPSProperties;
58 import com.sun.jersey.client.urlconnection.HttpURLConnectionFactory;
59 import com.sun.jersey.client.urlconnection.URLConnectionClientHandler;
61 public final class JenkinsExecutorClient {
63 private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(JenkinsExecutorClient.class);
65 private static final List<JenkinsExecutorClient> JENKINS_CLIENTS = new ArrayList<>();
66 private static final Object LOCK = new Object();
67 private final Client client;
69 private final String user;
70 private final String password;
71 private final String baseurl;
73 private final HostnameVerifier hostnameVerifier;
74 private final TrustManager[] trustAll;
76 private JenkinsExecutorClient(String newUser, String newPassword, String newBaseurl) {
78 this.password = newPassword;
79 this.baseurl = newBaseurl;
80 ClientConfig clientConfig = new DefaultClientConfig();
81 clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
82 this.client = new Client(new URLConnectionClientHandler(new HttpURLConnectionFactory() {
86 public HttpURLConnection getHttpURLConnection(URL url) throws IOException {
88 String proxyIp = System.getenv("JENKINS_PROXY").substring(0,
89 System.getenv("JENKINS_PROXY").lastIndexOf(":"));
90 String proxyPort = System.getenv("JENKINS_PROXY")
91 .substring(System.getenv("JENKINS_PROXY").lastIndexOf(":") + 1);
92 proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyIp, Integer.parseInt(proxyPort)));
93 return (HttpURLConnection) url.openConnection(proxy);
94 } catch (Exception ex) {
95 return (HttpURLConnection) url.openConnection();
99 this.client.addFilter(new HTTPBasicAuthFilter(user, password));
100 // Create all-trusting host name verifier
101 hostnameVerifier = new HostnameVerifier() {
103 public boolean verify(String hostname, SSLSession session) {
107 // Create a trust manager that does not validate certificate chains
108 trustAll = new TrustManager[] {new X509TrustManager() {
110 public X509Certificate[] getAcceptedIssuers() {
111 return null; // Not relevant.
115 public void checkClientTrusted(X509Certificate[] certs, String authType) {
116 // Do nothing. Just allow them all.
120 public void checkServerTrusted(X509Certificate[] certs, String authType) {
121 // Do nothing. Just allow them all.
126 public static synchronized JenkinsExecutorClient getInstance(@Nonnull String newUser, @Nonnull String newPassword,
127 @Nonnull String newBaseurl) throws MalformedURLException {
129 for (JenkinsExecutorClient client : JENKINS_CLIENTS) {
130 if (client.getBaseUrl().equals(newBaseurl) && client.getUser().equals(newUser)
131 && client.getPassword().equals(newPassword)) {
135 JenkinsExecutorClient client = new JenkinsExecutorClient(newUser, newPassword, newBaseurl);
136 JENKINS_CLIENTS.add(client);
140 public String getUser() {
144 public String getPassword() {
145 return this.password;
148 public String getBaseUrl() {
152 public QueueJobItem getQueueJobItem(URL queueJobItemUrl) throws HttpException, ClientHandlerException,
153 UniformInterfaceException, KeyManagementException, NoSuchAlgorithmException {
154 synchronized (LOCK) {
155 LOGGER.info(EELFLoggerDelegate.applicationLogger, "Trying to get a Jenkins resource");
156 String crumb = this.getCrumb();
157 LOGGER.debug(EELFLoggerDelegate.debugLogger, "Jenkins crumb is: " + crumb);
158 WebResource webResource = this.client.resource(queueJobItemUrl + "/api/json");
159 LOGGER.debug(EELFLoggerDelegate.debugLogger, "Request URI of get: " + webResource.getURI().toString());
160 WebResource.Builder builder = webResource.getRequestBuilder();
161 builder.header("Jenkins-Crumb", crumb);
162 ClientResponse response =
163 builder.accept("application/json").type("application/json").get(ClientResponse.class);
164 if (response.getStatus() != 200) {
165 throw new HttpException("Get on Jenkins failed. HTTP error code : " + response.getStatus()
166 + " and message: " + response.getEntity(String.class));
168 LOGGER.info(EELFLoggerDelegate.applicationLogger, "Get of Jenkins resource succeeded");
169 return response.getEntity(QueueJobItem.class);
177 * @return The URL of the corresponding Jenkins queue job item
178 * @throws UniformInterfaceException
179 * @throws ClientHandlerException
180 * @throws HttpException
181 * @throws MalformedURLException
182 * @throws NoSuchAlgorithmException
183 * @throws KeyManagementException
185 public URL postJobWithQueryParams(@Nonnull String jobName, @Nonnull Parameters parameters)
186 throws HttpException, ClientHandlerException, UniformInterfaceException, MalformedURLException,
187 KeyManagementException, NoSuchAlgorithmException {
188 synchronized (LOCK) {
189 LOGGER.info(EELFLoggerDelegate.applicationLogger, "Trying to trigger a job in Jenkins");
190 String crumb = this.getCrumb();
191 LOGGER.debug(EELFLoggerDelegate.debugLogger, "Jenkins crumb is: " + crumb);
192 String queryParams = "?";
193 for (Parameter parameter : parameters.getParameter()) {
194 queryParams = queryParams + parameter.getName() + "=" + parameter.getValue() + "&";
196 queryParams = queryParams.substring(0, queryParams.length() - 1);
197 WebResource webResource =
198 this.client.resource(this.getBaseUrl() + "/job/" + jobName + "/buildWithParameters" + queryParams);
199 LOGGER.debug(EELFLoggerDelegate.debugLogger, "Request URI of post: " + webResource.getURI().toString());
200 WebResource.Builder builder = webResource.getRequestBuilder();
201 builder.header("Jenkins-Crumb", crumb);
202 ClientResponse response = builder.type("application/json").post(ClientResponse.class, String.class);
203 if (response.getStatus() != 200 && response.getStatus() != 201) {
204 throw new HttpException("Post of Jenkins job failed. HTTP error code : " + response.getStatus()
205 + " and message: " + response.getEntity(String.class));
207 LOGGER.info(EELFLoggerDelegate.applicationLogger, "Jenkins job has been successfully triggered");
208 URL buildQueueUrl = null;
209 MultivaluedMap<String, String> responseValues = response.getHeaders();
210 Iterator<String> iter = responseValues.keySet().iterator();
211 while (iter.hasNext()) {
212 String key = iter.next();
213 if (key.equals("Location")) {
214 buildQueueUrl = new URL(responseValues.getFirst(key));
217 return buildQueueUrl;
221 private String getCrumb() throws HttpException, ClientHandlerException, UniformInterfaceException,
222 KeyManagementException, NoSuchAlgorithmException {
223 LOGGER.info(EELFLoggerDelegate.applicationLogger, "Attempting to get the crumb");
225 String crumbUri = baseurl + "/crumbIssuer/api/json";
226 WebResource webResource = this.client.resource(crumbUri);
227 ClientResponse response =
228 webResource.accept("application/json").type("application/json").get(ClientResponse.class);
229 if (response.getStatus() == 201 || response.getStatus() == 200) {
230 CrumbResponse crumbResponse = response.getEntity(CrumbResponse.class);
231 LOGGER.info(EELFLoggerDelegate.applicationLogger, "Successful crumb retrieval");
232 return crumbResponse.getCrumb();
234 throw new HttpException("Get crumb attempt towards Jenkins failed. HTTP error code: " + response.getStatus()
235 + " and message: " + response.getEntity(String.class));
238 private void setProperties() throws NoSuchAlgorithmException, KeyManagementException {
239 SSLContext sslContext = SSLContext.getInstance("SSL");
240 sslContext.init(null, this.trustAll, new java.security.SecureRandom());
241 HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
242 // Install the all-trusting host verifier
243 HttpsURLConnection.setDefaultHostnameVerifier(this.hostnameVerifier);
244 DefaultClientConfig config = new DefaultClientConfig();
245 Map<String, Object> properties = config.getProperties();
246 HTTPSProperties httpsProperties = new HTTPSProperties((str, sslSession) -> true, sslContext);
247 properties.put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, httpsProperties);