com.xliic.cicd.audit.client.Client Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cicd-core Show documentation
Show all versions of cicd-core Show documentation
Bundles multiple OpenAPI files (in JSON or YAML formats) using external references into one JSON file.
/*
Copyright (c) 42Crunch Ltd. All rights reserved.
Licensed under the GNU Affero General Public License version 3. See LICENSE.txt in the project root for license information.
*/
package com.xliic.cicd.audit.client;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Base64;
import com.xliic.cicd.audit.model.api.ApiCollections;
import com.xliic.cicd.audit.model.api.ErrorMessage;
import com.xliic.cicd.audit.model.api.Maybe;
import com.xliic.cicd.audit.JsonParser;
import com.xliic.cicd.audit.Logger;
import com.xliic.cicd.audit.Secret;
import com.xliic.cicd.audit.model.api.Api;
import com.xliic.cicd.audit.model.api.ApiCollection;
import com.xliic.cicd.audit.model.assessment.AssessmentResponse;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.http.client.config.RequestConfig;
public class Client {
private static String proxyHost;
private static int proxyPort;
private static String userAgent;
private static String platformUrl = ClientConstants.PLATFORM_URL;
public static void setUserAgent(String userAgent) {
Client.userAgent = userAgent;
}
public static void setProxy(String proxyHost, int proxyPort) {
Client.proxyHost = proxyHost;
Client.proxyPort = proxyPort;
}
public static void setPlatformUrl(String platformUrl) {
Client.platformUrl = platformUrl;
}
public static Maybe createApi(String collectionId, String name, String json, Secret apiKey,
Logger logger) throws IOException {
HttpPost request = new HttpPost(platformUrl + "/api/v1/apis");
HttpEntity data = MultipartEntityBuilder
.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE).addBinaryBody("specfile",
json.getBytes(StandardCharsets.UTF_8), ContentType.APPLICATION_JSON, "swagger.json")
.addTextBody("name", name).addTextBody("cid", collectionId).build();
request.setEntity(data);
Maybe api = new ProxyClient(request, apiKey, Api.class, logger).execute();
if (api.isError()) {
return new Maybe(api.getError());
}
return new Maybe(new RemoteApi(api.getResult().desc.id, ApiStatus.freshApiStatus()));
}
public static Maybe updateApi(String apiId, String json, Secret apiKey, Logger logger)
throws IOException {
// read api status first
Maybe status = readApiStatus(apiId, apiKey, logger);
if (status.isError()) {
return new Maybe(status.getError());
}
// update the api
HttpPut request = new HttpPut(platformUrl + "/api/v1/apis/" + apiId);
String encodedJson = Base64.getEncoder().encodeToString(json.getBytes(StandardCharsets.UTF_8));
request.setEntity(
new StringEntity(String.format("{\"specfile\": \"%s\"}", encodedJson), ContentType.APPLICATION_JSON));
Maybe result = new ProxyClient(request, apiKey, String.class, logger).execute();
if (result.isError()) {
return new Maybe(result.getError());
}
return new Maybe(new RemoteApi(apiId, status.getResult()));
}
public static Maybe deleteApi(String apiId, Secret apiKey, Logger logger) throws IOException {
HttpDelete request = new HttpDelete(String.format("%s/api/v1/apis/%s", platformUrl, apiId));
return new ProxyClient(request, apiKey, String.class, logger).execute();
}
public static Maybe readAssessment(Maybe api, Secret apiKey, Logger logger)
throws ClientProtocolException, IOException {
if (api.isError()) {
return new Maybe(api.getError());
}
HttpGet request = new HttpGet(platformUrl + "/api/v1/apis/" + api.getResult().apiId + "/assessmentreport");
ProxyClient client = new ProxyClient(request, apiKey,
AssessmentResponse.class, logger);
LocalDateTime start = LocalDateTime.now();
LocalDateTime now = LocalDateTime.now();
while (Duration.between(start, now).toMillis() < ClientConstants.ASSESSMENT_MAX_WAIT) {
Maybe status = readApiStatus(api.getResult().apiId, apiKey, logger);
// check if assessment is ready, or bail out with the error
if (status.isOk() && status.getResult().isProcessed
&& status.getResult().lastAssessment.isAfter(api.getResult().previousStatus.lastAssessment)) {
return client.execute();
} else if (status.isError()) {
return new Maybe(status.getError());
}
// sleep if assessment is not yet ready
try {
Thread.sleep(ClientConstants.ASSESSMENT_RETRY);
} catch (Exception e) {
throw new RuntimeException(e);
}
now = LocalDateTime.now();
}
return new Maybe(
new ErrorMessage("Timed out waiting for audit result for API ID: " + api.getResult().apiId));
}
public static Maybe readApiStatus(String apiId, Secret apiKey, Logger logger) throws IOException {
HttpGet request = new HttpGet(platformUrl + "/api/v1/apis/" + apiId);
Maybe result = new ProxyClient(request, apiKey, Api.class, logger).execute();
if (result.isError()) {
return new Maybe(result.getError());
}
return new Maybe(
new ApiStatus(result.getResult().assessment.isProcessed, result.getResult().assessment.last));
}
public static Maybe listCollection(String collectionId, Secret apiKey, Logger logger)
throws IOException {
HttpGet request = new HttpGet(String.format("%s/api/v1/collections/%s/apis", platformUrl, collectionId));
return new ProxyClient(request, apiKey, ApiCollection.class, logger).execute();
}
public static Maybe listCollections(Secret apiKey, Logger logger) throws IOException {
HttpGet request = new HttpGet(platformUrl + "/api/v1/collections");
return new ProxyClient(request, apiKey, ApiCollections.class, logger).execute();
}
public static Maybe createCollection(String collectionName, Secret apiKey,
Logger logger) throws IOException {
HttpPost request = new HttpPost(platformUrl + "/api/v1/collections");
request.setEntity(new StringEntity(String.format("{\"name\": \"%s\", \"isShared\": false}", collectionName),
ContentType.APPLICATION_JSON));
return new ProxyClient(request, apiKey, ApiCollections.ApiCollection.class,
logger).execute();
}
static class ProxyClient {
private java.lang.Class contentClass;
private Logger logger;
private HttpRequestBase request;
private Secret apiKey;
ProxyClient(HttpRequestBase request, Secret apiKey, Class contentClass, Logger logger) {
this.request = request;
this.apiKey = apiKey;
this.contentClass = contentClass;
this.logger = logger;
}
Maybe execute() throws IOException {
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
configureRequest(request, apiKey, logger);
try {
response = httpClient.execute(request);
int status = response.getStatusLine().getStatusCode();
if (status >= 200 && status < 300) {
HttpEntity entity = response.getEntity();
if (contentClass.equals(String.class)) {
return new Maybe((T) EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
} else {
return new Maybe(JsonParser.parse(entity.getContent(), contentClass));
}
}
String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
if (status == 409 && responseBody.contains("limit reached")) {
return new Maybe(new ErrorMessage(String.format(
"You have reached your maximum number of APIs. Please sign into %s and upgrade your account.",
platformUrl)));
} else if (status == 403) {
return new Maybe(new ErrorMessage(
"Received 'Forbidden 403' response. Check that your API IDs are correct and API Token has required permissions: "
+ responseBody));
} else if (status == 401) {
return new Maybe(new ErrorMessage(
"Received 'Unauthorized 401' response. Check that the API token is correct: "
+ responseBody));
}
return new Maybe(
new ErrorMessage(String.format("HTTP Request: %s %s failed with unexpected status code %s",
request.getMethod(), request.getURI(), status)));
} finally {
if (response != null) {
response.close();
}
httpClient.close();
}
}
private static HttpHost getProxyHost() {
if (Client.proxyHost != null) {
return new HttpHost(Client.proxyHost, Client.proxyPort, "http");
}
return null;
}
private static void configureRequest(HttpRequestBase request, Secret apiKey, Logger logger) {
request.setHeader("Accept", "application/json");
request.setHeader("X-API-KEY", apiKey.getPlainText());
if (Client.userAgent != null) {
request.setHeader("User-Agent", Client.userAgent);
}
HttpHost proxy = getProxyHost();
if (proxy != null) {
RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
request.setConfig(config);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy