Fixing XML parsers security bug
[so.git] / adapters / mso-openstack-adapters / src / main / java / org / onap / so / adapters / tasks / orchestration / StackService.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Modifications Copyright (c) 2019 Samsung
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.so.adapters.tasks.orchestration;
24
25 import java.io.ByteArrayInputStream;
26 import java.io.StringReader;
27 import java.nio.charset.StandardCharsets;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Optional;
32 import javax.xml.XMLConstants;
33 import javax.xml.bind.JAXB;
34 import javax.xml.parsers.DocumentBuilder;
35 import javax.xml.parsers.DocumentBuilderFactory;
36 import javax.xml.ws.Holder;
37 import org.apache.commons.lang3.StringUtils;
38 import org.apache.commons.lang3.mutable.MutableBoolean;
39 import org.camunda.bpm.client.task.ExternalTask;
40 import org.camunda.bpm.client.task.ExternalTaskService;
41 import org.onap.so.adapters.network.MsoNetworkAdapterImpl;
42 import org.onap.so.adapters.network.exceptions.NetworkException;
43 import org.onap.so.adapters.nwrest.ContrailNetwork;
44 import org.onap.so.adapters.nwrest.CreateNetworkRequest;
45 import org.onap.so.adapters.nwrest.DeleteNetworkRequest;
46 import org.onap.so.adapters.nwrest.ProviderVlanNetwork;
47 import org.onap.so.adapters.nwrest.RollbackNetworkRequest;
48 import org.onap.so.adapters.nwrest.UpdateNetworkRequest;
49 import org.onap.so.adapters.vnf.MsoVnfAdapterImpl;
50 import org.onap.so.adapters.vnf.MsoVnfPluginAdapterImpl;
51 import org.onap.so.adapters.vnf.VnfAdapterUtils;
52 import org.onap.so.adapters.vnf.exceptions.VnfException;
53 import org.onap.so.adapters.vnfrest.CreateVfModuleRequest;
54 import org.onap.so.adapters.vnfrest.CreateVolumeGroupRequest;
55 import org.onap.so.adapters.vnfrest.DeleteVfModuleRequest;
56 import org.onap.so.adapters.vnfrest.DeleteVolumeGroupRequest;
57 import org.onap.so.logging.tasks.AuditMDCSetup;
58 import org.onap.so.openstack.beans.NetworkRollback;
59 import org.onap.so.openstack.beans.RouteTarget;
60 import org.onap.so.utils.ExternalTaskUtils;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63 import org.springframework.beans.factory.annotation.Autowired;
64 import org.springframework.stereotype.Component;
65 import org.w3c.dom.Document;
66
67 @Component
68 public class StackService extends ExternalTaskUtils {
69
70     private static final Logger logger = LoggerFactory.getLogger(StackService.class);
71
72     @Autowired
73     private MsoVnfAdapterImpl vnfAdapterImpl;
74
75     @Autowired
76     private MsoNetworkAdapterImpl networkAdapterImpl;
77
78     @Autowired
79     private MsoVnfPluginAdapterImpl vnfPluginImpl;
80
81     @Autowired
82     private VnfAdapterUtils vnfAdapterUtils;
83
84     @Autowired
85     private AuditMDCSetup mdcSetup;
86
87     private static final String SHARED = "shared";
88     private static final String EXTERNAL = "external";
89
90     public void executeExternalTask(ExternalTask externalTask, ExternalTaskService externalTaskService) {
91         Map<String, Object> variables = new HashMap<>();
92         mdcSetup.setupMDC(externalTask);
93         String xmlRequest = externalTask.getVariable("openstackAdapterTaskRequest");
94         logger.debug("Starting External Task Stack Service. {}", xmlRequest);
95         MutableBoolean success = new MutableBoolean();
96         MutableBoolean backout = new MutableBoolean();
97         MutableBoolean os3Nw = new MutableBoolean();
98         Holder<String> canonicalStackId = new Holder<>();
99         String errorMessage = "";
100         try {
101             if (xmlRequest != null) {
102                 Optional<String> requestType = findRequestType(xmlRequest);
103                 if ("createVolumeGroupRequest".equals(requestType.get())) {
104                     logger.debug("Executing External Task Stack Service For Create Volume Group");
105                     createVolumeGroup(xmlRequest, canonicalStackId, backout, success);
106                 } else if ("createVfModuleRequest".equals(requestType.get())) {
107                     logger.debug("Executing External Task Stack Service For Create Vf Module");
108                     createVfModule(xmlRequest, canonicalStackId, backout, success);
109                 } else if ("deleteVfModuleRequest".equals(requestType.get())) {
110                     logger.debug("Executing External Task Stack Service For Delete Vf Module");
111                     deleteVfModule(xmlRequest, canonicalStackId, backout, success);
112                 } else if ("deleteVolumeGroupRequest".equals(requestType.get())) {
113                     logger.debug("Executing External Task Stack Service For Delete Volume Group");
114                     deleteVolumeGroup(xmlRequest, canonicalStackId, backout, success);
115                 } else if ("createNetworkRequest".equals(requestType.get())) {
116                     createNetwork(xmlRequest, canonicalStackId, backout, success, os3Nw);
117                 } else if ("deleteNetworkRequest".equals(requestType.get())) {
118                     deleteNetwork(xmlRequest, canonicalStackId, backout, success);
119                 } else if ("updateNetworkRequest".equals(requestType.get())) {
120                     updateNetwork(xmlRequest, canonicalStackId, backout, success);
121                 } else if ("rollbackNetworkRequest".equals(requestType.get())) {
122                     rollbackNetwork(xmlRequest, canonicalStackId, backout, success);
123                 }
124             }
125         } catch (Exception e) {
126             logger.error("Error during External Task Stack Service", e);
127             errorMessage = e.getMessage();
128         }
129         variables.put("backout", backout.booleanValue());
130         variables.put("OpenstackInvokeSuccess", success.booleanValue());
131         variables.put("stackId", canonicalStackId.value);
132         variables.put("openstackAdapterErrorMessage", errorMessage);
133         variables.put("PollRollbackStatus", false);
134         variables.put("rollbackPerformed", false);
135         variables.put("OpenstackRollbackSuccess", false);
136         variables.put("OpenstackPollSuccess", false);
137         variables.put("os3Nw", os3Nw.booleanValue());
138
139         if (success.isTrue()) {
140             externalTaskService.complete(externalTask, variables);
141             logger.debug("The External Task Id: {}  Successful", externalTask.getId());
142         } else {
143             logger.debug("The External Task Id: {}  Failed. Not Retrying", externalTask.getId());
144             externalTaskService.complete(externalTask, variables);
145         }
146     }
147
148     private void createVolumeGroup(String xmlRequest, Holder<String> canonicalStackId, MutableBoolean backout,
149             MutableBoolean success) throws VnfException {
150         CreateVolumeGroupRequest req = JAXB.unmarshal(new StringReader(xmlRequest), CreateVolumeGroupRequest.class);
151         String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
152         boolean isMulticloud = vnfAdapterUtils.isMulticloudMode(null, req.getCloudSiteId());
153         if (isMulticloud) {
154             vnfPluginImpl.createVfModule(req.getCloudSiteId(), req.getCloudOwner(), req.getTenantId(),
155                     completeVnfVfModuleType, req.getVnfVersion(), "", req.getVolumeGroupName(), "", "VOLUME", null,
156                     null, req.getModelCustomizationUuid(), req.getVolumeGroupParams(), false, true,
157                     req.getEnableBridge(), req.getMsoRequest(), canonicalStackId);
158         } else {
159             vnfAdapterImpl.createVfModule(req.getCloudSiteId(), req.getCloudOwner(), req.getTenantId(),
160                     completeVnfVfModuleType, req.getVnfVersion(), "", req.getVolumeGroupName(), "", "VOLUME", null,
161                     null, req.getModelCustomizationUuid(), req.getVolumeGroupParams(), false, true,
162                     req.getEnableBridge(), req.getMsoRequest(), canonicalStackId);
163         }
164         success.setTrue();
165         backout.setValue(!req.getSuppressBackout());
166     }
167
168     private void createVfModule(String xmlRequest, Holder<String> canonicalStackId, MutableBoolean backout,
169             MutableBoolean success) throws VnfException {
170         CreateVfModuleRequest req = JAXB.unmarshal(new StringReader(xmlRequest), CreateVfModuleRequest.class);
171         String completeVnfVfModuleType = req.getVnfType() + "::" + req.getVfModuleType();
172         boolean isMulticloud = vnfAdapterUtils.isMulticloudMode(null, req.getCloudSiteId());
173         if (isMulticloud) {
174             vnfPluginImpl.createVfModule(req.getCloudSiteId(), req.getCloudOwner(), req.getTenantId(),
175                     completeVnfVfModuleType, req.getVnfVersion(), req.getVnfId(), req.getVfModuleName(),
176                     req.getVfModuleId(), req.getRequestType(), req.getVolumeGroupStackId(),
177                     req.getBaseVfModuleStackId(), req.getModelCustomizationUuid(), req.getVfModuleParams(), false,
178                     false, req.getEnableBridge(), req.getMsoRequest(), canonicalStackId);
179         } else {
180             vnfAdapterImpl.createVfModule(req.getCloudSiteId(), req.getCloudOwner(), req.getTenantId(),
181                     completeVnfVfModuleType, req.getVnfVersion(), req.getVnfId(), req.getVfModuleName(),
182                     req.getVfModuleId(), req.getRequestType(), req.getVolumeGroupStackId(),
183                     req.getBaseVfModuleStackId(), req.getModelCustomizationUuid(), req.getVfModuleParams(), false,
184                     false, req.getEnableBridge(), req.getMsoRequest(), canonicalStackId);
185         }
186         success.setTrue();
187         backout.setValue(req.getBackout());
188     }
189
190     private void deleteVfModule(String xmlRequest, Holder<String> canonicalStackId, MutableBoolean backout,
191             MutableBoolean success) throws VnfException {
192         backout.setFalse();
193         Holder<Map<String, String>> outputs = new Holder<>();
194         DeleteVfModuleRequest req = JAXB.unmarshal(new StringReader(xmlRequest), DeleteVfModuleRequest.class);
195         boolean isMulticloud = vnfAdapterUtils.isMulticloudMode(null, req.getCloudSiteId());
196         if (isMulticloud) {
197             vnfPluginImpl.deleteVfModule(req.getCloudSiteId(), req.getCloudOwner(), req.getTenantId(),
198                     req.getVfModuleStackId(), req.getMsoRequest(), outputs);
199         } else {
200             vnfAdapterImpl.deleteVfModule(req.getCloudSiteId(), req.getCloudOwner(), req.getTenantId(),
201                     req.getVfModuleStackId(), req.getModelCustomizationUuid(), req.getMsoRequest(), outputs);
202         }
203         success.setTrue();
204         if (outputs != null && outputs.value != null) {
205             canonicalStackId.value = outputs.value.get("canonicalStackId");
206         } else {
207             canonicalStackId.value = req.getVfModuleStackId();
208         }
209     }
210
211     private void deleteVolumeGroup(String xmlRequest, Holder<String> canonicalStackId, MutableBoolean backout,
212             MutableBoolean success) throws VnfException {
213         backout.setFalse();
214         DeleteVolumeGroupRequest req = JAXB.unmarshal(new StringReader(xmlRequest), DeleteVolumeGroupRequest.class);
215         vnfAdapterImpl.deleteVfModule(req.getCloudSiteId(), req.getCloudOwner(), req.getTenantId(),
216                 req.getVolumeGroupStackId(), null, req.getMsoRequest(), new Holder<>());
217         success.setTrue();
218         canonicalStackId.value = req.getVolumeGroupStackId();
219     }
220
221     private void createNetwork(String xmlRequest, Holder<String> canonicalStackId, MutableBoolean backout,
222             MutableBoolean success, MutableBoolean os3) throws NetworkException {
223
224         CreateNetworkRequest req = JAXB.unmarshal(new StringReader(xmlRequest), CreateNetworkRequest.class);
225         HashMap<String, String> params = (HashMap<String, String>) req.getNetworkParams();
226         if (params == null) {
227             params = new HashMap<>();
228         }
229         String shared = null;
230         String external = null;
231         String physicalNetworkName = null;
232         List<Integer> vlans = null;
233         List<RouteTarget> routeTargets = null;
234         List<String> fqdns = null;
235         List<String> routeTable = null;
236         if (params.containsKey(SHARED))
237             shared = params.get(SHARED);
238         if (params.containsKey(EXTERNAL))
239             external = params.get(EXTERNAL);
240         if (req.isContrailRequest()) {
241             ContrailNetwork ctn = req.getContrailNetwork();
242             if (ctn == null) {
243                 ctn = new ContrailNetwork();
244                 req.setContrailNetwork(ctn);
245             }
246             if (shared == null && ctn.getShared() != null) {
247                 shared = ctn.getShared();
248             }
249             if (shared == null && ctn.getExternal() != null) {
250                 external = ctn.getExternal();
251             }
252             routeTargets = req.getContrailNetwork().getRouteTargets();
253             fqdns = req.getContrailNetwork().getPolicyFqdns();
254             routeTable = req.getContrailNetwork().getRouteTableFqdns();
255         } else {
256             ProviderVlanNetwork pvn = req.getProviderVlanNetwork();
257             if (pvn == null) {
258                 pvn = new ProviderVlanNetwork();
259                 req.setProviderVlanNetwork(pvn);
260             }
261             physicalNetworkName = req.getProviderVlanNetwork().getPhysicalNetworkName();
262             vlans = req.getProviderVlanNetwork().getVlans();
263         }
264         networkAdapterImpl.createNetwork(req.getCloudSiteId(), req.getTenantId(), req.getNetworkType(),
265                 req.getModelCustomizationUuid(), req.getNetworkName(), physicalNetworkName, vlans, routeTargets, shared,
266                 external, req.getFailIfExists(), false, req.getSubnets(), fqdns, routeTable, req.getMsoRequest(),
267                 canonicalStackId, os3);
268         success.setTrue();
269         backout.setValue(req.getBackout());
270     }
271
272     private void deleteNetwork(String xmlRequest, Holder<String> canonicalStackId, MutableBoolean backout,
273             MutableBoolean success) throws NetworkException {
274         backout.setFalse();
275         DeleteNetworkRequest req = JAXB.unmarshal(new StringReader(xmlRequest), DeleteNetworkRequest.class);
276
277         networkAdapterImpl.deleteNetwork(req.getCloudSiteId(), req.getTenantId(), req.getNetworkType(),
278                 req.getModelCustomizationUuid(), req.getNetworkStackId(), req.getMsoRequest());
279
280         canonicalStackId.value = req.getNetworkStackId();
281         success.setTrue();
282     }
283
284     private void rollbackNetwork(String xmlRequest, Holder<String> canonicalStackId, MutableBoolean backout,
285             MutableBoolean success) throws NetworkException {
286         backout.setFalse();
287         RollbackNetworkRequest req = JAXB.unmarshal(new StringReader(xmlRequest), RollbackNetworkRequest.class);
288
289         NetworkRollback rollback = req.getNetworkRollback();
290         networkAdapterImpl.rollbackNetwork(rollback);
291
292         canonicalStackId.value = rollback.getNetworkStackId();
293         success.setTrue();
294     }
295
296     private void updateNetwork(String xmlRequest, Holder<String> canonicalStackId, MutableBoolean backout,
297             MutableBoolean success) throws NetworkException {
298         backout.setFalse();
299         UpdateNetworkRequest req = JAXB.unmarshal(new StringReader(xmlRequest), UpdateNetworkRequest.class);
300         HashMap<String, String> params = (HashMap<String, String>) req.getNetworkParams();
301         if (params == null) {
302             params = new HashMap<>();
303         }
304         String shared = null;
305         String external = null;
306         String physicalNetworkName = null;
307         List<Integer> vlans = null;
308         List<RouteTarget> routeTargets = null;
309         List<String> fqdns = null;
310         List<String> routeTable = null;
311         if (params.containsKey(SHARED))
312             shared = params.get(SHARED);
313         if (params.containsKey(EXTERNAL))
314             external = params.get(EXTERNAL);
315         if (req.isContrailRequest()) {
316             ContrailNetwork ctn = req.getContrailNetwork();
317             if (ctn == null) {
318                 ctn = new ContrailNetwork();
319                 req.setContrailNetwork(ctn);
320             }
321             if (shared == null && ctn.getShared() != null) {
322                 shared = ctn.getShared();
323             }
324             if (shared == null && ctn.getExternal() != null) {
325                 external = ctn.getExternal();
326             }
327             routeTargets = req.getContrailNetwork().getRouteTargets();
328             fqdns = req.getContrailNetwork().getPolicyFqdns();
329             routeTable = req.getContrailNetwork().getRouteTableFqdns();
330         } else {
331             ProviderVlanNetwork pvn = req.getProviderVlanNetwork();
332             if (pvn == null) {
333                 pvn = new ProviderVlanNetwork();
334                 req.setProviderVlanNetwork(pvn);
335             }
336             physicalNetworkName = req.getProviderVlanNetwork().getPhysicalNetworkName();
337             vlans = req.getProviderVlanNetwork().getVlans();
338         }
339
340         networkAdapterImpl.updateNetwork(req.getCloudSiteId(), req.getTenantId(), req.getNetworkType(),
341                 req.getModelCustomizationUuid(), req.getNetworkStackId(), req.getNetworkName(), physicalNetworkName,
342                 vlans, routeTargets, shared, external, req.getSubnets(), fqdns, routeTable, req.getMsoRequest(),
343                 canonicalStackId);
344
345         success.setTrue();
346
347     }
348
349     protected Optional<String> findRequestType(final String xmlString) {
350         try {
351             final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
352             factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, StringUtils.EMPTY);
353             factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, StringUtils.EMPTY);
354
355             final DocumentBuilder builder = factory.newDocumentBuilder();
356             final Document doc = builder.parse(new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8)));
357             return Optional.of(doc.getDocumentElement().getNodeName());
358         } catch (final Exception e) {
359             logger.error("Error Finding Request Type", e);
360             return Optional.empty();
361         }
362     }
363 }