Support SIP TLS
[sdc.git] / openecomp-be / api / openecomp-sdc-rest-webapp / vendor-software-products-rest / vnf-repository-rest-services / src / main / java / org / openecomp / sdcrests / vsp / rest / services / VnfPackageRepositoryImpl.java
1 /*
2  * Copyright 2017 Huawei Technologies Co., Ltd.
3  * Modifications Copyright 2018 European Support Limited
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package org.openecomp.sdcrests.vsp.rest.services;
18
19 import org.onap.config.api.ConfigurationManager;
20 import org.onap.config.api.JettySSLUtils;
21 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
22 import org.openecomp.sdc.common.errors.CoreException;
23 import org.openecomp.sdc.common.errors.ErrorCode;
24 import org.openecomp.sdc.common.errors.ErrorCodeAndMessage;
25 import org.openecomp.sdc.common.errors.GeneralErrorBuilder;
26 import org.openecomp.sdc.logging.api.Logger;
27 import org.openecomp.sdc.logging.api.LoggerFactory;
28 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager;
29 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManagerFactory;
30 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
31 import org.openecomp.sdc.vendorsoftwareproduct.types.OnboardPackageInfo;
32 import org.openecomp.sdc.vendorsoftwareproduct.types.UploadFileResponse;
33 import org.openecomp.sdc.versioning.VersioningManager;
34 import org.openecomp.sdc.versioning.VersioningManagerFactory;
35 import org.openecomp.sdc.versioning.dao.types.Version;
36 import org.openecomp.sdcrests.vendorsoftwareproducts.types.UploadFileResponseDto;
37 import org.openecomp.sdcrests.vsp.rest.VnfPackageRepository;
38 import org.openecomp.sdcrests.vsp.rest.mapping.MapUploadFileResponseToUploadFileResponseDto;
39 import org.springframework.context.annotation.Scope;
40 import org.springframework.stereotype.Service;
41
42 import javax.inject.Named;
43 import javax.ws.rs.client.Client;
44 import javax.ws.rs.client.ClientBuilder;
45 import javax.ws.rs.core.Response;
46 import java.nio.ByteBuffer;
47 import java.nio.charset.StandardCharsets;
48 import java.util.List;
49 import java.util.Objects;
50 import java.util.Optional;
51
52 import static javax.ws.rs.core.HttpHeaders.CONTENT_DISPOSITION;
53 import static org.openecomp.core.utilities.file.FileUtils.getFileExtension;
54 import static org.openecomp.core.utilities.file.FileUtils.getNetworkPackageName;
55
56 /**
57  * Enables integration API interface with VNF Repository (VNFSDK).
58  * <ol>
59  *     <li>Get all the VNF Package Meta-data.</li>
60  *     <li>Download a VNF Package.</li>
61  *     <li>Import a VNF package to SDC catalog (Download & validate).</li>
62  * </ol>
63  *
64  * @version Amsterdam release (ONAP 1.0)
65  */
66 @Named
67 @Service("vnfPackageRepository")
68 @Scope(value = "prototype")
69 public class VnfPackageRepositoryImpl implements VnfPackageRepository {
70
71     private static final Logger LOGGER = LoggerFactory.getLogger(VnfPackageRepositoryImpl.class);
72     private static final Client CLIENT = trustSSLClient();
73
74     private static Client trustSSLClient() {
75         try {
76             return ClientBuilder.newBuilder()
77                     .sslContext(JettySSLUtils.getSslContext())
78                     .hostnameVerifier((requestedHost, remoteServerSession) -> requestedHost.equalsIgnoreCase(remoteServerSession.getPeerHost())).build();
79         } catch (final Exception e) {
80             LOGGER.error("Failed to initialize SSL context", e);
81         }
82         return ClientBuilder.newClient();
83     }
84
85     private final Configuration config;
86
87     public VnfPackageRepositoryImpl(Configuration config) {
88         this.config = config;
89     }
90
91     public VnfPackageRepositoryImpl() {
92         this(new FileConfiguration());
93     }
94
95     @Override
96     public Response getVnfPackages(String vspId, String versionId, String user) {
97         LOGGER.debug("Get VNF Packages from Repository: {}", vspId);
98         final String getVnfPackageUri = config.getGetUri();
99         Response remoteResponse = CLIENT.target(getVnfPackageUri).request().get();
100         if (remoteResponse.getStatus() != Response.Status.OK.getStatusCode()) {
101             return handleUnexpectedStatus("querying VNF package metadata", getVnfPackageUri, remoteResponse);
102         }
103         LOGGER.debug("Response from VNF Repository: {}", remoteResponse);
104         return Response.ok(remoteResponse.readEntity(String.class)).build();
105     }
106
107     @Override
108     public Response importVnfPackage(String vspId, String versionId, String csarId, String user) {
109         LOGGER.debug("Import VNF Packages from Repository: {}", csarId);
110         final String downloadPackageUri = String.format(config.getDownloadUri(), csarId);
111         Response remoteResponse = CLIENT.target(downloadPackageUri).request().get();
112         if (remoteResponse.getStatus() != Response.Status.OK.getStatusCode()) {
113             return handleUnexpectedStatus("downloading VNF package", downloadPackageUri, remoteResponse);
114         }
115         LOGGER.debug("Response from VNF Repository for download package is success. URI={}", downloadPackageUri);
116         byte[] payload = remoteResponse.readEntity(String.class).getBytes(StandardCharsets.ISO_8859_1);
117         return uploadVnfPackage(vspId, versionId, csarId, payload);
118     }
119
120     private Response uploadVnfPackage(final String vspId, final String versionId, final String csarId, final byte[] payload) {
121         try {
122             final OrchestrationTemplateCandidateManager candidateManager = OrchestrationTemplateCandidateManagerFactory.getInstance()
123                     .createInterface();
124             final String filename = formatFilename(csarId);
125             final String fileExtension = getFileExtension(filename);
126             final OnboardPackageInfo onboardPackageInfo = new OnboardPackageInfo(getNetworkPackageName(filename), fileExtension,
127                     ByteBuffer.wrap(payload), OnboardingTypesEnum.getOnboardingTypesEnum(fileExtension));
128             final VspDetails vspDetails = new VspDetails(vspId, getVersion(vspId, versionId));
129             final UploadFileResponse response = candidateManager.upload(vspDetails, onboardPackageInfo);
130             final UploadFileResponseDto uploadFileResponse = new MapUploadFileResponseToUploadFileResponseDto()
131                     .applyMapping(response, UploadFileResponseDto.class);
132             return Response.ok(uploadFileResponse).build();
133         } catch (final Exception e) {
134             ErrorCode error = new GeneralErrorBuilder().build();
135             LOGGER.error("Exception while uploading package received from VNF Repository", new CoreException(error, e));
136             return generateInternalServerError(error);
137         }
138     }
139
140     @Override
141     public Response downloadVnfPackage(String vspId, String versionId, String csarId, String user) {
142         LOGGER.debug("Download VNF package from repository: csarId={}", csarId);
143         final String downloadPackageUri = String.format(config.getDownloadUri(), csarId);
144         Response remoteResponse = CLIENT.target(downloadPackageUri).request().get();
145         if (remoteResponse.getStatus() != Response.Status.OK.getStatusCode()) {
146             return handleUnexpectedStatus("downloading VNF package", downloadPackageUri, remoteResponse);
147         }
148         byte[] payload = remoteResponse.readEntity(String.class).getBytes(StandardCharsets.ISO_8859_1);
149         Response.ResponseBuilder response = Response.ok(payload);
150         response.header(CONTENT_DISPOSITION, "attachment; filename=" + formatFilename(csarId));
151         LOGGER.debug("Response from VNF Repository for download package is success. URI={}", downloadPackageUri);
152         return response.build();
153     }
154
155     private Version getVersion(String vspId, String versionId) {
156         VersioningManager versioningManager = VersioningManagerFactory.getInstance().createInterface();
157         return findVersion(versioningManager.list(vspId), versionId).orElse(new Version(versionId));
158     }
159
160     Optional<Version> findVersion(List<Version> versions, String requestedVersion) {
161         return versions.stream().filter(ver -> Objects.equals(ver.getId(), requestedVersion)).findAny();
162     }
163
164     private static Response handleUnexpectedStatus(String action, String uri, Response response) {
165         ErrorCode error = new GeneralErrorBuilder().build();
166         if (LOGGER.isErrorEnabled()) {
167             String body = response.hasEntity() ? response.readEntity(String.class) : "";
168             LOGGER.error("Unexpected response status while {}: URI={}, status={}, body={}", action, uri, response.getStatus(), body,
169                     new CoreException(error));
170         }
171         return generateInternalServerError(error);
172     }
173
174     private static Response generateInternalServerError(ErrorCode error) {
175         ErrorCodeAndMessage payload = new ErrorCodeAndMessage(Response.Status.INTERNAL_SERVER_ERROR, error);
176         return Response.serverError().entity(payload).build();
177     }
178
179     private static String formatFilename(String csarId) {
180         return "temp_" + csarId + ".csar";
181     }
182
183     interface Configuration {
184
185         String getGetUri();
186
187         String getDownloadUri();
188     }
189
190     static class FileConfiguration implements Configuration {
191
192         @Override
193         public String getGetUri() {
194             return LazyFileConfiguration.INSTANCE.getGetUri();
195         }
196
197         @Override
198         public String getDownloadUri() {
199             return LazyFileConfiguration.INSTANCE.getDownloadUri();
200         }
201
202         private static class LazyFileConfiguration implements Configuration {
203
204             private static final String CONFIG_NAMESPACE = "vnfrepo";
205             private static final String DEFAULT_HOST = "localhost";
206             private static final String DEFAULT_PORT = "8702";
207             private static final String DEFAULT_URI_PREFIX = "/onapapi/vnfsdk-marketplace/v1/PackageResource/csars";
208             private static final String DEFAULT_LIST_URI = DEFAULT_URI_PREFIX + "/";
209             private static final String DEFAULT_DOWNLOAD_URI = DEFAULT_URI_PREFIX + "/%s/files";
210             private static final LazyFileConfiguration INSTANCE = new LazyFileConfiguration();
211             private final String getUri;
212             private final String downloadUri;
213
214             private LazyFileConfiguration() {
215                 org.onap.config.api.Configuration config = ConfigurationManager.lookup();
216                 String host = readConfig(config, "vnfRepoHost", DEFAULT_HOST);
217                 String port = readConfig(config, "vnfRepoPort", DEFAULT_PORT);
218                 String listPackagesUri = readConfig(config, "getVnfUri", DEFAULT_LIST_URI);
219                 String downloadPackageUri = readConfig(config, "downloadVnfUri", DEFAULT_DOWNLOAD_URI);
220                 this.getUri = formatUri(host, port, listPackagesUri);
221                 this.downloadUri = formatUri(host, port, downloadPackageUri);
222             }
223
224             private String readConfig(org.onap.config.api.Configuration config, String key, String defaultValue) {
225                 try {
226                     String value = config.getAsString(CONFIG_NAMESPACE, key);
227                     return (value == null) ? defaultValue : value;
228                 } catch (Exception e) {
229                     LOGGER.error("Failed to read VNF repository configuration key '{}', default value '{}' will be used", key, defaultValue, e);
230                     return defaultValue;
231                 }
232             }
233
234             private static String formatUri(String host, String port, String path) {
235                 return "https://" + host + ":" + port + (path.startsWith("/") ? path : "/" + path);
236             }
237
238             public String getGetUri() {
239                 return getUri;
240             }
241
242             public String getDownloadUri() {
243                 return downloadUri;
244             }
245         }
246     }
247 }