From 0df5aa1d2f10f0c20d80dfaf0311891e6d1b5974 Mon Sep 17 00:00:00 2001 From: Michal Kabaj Date: Fri, 16 Feb 2018 11:37:35 +0100 Subject: ChefApiClient Package Reorganization and cleanup -Reorganize ChefApiClient classes according to their usage, construction and implementation. -Introduce api and impl packages. -Extract interface from ChefApiClient impl -Remove unused old chefapi.* classes Change-Id: Ic1ddbdcfd0e1bbc0830b923da5aac5b68ac44a2f Issue-ID: APPC-437 Signed-off-by: Michal Kabaj --- .../onap/appc/adapter/chef/chefapi/ApiMethod.java | 167 ---------------- .../org/onap/appc/adapter/chef/chefapi/Delete.java | 36 ---- .../org/onap/appc/adapter/chef/chefapi/Get.java | 35 ---- .../org/onap/appc/adapter/chef/chefapi/Post.java | 46 ----- .../org/onap/appc/adapter/chef/chefapi/Put.java | 46 ----- .../adapter/chef/chefclient/ChefApiClient.java | 100 ---------- .../chef/chefclient/ChefApiClientFactory.java | 5 +- .../chef/chefclient/ChefApiHeaderFactory.java | 71 ------- .../chef/chefclient/ChefRequestBuilder.java | 112 ----------- .../appc/adapter/chef/chefclient/ChefResponse.java | 43 ---- .../chef/chefclient/FormattedTimestamp.java | 36 ---- .../onap/appc/adapter/chef/chefclient/Utils.java | 105 ---------- .../adapter/chef/chefclient/api/ChefApiClient.java | 31 +++ .../adapter/chef/chefclient/api/ChefResponse.java | 43 ++++ .../chef/chefclient/impl/ChefApiClientImpl.java | 106 ++++++++++ .../chef/chefclient/impl/ChefApiHeaderFactory.java | 71 +++++++ .../chef/chefclient/impl/ChefRequestBuilder.java | 112 +++++++++++ .../chef/chefclient/impl/FormattedTimestamp.java | 36 ++++ .../appc/adapter/chef/chefclient/impl/Utils.java | 105 ++++++++++ .../appc/adapter/chef/impl/ChefAdapterImpl.java | 5 +- .../adapter/chef/chefclient/ChefApiClientTest.java | 215 -------------------- .../chef/chefclient/ChefApiHeaderFactoryTest.java | 83 -------- .../chef/chefclient/FormattedTimestampTest.java | 40 ---- .../chefclient/impl/ChefApiClientImplTest.java | 218 +++++++++++++++++++++ .../chefclient/impl/ChefApiHeaderFactoryTest.java | 83 ++++++++ .../chefclient/impl/FormattedTimestampTest.java | 40 ++++ .../src/test/resources/test.properties | 26 --- 27 files changed, 851 insertions(+), 1165 deletions(-) delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/ApiMethod.java delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Delete.java delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Get.java delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Post.java delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Put.java delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefApiClient.java delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefApiHeaderFactory.java delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefRequestBuilder.java delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefResponse.java delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/FormattedTimestamp.java delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/Utils.java create mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/api/ChefApiClient.java create mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/api/ChefResponse.java create mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiClientImpl.java create mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiHeaderFactory.java create mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/ChefRequestBuilder.java create mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/FormattedTimestamp.java create mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/Utils.java delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/ChefApiClientTest.java delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/ChefApiHeaderFactoryTest.java delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/FormattedTimestampTest.java create mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiClientImplTest.java create mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiHeaderFactoryTest.java create mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/impl/FormattedTimestampTest.java delete mode 100644 appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/resources/test.properties (limited to 'appc-adapters') diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/ApiMethod.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/ApiMethod.java deleted file mode 100644 index 8edee5709..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/ApiMethod.java +++ /dev/null @@ -1,167 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Copyright (C) 2017 Amdocs - * ============================================================================= - * 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. - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * ============LICENSE_END========================================================= - */ - -package org.onap.appc.adapter.chef.chefapi; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.TimeZone; - -import org.apache.http.HttpResponse; -import org.apache.http.Header; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.util.EntityUtils; -import org.onap.appc.adapter.chef.chefclient.Utils; - -import org.apache.http.HttpEntity; -import org.apache.http.impl.client.HttpClients; - -public class ApiMethod { - private HttpClient client = null; - protected HttpRequestBase method = null; - protected HttpResponse response = null; - protected String reqBody = ""; - protected String userId = ""; - protected String pemPath = ""; - protected String chefPath = ""; - protected String organizations = ""; - protected int resCode=0; - protected String responseBody=""; - private String methodName = "GET"; - public String test = ""; - private int returnCode; - final String KEY_STORE_PATH = "/etc/chef/trusted_certs/mykeystore.jks"; - final String KEY_STORE_PASSWORD = "adminadmin"; - static - { - System.setProperty("javax.net.ssl.trustStore", "/opt/onap/appc/chef/chefServerSSL.jks"); - System.setProperty("javax.net.ssl.trustStorePassword", "adminadmin"); - } - - public ApiMethod(String methodName) { - client=HttpClients.createDefault(); - this.methodName = methodName; - } - - - - public ApiMethod execute() { - String hashedPath = Utils.sha1AndBase64("/organizations/"+organizations+chefPath); - String hashedBody = Utils.sha1AndBase64(reqBody); - - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - sdf.setTimeZone(TimeZone.getTimeZone("UTC")); - String timeStamp = sdf.format(new Date()); - timeStamp = timeStamp.replace(" ", "T"); - timeStamp = timeStamp + "Z"; - - StringBuilder sb = new StringBuilder(); - sb.append("Method:").append(methodName).append("\n"); - sb.append("Hashed Path:").append(hashedPath).append("\n"); - sb.append("X-Ops-Content-Hash:").append(hashedBody).append("\n"); - sb.append("X-Ops-Timestamp:").append(timeStamp).append("\n"); - sb.append("X-Ops-UserId:").append(userId); - test = test + "sb " + sb + "\n"; - - String auth_String = Utils.signWithRSA(sb.toString(), pemPath); - String[] auth_headers = Utils.splitAs60(auth_String); - - method.addHeader("Content-type", "application/json"); - method.addHeader("X-Ops-Timestamp", timeStamp); - method.addHeader("X-Ops-Userid", userId); - method.addHeader("X-Chef-Version", "12.4.1"); - method.addHeader("Accept", "application/json"); - method.addHeader("X-Ops-Content-Hash", hashedBody); - method.addHeader("X-Ops-Sign", "version=1.0"); - - for (int i = 0; i < auth_headers.length; i++) { - method.addHeader("X-Ops-Authorization-" + (i + 1), auth_headers[i]); - } - try{ - response = client.execute(method); - resCode = response.getStatusLine().getStatusCode(); - HttpEntity entity1 = response.getEntity(); - responseBody = EntityUtils.toString(entity1);} - catch(Exception ex){ - resCode=500; - responseBody=ex.getMessage(); - } - return this; - } - - public void setHeaders(Header[] headers) { - for (Header header : headers) { - this.method.addHeader(header); - } - } - - public String getResponseBodyAsString() { - return responseBody; - } - - public int getReturnCode() { - return resCode; - } - - public String getReqBody() { - return reqBody; - } - - public void setReqBody(String body) { - this.reqBody = body; - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public String getPemPath() { - return pemPath; - } - - public void setPemPath(String pemPath) { - this.pemPath = pemPath; - } - - public String getChefPath() { - return chefPath; - } - - public void setChefPath(String chefPath) { - this.chefPath = chefPath; - } - - public String getOrganizations() { - return organizations; - } - - public void setOrganizations(String organizations) { - this.organizations = organizations; - } -} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Delete.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Delete.java deleted file mode 100644 index 5fa8a3fae..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Delete.java +++ /dev/null @@ -1,36 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Copyright (C) 2017 Amdocs - * ============================================================================= - * 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. - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * ============LICENSE_END========================================================= - */ - -package org.onap.appc.adapter.chef.chefapi; - -import org.apache.http.client.methods.HttpDelete; - -public class Delete extends ApiMethod{ - - public Delete(HttpDelete method) { - super("DELETE"); - this.method = method; - } - -} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Get.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Get.java deleted file mode 100644 index da37236a7..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Get.java +++ /dev/null @@ -1,35 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Copyright (C) 2017 Amdocs - * ============================================================================= - * 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. - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * ============LICENSE_END========================================================= - */ - -package org.onap.appc.adapter.chef.chefapi; - -import org.apache.http.client.methods.HttpGet; - -public class Get extends ApiMethod{ - - public Get(HttpGet method) { - super("GET"); - this.method = method; - } -} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Post.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Post.java deleted file mode 100644 index 3234eeefa..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Post.java +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Copyright (C) 2017 Amdocs - * ============================================================================= - * 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. - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * ============LICENSE_END========================================================= - */ - -package org.onap.appc.adapter.chef.chefapi; - -import org.apache.http.client.methods.*; -import org.apache.http.entity.StringEntity; - -public class Post extends ApiMethod{ - - public Post(HttpRequestBase method) { - super("POST"); - this.method = method; - } - - public ApiMethod body(String body){ - this.reqBody = body; - StringEntity params =new StringEntity (body,"UTF-8"); - params.setContentType("application/json"); - HttpPost post = (HttpPost) method; - post.setEntity(params); - return this; - } - -} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Put.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Put.java deleted file mode 100644 index c96fc64d1..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefapi/Put.java +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Copyright (C) 2017 Amdocs - * ============================================================================= - * 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. - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * ============LICENSE_END========================================================= - */ - -package org.onap.appc.adapter.chef.chefapi; - -import org.apache.http.client.methods.*; -import org.apache.http.entity.StringEntity; - -public class Put extends ApiMethod{ - - public Put(HttpRequestBase method) { - super("PUT"); - this.method = method; - } - - public ApiMethod body(String body){ - this.reqBody = body; - StringEntity params =new StringEntity (body,"UTF-8"); - params.setContentType("application/json"); - HttpPut put = (HttpPut) method; - put.setEntity(params); - return this; - } - -} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefApiClient.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefApiClient.java deleted file mode 100644 index 33d463bde..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefApiClient.java +++ /dev/null @@ -1,100 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Copyright (C) 2017 Amdocs - * ============================================================================= - * 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. - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * ============LICENSE_END========================================================= - */ - -package org.onap.appc.adapter.chef.chefclient; - -import java.io.IOException; -import java.net.URISyntaxException; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.HttpClient; -import org.apache.http.util.EntityUtils; -import org.onap.appc.adapter.chef.chefclient.ChefRequestBuilder.OngoingRequestBuilder; - -public class ChefApiClient { - - private final HttpClient httpClient; - private final ChefApiHeaderFactory chefApiHeaderFactory; - private String endpoint; - private String userId; - private String pemPath; - private String organizations; - - ChefApiClient(HttpClient httpClient, ChefApiHeaderFactory chefApiHeaderFactory, - String endpoint, String organizations, String userId, String pemPath) { - this.httpClient = httpClient; - this.chefApiHeaderFactory = chefApiHeaderFactory; - this.endpoint = endpoint; - this.organizations = organizations; - this.userId = userId; - this.pemPath = pemPath; - } - - public ChefResponse get(String path) { - OngoingRequestBuilder requestBuilder = ChefRequestBuilder.newRequestTo(endpoint) - .httpGet() - .withPath(path) - .withHeaders(chefApiHeaderFactory.create("GET", path, "", userId, organizations, pemPath)); - return execute(requestBuilder); - } - - public ChefResponse delete(String path) { - OngoingRequestBuilder requestBuilder = ChefRequestBuilder.newRequestTo(endpoint) - .httpDelete() - .withPath(path) - .withHeaders(chefApiHeaderFactory.create("DELETE", path, "", userId, organizations, pemPath)); - return execute(requestBuilder); - } - - public ChefResponse post(String path, String body) { - OngoingRequestBuilder requestBuilder = ChefRequestBuilder.newRequestTo(endpoint) - .httpPost(body) - .withPath(path) - .withHeaders(chefApiHeaderFactory.create("POST", path, body, userId, organizations, pemPath)); - return execute(requestBuilder); - } - - public ChefResponse put(String path, String body) { - OngoingRequestBuilder requestBuilder = ChefRequestBuilder.newRequestTo(endpoint) - .httpPut(body) - .withPath(path) - .withHeaders(chefApiHeaderFactory.create("PUT", path, body, userId, organizations, pemPath)); - return execute(requestBuilder); - } - - private ChefResponse execute(OngoingRequestBuilder chefRequest) { - try { - HttpResponse response = httpClient.execute(chefRequest.build()); - int statusCode = response.getStatusLine().getStatusCode(); - HttpEntity httpEntity = response.getEntity(); - String responseBody = EntityUtils.toString(httpEntity); - return ChefResponse.create(statusCode, responseBody); - } catch (IOException ex) { - return ChefResponse.create(HttpStatus.SC_INTERNAL_SERVER_ERROR, ex.getMessage()); - } catch (URISyntaxException ex) { - return ChefResponse.create(HttpStatus.SC_INTERNAL_SERVER_ERROR, ex.getMessage()); - } - } -} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefApiClientFactory.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefApiClientFactory.java index b3c4272c1..a69ccf1b2 100644 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefApiClientFactory.java +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefApiClientFactory.java @@ -21,6 +21,9 @@ package org.onap.appc.adapter.chef.chefclient; import org.apache.http.client.HttpClient; import org.apache.http.impl.client.HttpClients; +import org.onap.appc.adapter.chef.chefclient.api.ChefApiClient; +import org.onap.appc.adapter.chef.chefclient.impl.ChefApiClientImpl; +import org.onap.appc.adapter.chef.chefclient.impl.ChefApiHeaderFactory; public final class ChefApiClientFactory { @@ -28,7 +31,7 @@ public final class ChefApiClientFactory { private ChefApiHeaderFactory chefApiHeaderFactory = new ChefApiHeaderFactory(); public ChefApiClient create(String endPoint, String organizations, String userId, String pemPath) { - return new ChefApiClient(httpClient, + return new ChefApiClientImpl(httpClient, chefApiHeaderFactory, endPoint, organizations, diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefApiHeaderFactory.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefApiHeaderFactory.java deleted file mode 100644 index 94abd06dd..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefApiHeaderFactory.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2018 Nokia. All rights reserved. - * ============================================================================= - * 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. - * ============LICENSE_END========================================================= - */ -package org.onap.appc.adapter.chef.chefclient; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableMap.Builder; -import java.util.Date; - -class ChefApiHeaderFactory { - - private FormattedTimestamp formattedTimestamp = new FormattedTimestamp(); - - static { - System.setProperty("javax.net.ssl.trustStore", "/opt/onap/appc/chef/chefServerSSL.jks"); - System.setProperty("javax.net.ssl.trustStorePassword", "adminadmin"); - } - - ImmutableMap create(String methodName, String path, String body, String userId, - String organizations, String pemPath) { - - String hashedBody = Utils.sha1AndBase64(body); - String timeStamp = formattedTimestamp.format(new Date()); - - Builder builder = ImmutableMap.builder(); - builder - .put("Content-type", "application/json") - .put("Accept", "application/json") - .put("X-Ops-Timestamp", timeStamp) - .put("X-Ops-UserId", userId) - .put("X-Chef-Version", "12.4.1") - .put("X-Ops-Content-Hash", hashedBody) - .put("X-Ops-Sign", "version=1.0") - .build(); - - String hashedPath = Utils.sha1AndBase64("/organizations/" + organizations + path); - - StringBuilder sb = new StringBuilder(); - sb.append("Method:").append(methodName).append("\n"); - sb.append("Hashed Path:").append(hashedPath).append("\n"); - sb.append("X-Ops-Content-Hash:").append(hashedBody).append("\n"); - sb.append("X-Ops-Timestamp:").append(timeStamp).append("\n"); - sb.append("X-Ops-UserId:").append(userId); - - String auth_String = Utils.signWithRSA(sb.toString(), pemPath); - String[] auth_headers = Utils.splitAs60(auth_String); - - for (int i = 0; i < auth_headers.length; i++) { - builder.put("X-Ops-Authorization-" + (i + 1), auth_headers[i]); - } - - return builder.build(); - } - -} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefRequestBuilder.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefRequestBuilder.java deleted file mode 100644 index acf0a489d..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefRequestBuilder.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2018 Nokia. All rights reserved. - * ============================================================================= - * 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. - * ============LICENSE_END========================================================= - */ -package org.onap.appc.adapter.chef.chefclient; - -import com.google.common.collect.ImmutableMap; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Map.Entry; -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.client.utils.URIBuilder; -import org.apache.http.entity.StringEntity; - -public final class ChefRequestBuilder { - - private ChefRequestBuilder() { - } - - public static OngoingRequestBuilder newRequestTo(String endPoint) { - return new OngoingRequestBuilder(endPoint); - } - - public static class OngoingRequestBuilder { - - private HttpRequestBase httpRequestBase; - private String endPoint; - private String path; - private ImmutableMap headers; - - private OngoingRequestBuilder(String endPoint) { - this.endPoint = endPoint; - } - - public OngoingRequestBuilder withPath(String path) { - this.path = path; - return this; - } - - public OngoingRequestBuilder httpGet() { - httpRequestBase = new HttpGet(); - return this; - } - - public OngoingRequestBuilder httpDelete() { - httpRequestBase = new HttpDelete(); - return this; - } - - public OngoingRequestBuilder httpPost(String body) { - HttpPost httpPost = new HttpPost(); - toEntity(body); - httpRequestBase = httpPost; - return this; - } - - public OngoingRequestBuilder httpPut(String body) { - HttpPut httpPut = new HttpPut(); - toEntity(body); - httpRequestBase = httpPut; - return this; - } - - private void toEntity(String body) { - StringEntity stringEntity = new StringEntity(body, "UTF-8"); - stringEntity.setContentType("application/json"); - } - - public OngoingRequestBuilder withHeaders(ImmutableMap headers) { - this.headers = headers; - return this; - } - - public HttpRequestBase build() throws URISyntaxException { - setRequestUri(); - setRequestHeaders(); - - return httpRequestBase; - } - - private void setRequestUri() throws URISyntaxException { - URI fullPath = new URIBuilder(endPoint) - .setPath(path).build(); - httpRequestBase.setURI(fullPath); - } - - private void setRequestHeaders() { - for (Entry entry : headers.entrySet()) { - httpRequestBase.addHeader(entry.getKey(), entry.getValue()); - } - } - } -} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefResponse.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefResponse.java deleted file mode 100644 index e83711a44..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/ChefResponse.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2018 Nokia. All rights reserved. - * ============================================================================= - * 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. - * ============LICENSE_END========================================================= - */ -package org.onap.appc.adapter.chef.chefclient; - -public final class ChefResponse { - - private final String body; - private final int status; - - public static ChefResponse create(int status, String body) { - return new ChefResponse(status, body); - } - - private ChefResponse(int status, String body) { - this.status = status; - this.body = body; - } - - public int getStatusCode() { - return status; - } - - public String getBody() { - return body; - } -} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/FormattedTimestamp.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/FormattedTimestamp.java deleted file mode 100644 index 15ad87389..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/FormattedTimestamp.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2018 Nokia. All rights reserved. - * ============================================================================= - * 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. - * ============LICENSE_END========================================================= - */ -package org.onap.appc.adapter.chef.chefclient; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.TimeZone; - -class FormattedTimestamp { - - String format(Date date) { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - sdf.setTimeZone(TimeZone.getTimeZone("UTC")); - String timeStamp = sdf.format(date); - timeStamp = timeStamp.replace(" ", "T"); - timeStamp = timeStamp + "Z"; - return timeStamp; - } -} \ No newline at end of file diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/Utils.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/Utils.java deleted file mode 100644 index 3f7f203b7..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/Utils.java +++ /dev/null @@ -1,105 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Copyright (C) 2017 Amdocs - * ============================================================================= - * 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. - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * ============LICENSE_END========================================================= - */ - -package org.onap.appc.adapter.chef.chefclient; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; -import java.security.InvalidKeyException; -import java.security.KeyPair; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.Security; -import java.security.Signature; -import java.security.SignatureException; - -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.openssl.PEMParser; -import org.bouncycastle.util.encoders.Base64; -import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; -import org.bouncycastle.openssl.PEMKeyPair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class Utils { - private final static Logger logger = LoggerFactory.getLogger(Utils.class); - private Utils(){} - - public static String sha1AndBase64(String inStr) { - MessageDigest md = null; - byte[] outbty = null; - try { - md = MessageDigest.getInstance("SHA-1"); - byte[] digest = md.digest(inStr.getBytes()); - outbty = Base64.encode(digest); - } catch (NoSuchAlgorithmException nsae) { - logger.error(nsae.getMessage()); - } - return new String(outbty); - } - - public static String signWithRSA(String inStr, String pemPath) { - byte[] outStr = null; - try ( BufferedReader br = new BufferedReader(new FileReader(pemPath))) { - Security.addProvider(new BouncyCastleProvider()); - PEMParser pemParser = new PEMParser(br); - JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); - Object object = pemParser.readObject(); - KeyPair kp = converter.getKeyPair((PEMKeyPair) object);; - PrivateKey privateKey = kp.getPrivate(); - Signature instance = Signature.getInstance("RSA"); - instance.initSign(privateKey); - instance.update(inStr.getBytes()); - byte[] signature = instance.sign(); - outStr = Base64.encode(signature); - String tmp = new String(outStr); - } catch (InvalidKeyException e) { - logger.error(e.getMessage()); - } catch (IOException e) { - logger.error(e.getMessage()); - } catch (SignatureException e) { - logger.error(e.getMessage()); - } catch (NoSuchAlgorithmException e) { - logger.error(e.getMessage()); - } - return new String(outStr); - } - - public static String[] splitAs60(String inStr) { - int count = inStr.length() / 60; - String[] out = new String[count + 1]; - for (int i = 0; i < count; i++) { - String tmp = inStr.substring(i * 60, i * 60 + 60); - out[i] = tmp; - } - if (inStr.length() > count * 60) { - String tmp = inStr.substring(count * 60, inStr.length()); - out[count] = tmp; - } - return out; - } - -} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/api/ChefApiClient.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/api/ChefApiClient.java new file mode 100644 index 000000000..058795b69 --- /dev/null +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/api/ChefApiClient.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ============================================================================= + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.appc.adapter.chef.chefclient.api; + +public interface ChefApiClient { + + ChefResponse get(String path); + + ChefResponse delete(String path); + + ChefResponse post(String path, String body); + + ChefResponse put(String path, String body); +} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/api/ChefResponse.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/api/ChefResponse.java new file mode 100644 index 000000000..5f8ec1f8f --- /dev/null +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/api/ChefResponse.java @@ -0,0 +1,43 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ============================================================================= + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.appc.adapter.chef.chefclient.api; + +public final class ChefResponse { + + private final String body; + private final int status; + + public static ChefResponse create(int status, String body) { + return new ChefResponse(status, body); + } + + private ChefResponse(int status, String body) { + this.status = status; + this.body = body; + } + + public int getStatusCode() { + return status; + } + + public String getBody() { + return body; + } +} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiClientImpl.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiClientImpl.java new file mode 100644 index 000000000..b26f69a9e --- /dev/null +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiClientImpl.java @@ -0,0 +1,106 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.chef.chefclient.impl; + +import java.io.IOException; +import java.net.URISyntaxException; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.util.EntityUtils; +import org.onap.appc.adapter.chef.chefclient.api.ChefApiClient; +import org.onap.appc.adapter.chef.chefclient.api.ChefResponse; +import org.onap.appc.adapter.chef.chefclient.impl.ChefRequestBuilder.OngoingRequestBuilder; + +public class ChefApiClientImpl implements ChefApiClient { + + private final HttpClient httpClient; + private final ChefApiHeaderFactory chefApiHeaderFactory; + private String endpoint; + private String userId; + private String pemPath; + private String organizations; + + public ChefApiClientImpl(HttpClient httpClient, ChefApiHeaderFactory chefApiHeaderFactory, + String endpoint, String organizations, String userId, String pemPath) { + this.httpClient = httpClient; + this.chefApiHeaderFactory = chefApiHeaderFactory; + this.endpoint = endpoint; + this.organizations = organizations; + this.userId = userId; + this.pemPath = pemPath; + } + + @Override + public ChefResponse get(String path) { + OngoingRequestBuilder requestBuilder = ChefRequestBuilder.newRequestTo(endpoint) + .httpGet() + .withPath(path) + .withHeaders(chefApiHeaderFactory.create("GET", path, "", userId, organizations, pemPath)); + return execute(requestBuilder); + } + + @Override + public ChefResponse delete(String path) { + OngoingRequestBuilder requestBuilder = ChefRequestBuilder.newRequestTo(endpoint) + .httpDelete() + .withPath(path) + .withHeaders(chefApiHeaderFactory.create("DELETE", path, "", userId, organizations, pemPath)); + return execute(requestBuilder); + } + + @Override + public ChefResponse post(String path, String body) { + OngoingRequestBuilder requestBuilder = ChefRequestBuilder.newRequestTo(endpoint) + .httpPost(body) + .withPath(path) + .withHeaders(chefApiHeaderFactory.create("POST", path, body, userId, organizations, pemPath)); + return execute(requestBuilder); + } + + @Override + public ChefResponse put(String path, String body) { + OngoingRequestBuilder requestBuilder = ChefRequestBuilder.newRequestTo(endpoint) + .httpPut(body) + .withPath(path) + .withHeaders(chefApiHeaderFactory.create("PUT", path, body, userId, organizations, pemPath)); + return execute(requestBuilder); + } + + private ChefResponse execute(OngoingRequestBuilder chefRequest) { + try { + HttpResponse response = httpClient.execute(chefRequest.build()); + int statusCode = response.getStatusLine().getStatusCode(); + HttpEntity httpEntity = response.getEntity(); + String responseBody = EntityUtils.toString(httpEntity); + return ChefResponse.create(statusCode, responseBody); + } catch (IOException ex) { + return ChefResponse.create(HttpStatus.SC_INTERNAL_SERVER_ERROR, ex.getMessage()); + } catch (URISyntaxException ex) { + return ChefResponse.create(HttpStatus.SC_INTERNAL_SERVER_ERROR, ex.getMessage()); + } + } +} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiHeaderFactory.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiHeaderFactory.java new file mode 100644 index 000000000..d045135c4 --- /dev/null +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiHeaderFactory.java @@ -0,0 +1,71 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ============================================================================= + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.appc.adapter.chef.chefclient.impl; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; +import java.util.Date; + +public class ChefApiHeaderFactory { + + private FormattedTimestamp formattedTimestamp = new FormattedTimestamp(); + + static { + System.setProperty("javax.net.ssl.trustStore", "/opt/onap/appc/chef/chefServerSSL.jks"); + System.setProperty("javax.net.ssl.trustStorePassword", "adminadmin"); + } + + public ImmutableMap create(String methodName, String path, String body, String userId, + String organizations, String pemPath) { + + String hashedBody = Utils.sha1AndBase64(body); + String timeStamp = formattedTimestamp.format(new Date()); + + Builder builder = ImmutableMap.builder(); + builder + .put("Content-type", "application/json") + .put("Accept", "application/json") + .put("X-Ops-Timestamp", timeStamp) + .put("X-Ops-UserId", userId) + .put("X-Chef-Version", "12.4.1") + .put("X-Ops-Content-Hash", hashedBody) + .put("X-Ops-Sign", "version=1.0") + .build(); + + String hashedPath = Utils.sha1AndBase64("/organizations/" + organizations + path); + + StringBuilder sb = new StringBuilder(); + sb.append("Method:").append(methodName).append("\n"); + sb.append("Hashed Path:").append(hashedPath).append("\n"); + sb.append("X-Ops-Content-Hash:").append(hashedBody).append("\n"); + sb.append("X-Ops-Timestamp:").append(timeStamp).append("\n"); + sb.append("X-Ops-UserId:").append(userId); + + String auth_String = Utils.signWithRSA(sb.toString(), pemPath); + String[] auth_headers = Utils.splitAs60(auth_String); + + for (int i = 0; i < auth_headers.length; i++) { + builder.put("X-Ops-Authorization-" + (i + 1), auth_headers[i]); + } + + return builder.build(); + } + +} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/ChefRequestBuilder.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/ChefRequestBuilder.java new file mode 100644 index 000000000..a2248438a --- /dev/null +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/ChefRequestBuilder.java @@ -0,0 +1,112 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ============================================================================= + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.appc.adapter.chef.chefclient.impl; + +import com.google.common.collect.ImmutableMap; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Map.Entry; +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.client.utils.URIBuilder; +import org.apache.http.entity.StringEntity; + +final class ChefRequestBuilder { + + private ChefRequestBuilder() { + } + + static OngoingRequestBuilder newRequestTo(String endPoint) { + return new OngoingRequestBuilder(endPoint); + } + + static class OngoingRequestBuilder { + + private HttpRequestBase httpRequestBase; + private String endPoint; + private String path; + private ImmutableMap headers; + + private OngoingRequestBuilder(String endPoint) { + this.endPoint = endPoint; + } + + public OngoingRequestBuilder withPath(String path) { + this.path = path; + return this; + } + + public OngoingRequestBuilder httpGet() { + httpRequestBase = new HttpGet(); + return this; + } + + public OngoingRequestBuilder httpDelete() { + httpRequestBase = new HttpDelete(); + return this; + } + + public OngoingRequestBuilder httpPost(String body) { + HttpPost httpPost = new HttpPost(); + toEntity(body); + httpRequestBase = httpPost; + return this; + } + + public OngoingRequestBuilder httpPut(String body) { + HttpPut httpPut = new HttpPut(); + toEntity(body); + httpRequestBase = httpPut; + return this; + } + + private void toEntity(String body) { + StringEntity stringEntity = new StringEntity(body, "UTF-8"); + stringEntity.setContentType("application/json"); + } + + public OngoingRequestBuilder withHeaders(ImmutableMap headers) { + this.headers = headers; + return this; + } + + public HttpRequestBase build() throws URISyntaxException { + setRequestUri(); + setRequestHeaders(); + + return httpRequestBase; + } + + private void setRequestUri() throws URISyntaxException { + URI fullPath = new URIBuilder(endPoint) + .setPath(path).build(); + httpRequestBase.setURI(fullPath); + } + + private void setRequestHeaders() { + for (Entry entry : headers.entrySet()) { + httpRequestBase.addHeader(entry.getKey(), entry.getValue()); + } + } + } +} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/FormattedTimestamp.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/FormattedTimestamp.java new file mode 100644 index 000000000..f9adee5d6 --- /dev/null +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/FormattedTimestamp.java @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ============================================================================= + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.appc.adapter.chef.chefclient.impl; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + +class FormattedTimestamp { + + String format(Date date) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + sdf.setTimeZone(TimeZone.getTimeZone("UTC")); + String timeStamp = sdf.format(date); + timeStamp = timeStamp.replace(" ", "T"); + timeStamp = timeStamp + "Z"; + return timeStamp; + } +} \ No newline at end of file diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/Utils.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/Utils.java new file mode 100644 index 000000000..ede5ed3d9 --- /dev/null +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/chefclient/impl/Utils.java @@ -0,0 +1,105 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Copyright (C) 2017 Amdocs + * ============================================================================= + * 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. + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ============LICENSE_END========================================================= + */ + +package org.onap.appc.adapter.chef.chefclient.impl; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.Security; +import java.security.Signature; +import java.security.SignatureException; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.util.encoders.Base64; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.bouncycastle.openssl.PEMKeyPair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Utils { + private final static Logger logger = LoggerFactory.getLogger(Utils.class); + private Utils(){} + + public static String sha1AndBase64(String inStr) { + MessageDigest md = null; + byte[] outbty = null; + try { + md = MessageDigest.getInstance("SHA-1"); + byte[] digest = md.digest(inStr.getBytes()); + outbty = Base64.encode(digest); + } catch (NoSuchAlgorithmException nsae) { + logger.error(nsae.getMessage()); + } + return new String(outbty); + } + + public static String signWithRSA(String inStr, String pemPath) { + byte[] outStr = null; + try ( BufferedReader br = new BufferedReader(new FileReader(pemPath))) { + Security.addProvider(new BouncyCastleProvider()); + PEMParser pemParser = new PEMParser(br); + JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); + Object object = pemParser.readObject(); + KeyPair kp = converter.getKeyPair((PEMKeyPair) object);; + PrivateKey privateKey = kp.getPrivate(); + Signature instance = Signature.getInstance("RSA"); + instance.initSign(privateKey); + instance.update(inStr.getBytes()); + byte[] signature = instance.sign(); + outStr = Base64.encode(signature); + String tmp = new String(outStr); + } catch (InvalidKeyException e) { + logger.error(e.getMessage()); + } catch (IOException e) { + logger.error(e.getMessage()); + } catch (SignatureException e) { + logger.error(e.getMessage()); + } catch (NoSuchAlgorithmException e) { + logger.error(e.getMessage()); + } + return new String(outStr); + } + + public static String[] splitAs60(String inStr) { + int count = inStr.length() / 60; + String[] out = new String[count + 1]; + for (int i = 0; i < count; i++) { + String tmp = inStr.substring(i * 60, i * 60 + 60); + out[i] = tmp; + } + if (inStr.length() > count * 60) { + String tmp = inStr.substring(count * 60, inStr.length()); + out[count] = tmp; + } + return out; + } + +} diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/impl/ChefAdapterImpl.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/impl/ChefAdapterImpl.java index 65e64f839..eb5ee7bde 100644 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/impl/ChefAdapterImpl.java +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/main/java/org/onap/appc/adapter/chef/impl/ChefAdapterImpl.java @@ -38,10 +38,9 @@ import org.apache.http.util.EntityUtils; import org.json.JSONException; import org.json.JSONObject; import org.onap.appc.adapter.chef.ChefAdapter; -import org.onap.appc.adapter.chef.chefapi.ApiMethod; -import org.onap.appc.adapter.chef.chefclient.ChefApiClient; +import org.onap.appc.adapter.chef.chefclient.api.ChefApiClient; import org.onap.appc.adapter.chef.chefclient.ChefApiClientFactory; -import org.onap.appc.adapter.chef.chefclient.ChefResponse; +import org.onap.appc.adapter.chef.chefclient.api.ChefResponse; import org.onap.ccsdk.sli.core.sli.SvcLogicContext; import org.onap.ccsdk.sli.core.sli.SvcLogicException; import com.att.eelf.configuration.EELFLogger; diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/ChefApiClientTest.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/ChefApiClientTest.java deleted file mode 100644 index 58b55854a..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/ChefApiClientTest.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2018 Nokia. All rights reserved. - * ============================================================================= - * 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. - * ============LICENSE_END========================================================= - */ -package org.onap.appc.adapter.chef.chefclient; - -import static junit.framework.TestCase.assertEquals; -import static org.mockito.BDDMockito.given; -import static org.mockito.Matchers.argThat; -import static org.mockito.Mockito.mock; - -import com.google.common.collect.ImmutableMap; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.function.Supplier; -import org.apache.http.Header; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.StatusLine; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.entity.StringEntity; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentMatcher; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; - -@RunWith(MockitoJUnitRunner.class) -public class ChefApiClientTest { - - private static final String END_POINT = "https://chefServer"; - private static final String ORGANIZATIONS_PATH = "onap"; - private static final String USER_ID = "testUser"; - private static final String REQUEST_PATH = "/test/path"; - private static final String BODY = "SOME BODY STRING"; - private static final ImmutableMap HEADERS = ImmutableMap.builder() - .put("Content-type", "application/json") - .put("Accept", "application/json") - .put("X-Ops-Timestamp", "1970-01-15T06:56:07Z") - .put("X-Ops-UserId", USER_ID) - .put("X-Chef-Version", "12.4.1") - .put("X-Ops-Content-Hash", BODY) - .put("X-Ops-Sign", "version=1.0").build(); - - @Mock - private HttpClient httpClient; - @Mock - private ChefApiHeaderFactory chefHttpHeaderFactory; - - @InjectMocks - private ChefApiClientFactory chefApiClientFactory; - private static final String PEM_FILEPATH = "path/to/pemFile"; - private ChefApiClient chefApiClient; - - @Before - public void setUp() { - chefApiClient = chefApiClientFactory.create( - END_POINT, - ORGANIZATIONS_PATH, - USER_ID, - PEM_FILEPATH); - } - - @Test - public void execute_HttpGet_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException { - // GIVEN - String methodName = "GET"; - String body = ""; - Supplier chefClientApiCall = () -> chefApiClient.get(REQUEST_PATH); - - // WHEN //THEN - assertChefApiClientCall(methodName, body, chefClientApiCall); - } - - @Test - public void execute_HttpDelete_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException { - // GIVEN - String methodName = "DELETE"; - String body = ""; - Supplier chefClientApiCall = () -> chefApiClient.delete(REQUEST_PATH); - - // WHEN //THEN - assertChefApiClientCall(methodName, body, chefClientApiCall); - } - - @Test - public void execute_HttpPost_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException { - // GIVEN - String methodName = "POST"; - Supplier chefClientApiCall = () -> chefApiClient.post(REQUEST_PATH, BODY); - - // WHEN //THEN - assertChefApiClientCall(methodName, BODY, chefClientApiCall); - } - - @Test - public void execute_HttpPut_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException { - // GIVEN - String methodName = "PUT"; - Supplier chefClientApiCall = () -> chefApiClient.put(REQUEST_PATH, BODY); - - // WHEN //THEN - assertChefApiClientCall(methodName, BODY, chefClientApiCall); - } - - private void assertChefApiClientCall(String methodName, String body, Supplier httpMethod) - throws IOException { - // GIVEN - given(chefHttpHeaderFactory.create(methodName, REQUEST_PATH, body, USER_ID, ORGANIZATIONS_PATH, PEM_FILEPATH)) - .willReturn(HEADERS); - - StatusLine statusLine = mock(StatusLine.class); - given(statusLine.getStatusCode()).willReturn(HttpStatus.SC_OK); - HttpResponse httpResponse = mock(HttpResponse.class); - given(httpResponse.getStatusLine()).willReturn(statusLine); - given(httpResponse.getEntity()).willReturn(new StringEntity("Successful Response String")); - given(httpClient.execute(argThat(new HttpRequestBaseMatcher(methodName)))) - .willReturn(httpResponse); - - // WHEN - ChefResponse chefResponse = httpMethod.get(); - - // THEN - assertEquals("Successful Response String", chefResponse.getBody()); - assertEquals(HttpStatus.SC_OK, chefResponse.getStatusCode()); - } - - @Test - public void execute_shouldHandleException_whenHttpClientExecutionFails() throws IOException { - - // GIVEN - given(chefHttpHeaderFactory.create("GET", REQUEST_PATH, "", USER_ID, ORGANIZATIONS_PATH, PEM_FILEPATH)) - .willReturn(HEADERS); - - String expectedErrorMsg = "HttpClient call failed"; - given(httpClient.execute(argThat(new HttpRequestBaseMatcher("GET")))) - .willThrow(new IOException(expectedErrorMsg)); - - // WHEN - ChefResponse chefResponse = chefApiClient.get(REQUEST_PATH); - - // THEN - assertEquals(expectedErrorMsg, chefResponse.getBody()); - assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, chefResponse.getStatusCode()); - } - - @Test - public void execute_shouldHandleException_whenEndpointURIisMalformed() { - // GIVEN - String expectedErrorMsg = "Malformed escape pair at index 1: /%#@/"; - - // WHEN - ChefApiClient chefApiClient = chefApiClientFactory.create( - "/%#@/", - ORGANIZATIONS_PATH, - USER_ID, - PEM_FILEPATH); - ChefResponse chefResponse = chefApiClient.get(REQUEST_PATH); - - // THEN - assertEquals(expectedErrorMsg, chefResponse.getBody()); - assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, chefResponse.getStatusCode()); - } - - private class HttpRequestBaseMatcher extends ArgumentMatcher { - - private final String methodName; - - public HttpRequestBaseMatcher(String methodName) { - this.methodName = methodName; - } - - @Override - public boolean matches(Object argument) { - HttpRequestBase httpRequestBase = (HttpRequestBase) argument; - - boolean headersMatch = checkIfHeadersMatch(httpRequestBase); - try { - return methodName.equals(httpRequestBase.getMethod()) - && new URI(END_POINT + REQUEST_PATH).equals(httpRequestBase.getURI()) - && headersMatch; - } catch (URISyntaxException e) { - e.printStackTrace(); - return false; - } - } - - private boolean checkIfHeadersMatch(HttpRequestBase httpRequestBase) { - Header[] generatedHeaders = httpRequestBase.getAllHeaders(); - return generatedHeaders.length > 0 - && generatedHeaders.length == HEADERS.size() - && HEADERS.entrySet().stream() - .allMatch(p -> httpRequestBase.getFirstHeader(p.getKey()).getValue().equals(p.getValue())); - } - } -} \ No newline at end of file diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/ChefApiHeaderFactoryTest.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/ChefApiHeaderFactoryTest.java deleted file mode 100644 index cc309811d..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/ChefApiHeaderFactoryTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2018 Nokia. All rights reserved. - * ============================================================================= - * 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. - * ============LICENSE_END========================================================= - */ -package org.onap.appc.adapter.chef.chefclient; - -import static junit.framework.TestCase.assertEquals; -import static org.mockito.BDDMockito.given; -import static org.mockito.Matchers.any; - -import com.google.common.collect.ImmutableMap; -import java.util.Date; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; - -@RunWith(MockitoJUnitRunner.class) -public class ChefApiHeaderFactoryTest { - - private static final String ORGANIZATIONS_PATH = "onap"; - private static final String USER_ID = "testUser"; - private static final String REQUEST_PATH = "/test/path"; - private static final String EXPECTED_TIMESTAMP = "1970-01-15T06:56:07Z"; - private static final String EMPTY_BODY = ""; - - @Mock - private FormattedTimestamp formattedTimestamp; - - @InjectMocks - private ChefApiHeaderFactory chefApiHeaderFactory; - - @Test - public void create_shouldCreateProperChefHeaders_withHashedAuthorizationString() { - // GIVEN - given(formattedTimestamp.format(any(Date.class))).willReturn(EXPECTED_TIMESTAMP); - String pemFilePath = getClass().getResource("/testclient.pem").getPath(); - - // WHEN - ImmutableMap headers = chefApiHeaderFactory - .create("GET", REQUEST_PATH, "", USER_ID, ORGANIZATIONS_PATH, pemFilePath); - - // THEN - assertEquals(headers, createExpectedHeaders()); - } - - private ImmutableMap createExpectedHeaders() { - String hashedBody = Utils.sha1AndBase64(EMPTY_BODY); - ImmutableMap.Builder builder = ImmutableMap.builder(); - builder - .put("Content-type", "application/json") - .put("Accept", "application/json") - .put("X-Ops-Timestamp", EXPECTED_TIMESTAMP) - .put("X-Ops-UserId", USER_ID) - .put("X-Chef-Version", "12.4.1") - .put("X-Ops-Content-Hash", hashedBody) - .put("X-Ops-Sign", "version=1.0") - .put("X-Ops-Authorization-1", "i+HGCso703727yd2ZQWMZIIpGKgTzm41fA31LIExNxEf9mOUMcpesIHjH/Wr") - .put("X-Ops-Authorization-2", "QEvsX/Gy1ay9KsUtqhy9GA6PB8UfDeMNoVUisqR4HQW+S6IOfvqBjW+2afzE") - .put("X-Ops-Authorization-3", "RdRReB/TJIF3s6ZC8vNpbEdY9kHmwiDglhxmS8X2FS+ArSh/DK/i7MqBbjux") - .put("X-Ops-Authorization-4", "49iiOlRVG7aTr/FA115hlBYP9CYCIQWKIBUOK3JyV9fXNdVqc9R0r1XdjxUl") - .put("X-Ops-Authorization-5", "EDGw6tuE8YW8mH5wkgHCjKpXG3WjmWt2X6kUrdIu44qCBK2N3sZziSub2fJA") - .put("X-Ops-Authorization-6", "hPBuOhjiYDZuFUqC99lCryM0Hf5RMw1uTlkYsBEZmA=="); - - return builder.build(); - } -} \ No newline at end of file diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/FormattedTimestampTest.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/FormattedTimestampTest.java deleted file mode 100644 index 47d2f6c2c..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/FormattedTimestampTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP : APPC - * ================================================================================ - * Copyright (C) 2018 Nokia. All rights reserved. - * ============================================================================= - * 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. - * ============LICENSE_END========================================================= - */ -package org.onap.appc.adapter.chef.chefclient; - -import static org.junit.Assert.assertEquals; - -import java.util.Date; -import org.junit.Test; - -public class FormattedTimestampTest { - - @Test - public void format_shouldFormatGivenDate_withCorrectTimezoneSet() { - // GIVEN - String expectedFormattedDate = "1970-01-15T06:56:07Z"; - - // WHEN - String formattedDateWithTimezone = new FormattedTimestamp().format(new Date(1234567890)); - - // THEN - assertEquals(expectedFormattedDate, formattedDateWithTimezone); - } -} \ No newline at end of file diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiClientImplTest.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiClientImplTest.java new file mode 100644 index 000000000..21e607de7 --- /dev/null +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiClientImplTest.java @@ -0,0 +1,218 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ============================================================================= + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.appc.adapter.chef.chefclient.impl; + +import static junit.framework.TestCase.assertEquals; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.mock; + +import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.function.Supplier; +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.StatusLine; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.StringEntity; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentMatcher; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.appc.adapter.chef.chefclient.ChefApiClientFactory; +import org.onap.appc.adapter.chef.chefclient.api.ChefApiClient; +import org.onap.appc.adapter.chef.chefclient.api.ChefResponse; + +@RunWith(MockitoJUnitRunner.class) +public class ChefApiClientImplTest { + + private static final String END_POINT = "https://chefServer"; + private static final String ORGANIZATIONS_PATH = "onap"; + private static final String USER_ID = "testUser"; + private static final String REQUEST_PATH = "/test/path"; + private static final String BODY = "SOME BODY STRING"; + private static final ImmutableMap HEADERS = ImmutableMap.builder() + .put("Content-type", "application/json") + .put("Accept", "application/json") + .put("X-Ops-Timestamp", "1970-01-15T06:56:07Z") + .put("X-Ops-UserId", USER_ID) + .put("X-Chef-Version", "12.4.1") + .put("X-Ops-Content-Hash", BODY) + .put("X-Ops-Sign", "version=1.0").build(); + + @Mock + private HttpClient httpClient; + @Mock + private ChefApiHeaderFactory chefHttpHeaderFactory; + + @InjectMocks + private ChefApiClientFactory chefApiClientFactory; + private static final String PEM_FILEPATH = "path/to/pemFile"; + private ChefApiClient chefApiClient; + + @Before + public void setUp() { + chefApiClient = chefApiClientFactory.create( + END_POINT, + ORGANIZATIONS_PATH, + USER_ID, + PEM_FILEPATH); + } + + @Test + public void execute_HttpGet_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException { + // GIVEN + String methodName = "GET"; + String body = ""; + Supplier chefClientApiCall = () -> chefApiClient.get(REQUEST_PATH); + + // WHEN //THEN + assertChefApiClientCall(methodName, body, chefClientApiCall); + } + + @Test + public void execute_HttpDelete_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException { + // GIVEN + String methodName = "DELETE"; + String body = ""; + Supplier chefClientApiCall = () -> chefApiClient.delete(REQUEST_PATH); + + // WHEN //THEN + assertChefApiClientCall(methodName, body, chefClientApiCall); + } + + @Test + public void execute_HttpPost_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException { + // GIVEN + String methodName = "POST"; + Supplier chefClientApiCall = () -> chefApiClient.post(REQUEST_PATH, BODY); + + // WHEN //THEN + assertChefApiClientCall(methodName, BODY, chefClientApiCall); + } + + @Test + public void execute_HttpPut_shouldReturnResponseObject_whenRequestIsSuccessful() throws IOException { + // GIVEN + String methodName = "PUT"; + Supplier chefClientApiCall = () -> chefApiClient.put(REQUEST_PATH, BODY); + + // WHEN //THEN + assertChefApiClientCall(methodName, BODY, chefClientApiCall); + } + + private void assertChefApiClientCall(String methodName, String body, Supplier httpMethod) + throws IOException { + // GIVEN + given(chefHttpHeaderFactory.create(methodName, REQUEST_PATH, body, USER_ID, ORGANIZATIONS_PATH, PEM_FILEPATH)) + .willReturn(HEADERS); + + StatusLine statusLine = mock(StatusLine.class); + given(statusLine.getStatusCode()).willReturn(HttpStatus.SC_OK); + HttpResponse httpResponse = mock(HttpResponse.class); + given(httpResponse.getStatusLine()).willReturn(statusLine); + given(httpResponse.getEntity()).willReturn(new StringEntity("Successful Response String")); + given(httpClient.execute(argThat(new HttpRequestBaseMatcher(methodName)))) + .willReturn(httpResponse); + + // WHEN + ChefResponse chefResponse = httpMethod.get(); + + // THEN + assertEquals("Successful Response String", chefResponse.getBody()); + assertEquals(HttpStatus.SC_OK, chefResponse.getStatusCode()); + } + + @Test + public void execute_shouldHandleException_whenHttpClientExecutionFails() throws IOException { + + // GIVEN + given(chefHttpHeaderFactory.create("GET", REQUEST_PATH, "", USER_ID, ORGANIZATIONS_PATH, PEM_FILEPATH)) + .willReturn(HEADERS); + + String expectedErrorMsg = "HttpClient call failed"; + given(httpClient.execute(argThat(new HttpRequestBaseMatcher("GET")))) + .willThrow(new IOException(expectedErrorMsg)); + + // WHEN + ChefResponse chefResponse = chefApiClient.get(REQUEST_PATH); + + // THEN + assertEquals(expectedErrorMsg, chefResponse.getBody()); + assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, chefResponse.getStatusCode()); + } + + @Test + public void execute_shouldHandleException_whenEndpointURIisMalformed() { + // GIVEN + String expectedErrorMsg = "Malformed escape pair at index 1: /%#@/"; + + // WHEN + ChefApiClient chefApiClient = chefApiClientFactory.create( + "/%#@/", + ORGANIZATIONS_PATH, + USER_ID, + PEM_FILEPATH); + ChefResponse chefResponse = chefApiClient.get(REQUEST_PATH); + + // THEN + assertEquals(expectedErrorMsg, chefResponse.getBody()); + assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, chefResponse.getStatusCode()); + } + + private class HttpRequestBaseMatcher extends ArgumentMatcher { + + private final String methodName; + + public HttpRequestBaseMatcher(String methodName) { + this.methodName = methodName; + } + + @Override + public boolean matches(Object argument) { + HttpRequestBase httpRequestBase = (HttpRequestBase) argument; + + boolean headersMatch = checkIfHeadersMatch(httpRequestBase); + try { + return methodName.equals(httpRequestBase.getMethod()) + && new URI(END_POINT + REQUEST_PATH).equals(httpRequestBase.getURI()) + && headersMatch; + } catch (URISyntaxException e) { + e.printStackTrace(); + return false; + } + } + + private boolean checkIfHeadersMatch(HttpRequestBase httpRequestBase) { + Header[] generatedHeaders = httpRequestBase.getAllHeaders(); + return generatedHeaders.length > 0 + && generatedHeaders.length == HEADERS.size() + && HEADERS.entrySet().stream() + .allMatch(p -> httpRequestBase.getFirstHeader(p.getKey()).getValue().equals(p.getValue())); + } + } +} \ No newline at end of file diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiHeaderFactoryTest.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiHeaderFactoryTest.java new file mode 100644 index 000000000..4aece53a0 --- /dev/null +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/impl/ChefApiHeaderFactoryTest.java @@ -0,0 +1,83 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ============================================================================= + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.appc.adapter.chef.chefclient.impl; + +import static junit.framework.TestCase.assertEquals; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.any; + +import com.google.common.collect.ImmutableMap; +import java.util.Date; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ChefApiHeaderFactoryTest { + + private static final String ORGANIZATIONS_PATH = "onap"; + private static final String USER_ID = "testUser"; + private static final String REQUEST_PATH = "/test/path"; + private static final String EXPECTED_TIMESTAMP = "1970-01-15T06:56:07Z"; + private static final String EMPTY_BODY = ""; + + @Mock + private FormattedTimestamp formattedTimestamp; + + @InjectMocks + private ChefApiHeaderFactory chefApiHeaderFactory; + + @Test + public void create_shouldCreateProperChefHeaders_withHashedAuthorizationString() { + // GIVEN + given(formattedTimestamp.format(any(Date.class))).willReturn(EXPECTED_TIMESTAMP); + String pemFilePath = getClass().getResource("/testclient.pem").getPath(); + + // WHEN + ImmutableMap headers = chefApiHeaderFactory + .create("GET", REQUEST_PATH, "", USER_ID, ORGANIZATIONS_PATH, pemFilePath); + + // THEN + assertEquals(headers, createExpectedHeaders()); + } + + private ImmutableMap createExpectedHeaders() { + String hashedBody = Utils.sha1AndBase64(EMPTY_BODY); + ImmutableMap.Builder builder = ImmutableMap.builder(); + builder + .put("Content-type", "application/json") + .put("Accept", "application/json") + .put("X-Ops-Timestamp", EXPECTED_TIMESTAMP) + .put("X-Ops-UserId", USER_ID) + .put("X-Chef-Version", "12.4.1") + .put("X-Ops-Content-Hash", hashedBody) + .put("X-Ops-Sign", "version=1.0") + .put("X-Ops-Authorization-1", "i+HGCso703727yd2ZQWMZIIpGKgTzm41fA31LIExNxEf9mOUMcpesIHjH/Wr") + .put("X-Ops-Authorization-2", "QEvsX/Gy1ay9KsUtqhy9GA6PB8UfDeMNoVUisqR4HQW+S6IOfvqBjW+2afzE") + .put("X-Ops-Authorization-3", "RdRReB/TJIF3s6ZC8vNpbEdY9kHmwiDglhxmS8X2FS+ArSh/DK/i7MqBbjux") + .put("X-Ops-Authorization-4", "49iiOlRVG7aTr/FA115hlBYP9CYCIQWKIBUOK3JyV9fXNdVqc9R0r1XdjxUl") + .put("X-Ops-Authorization-5", "EDGw6tuE8YW8mH5wkgHCjKpXG3WjmWt2X6kUrdIu44qCBK2N3sZziSub2fJA") + .put("X-Ops-Authorization-6", "hPBuOhjiYDZuFUqC99lCryM0Hf5RMw1uTlkYsBEZmA=="); + + return builder.build(); + } +} \ No newline at end of file diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/impl/FormattedTimestampTest.java b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/impl/FormattedTimestampTest.java new file mode 100644 index 000000000..faaca6284 --- /dev/null +++ b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/java/org/onap/appc/adapter/chef/chefclient/impl/FormattedTimestampTest.java @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : APPC + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ============================================================================= + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.appc.adapter.chef.chefclient.impl; + +import static org.junit.Assert.assertEquals; + +import java.util.Date; +import org.junit.Test; + +public class FormattedTimestampTest { + + @Test + public void format_shouldFormatGivenDate_withCorrectTimezoneSet() { + // GIVEN + String expectedFormattedDate = "1970-01-15T06:56:07Z"; + + // WHEN + String formattedDateWithTimezone = new FormattedTimestamp().format(new Date(1234567890)); + + // THEN + assertEquals(expectedFormattedDate, formattedDateWithTimezone); + } +} \ No newline at end of file diff --git a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/resources/test.properties b/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/resources/test.properties deleted file mode 100644 index 09d42083a..000000000 --- a/appc-adapters/appc-chef-adapter/appc-chef-adapter-bundle/src/test/resources/test.properties +++ /dev/null @@ -1,26 +0,0 @@ -# ============LICENSE_START========================================== -# ONAP : APPC -# =================================================================== -# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. -# =================================================================== -# -# Unless otherwise specified, all software contained herein is licensed -# under the Apache License, Version 2.0 (the License); -# you may not use this software 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. -# -# ECOMP is a trademark and service mark of AT&T Intellectual Property. -# ============LICENSE_END============================================ -org.onap.appc.adapter.chef.chefclient.userId=test -org.onap.appc.adapter.chef.chefclient.pemPath=/src/test/resources/testclient.pem -org.onap.appc.adapter.chef.chefclient.endPoint=http://127.0.0.1 -org.onap.appc.adapter.chef.chefclient.organizations=onap -org.onap.appc.adapter.chef.chefclient.path=/test/path -- cgit 1.2.3-korg