diff options
author | Edwin Lawrance <Edwin.Lawrance@amdocs.com> | 2017-09-22 16:55:07 +0100 |
---|---|---|
committer | Edwin Lawrance <Edwin.Lawrance@amdocs.com> | 2017-10-05 11:36:10 +0100 |
commit | 1433a67a9e3dcad20d0dda8edcaad9403320f4f9 (patch) | |
tree | 91dc94ca6acb183f5c87e3e141f678e1f06b6945 /src/main/java/org/onap | |
parent | 5f3bae5a14b3167d43c3bedf83446cbf5269d5c2 (diff) |
Initial code submit for Babel
Change-Id: I3738ebe15eadbbd6d16e24e374c6e40c535b425d
Issue-ID: AAI-46
Signed-off-by: Edwin Lawrance <Edwin.Lawrance@amdocs.com>
Diffstat (limited to 'src/main/java/org/onap')
19 files changed, 1560 insertions, 0 deletions
diff --git a/src/main/java/org/onap/aai/auth/AAIAuthException.java b/src/main/java/org/onap/aai/auth/AAIAuthException.java new file mode 100644 index 0000000..13593ab --- /dev/null +++ b/src/main/java/org/onap/aai/auth/AAIAuthException.java @@ -0,0 +1,39 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.auth; + +public class AAIAuthException extends Exception { + /** + * + */ + private static final long serialVersionUID = 1L; + + public AAIAuthException(String string) { + super(string); + } + + public AAIAuthException(String string, Exception e) { + super(string, e); + } + +} diff --git a/src/main/java/org/onap/aai/auth/AAIMicroServiceAuth.java b/src/main/java/org/onap/aai/auth/AAIMicroServiceAuth.java new file mode 100644 index 0000000..f678498 --- /dev/null +++ b/src/main/java/org/onap/aai/auth/AAIMicroServiceAuth.java @@ -0,0 +1,121 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.auth; + +import java.security.cert.X509Certificate; +import javax.inject.Inject; +import javax.security.auth.x500.X500Principal; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.HttpHeaders; +import org.onap.aai.babel.config.BabelAuthConfig; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; + + +/** + * Public class for authentication and authorization operations. Authorization is applied according to user and role + */ +public class AAIMicroServiceAuth { + + private static Logger applicationLogger = LoggerFactory.getInstance().getLogger(AAIMicroServiceAuth.class); + + private BabelAuthConfig babelAuthConfig; + + /** + * @param babelAuthConfig + * @throws AAIAuthException + */ + @Inject + public AAIMicroServiceAuth(final BabelAuthConfig babelAuthConfig) throws AAIAuthException { + this.babelAuthConfig = babelAuthConfig; + if (!babelAuthConfig.isAuthenticationDisable()) { + AAIMicroServiceAuthCore.init(babelAuthConfig.getAuthPolicyFile()); + } + } + + /** + * @param username + * @param policyFunction + * @return + * @throws AAIAuthException + */ + public boolean authorize(String username, String policyFunction) throws AAIAuthException { + return AAIMicroServiceAuthCore.authorize(username, policyFunction); + } + + /** + * @param authUser + * @param policyFunction + * @return + * @throws AAIAuthException + */ + public String authenticate(String authUser, String policyFunction) throws AAIAuthException { + if (authorize(authUser, policyFunction)) { + return "OK"; + } else { + return "AAI_9101"; + } + } + + /** + * @param headers + * @param req + * @param action + * @param apiPath + * @return + * @throws AAIAuthException + */ + public boolean validateRequest(HttpHeaders headers /* NOSONAR */, HttpServletRequest req, + AAIMicroServiceAuthCore.HTTP_METHODS action, String apiPath) throws AAIAuthException { + + applicationLogger.debug("validateRequest: " + apiPath); + applicationLogger + .debug("babelAuthConfig.isAuthenticationDisable(): " + babelAuthConfig.isAuthenticationDisable()); + + if (babelAuthConfig.isAuthenticationDisable()) { + return true; + } + + String[] ps = apiPath.split("/"); + String authPolicyFunctionName = ps[0]; + if (ps.length > 1 && authPolicyFunctionName.matches("v\\d+")) { + authPolicyFunctionName = ps[1]; + } + + String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite"); + String authUser = null; + + if (cipherSuite != null) { + X509Certificate[] certChain = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate"); + X509Certificate clientCert = certChain[0]; + X500Principal subjectDN = clientCert.getSubjectX500Principal(); + authUser = subjectDN.toString(); + } + + if (authUser != null) { + return "OK".equals(authenticate(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName)); + } else { + return false; + } + } +} diff --git a/src/main/java/org/onap/aai/auth/AAIMicroServiceAuthCore.java b/src/main/java/org/onap/aai/auth/AAIMicroServiceAuthCore.java new file mode 100644 index 0000000..b148440 --- /dev/null +++ b/src/main/java/org/onap/aai/auth/AAIMicroServiceAuthCore.java @@ -0,0 +1,287 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.auth; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; +import org.onap.aai.babel.logging.ApplicationMsgs; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; + +/** + * Authentication and authorization by user and role. + * + */ +public class AAIMicroServiceAuthCore { + + private static Logger applicationLogger = LoggerFactory.getInstance().getLogger(AAIMicroServiceAuthCore.class); + + public static final String FILESEP = + (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator"); + public static final String APPCONFIG_DIR = (System.getProperty("CONFIG_HOME") == null) + ? System.getProperty("AJSC_HOME") + FILESEP + "appconfig" : System.getProperty("CONFIG_HOME"); + + private static String appConfigAuthDir = APPCONFIG_DIR + FILESEP + "auth"; + private static String defaultAuthFileName = appConfigAuthDir + FILESEP + "auth_policy.json"; + + private static boolean usersInitialized = false; + private static HashMap<String, AAIAuthUser> users; + private static boolean timerSet = false; + private static Timer timer = null; + private static String policyAuthFileName; + + public enum HTTP_METHODS { + GET, + PUT, + DELETE, + HEAD, + POST + } + + // Don't instantiate + private AAIMicroServiceAuthCore() {} + + public static String getDefaultAuthFileName() { + return defaultAuthFileName; + } + + public static void setDefaultAuthFileName(String defaultAuthFileName) { + AAIMicroServiceAuthCore.defaultAuthFileName = defaultAuthFileName; + } + + public static synchronized void init(String authPolicyFile) throws AAIAuthException { + + try { + policyAuthFileName = AAIMicroServiceAuthCore.getConfigFile(authPolicyFile); + } catch (IOException e) { + applicationLogger.debug("Exception while retrieving policy file."); + applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e); + throw new AAIAuthException(e.getMessage()); + } + if (policyAuthFileName == null) { + throw new AAIAuthException("Auth policy file could not be found"); + } + AAIMicroServiceAuthCore.reloadUsers(); + + TimerTask task = new FileWatcher(new File(policyAuthFileName)) { + @Override + protected void onChange(File file) { + // here we implement the onChange + applicationLogger.debug("File " + file.getName() + " has been changed!"); + try { + AAIMicroServiceAuthCore.reloadUsers(); + } catch (AAIAuthException e) { + applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e); + } + applicationLogger.debug("File " + file.getName() + " has been reloaded!"); + } + }; + + if (!timerSet) { + timerSet = true; + timer = new Timer(); + long period = TimeUnit.SECONDS.toMillis(1); + timer.schedule(task, new Date(), period); + applicationLogger.debug("Config Watcher Interval = " + period); + } + } + + public static void cleanup() { + timer.cancel(); + } + + public static String getConfigFile(String authPolicyFile) throws IOException { + File authFile = new File(authPolicyFile); + if (authFile.exists()) { + return authFile.getCanonicalPath(); + } + authFile = new File(appConfigAuthDir + FILESEP + authPolicyFile); + if (authFile.exists()) { + return authFile.getCanonicalPath(); + } + if (defaultAuthFileName != null) { + authFile = new File(defaultAuthFileName); + if (authFile.exists()) { + return defaultAuthFileName; + } + } + return null; + } + + public static synchronized void reloadUsers() throws AAIAuthException { + users = new HashMap<>(); + + ObjectMapper mapper = new ObjectMapper(); + try { + applicationLogger.debug("Reading from " + policyAuthFileName); + JsonNode rootNode = mapper.readTree(new File(policyAuthFileName)); + for (JsonNode roleNode : rootNode.path("roles")) { + String roleName = roleNode.path("name").asText(); + AAIAuthRole r = new AAIAuthRole(); + installFunctionOnRole(roleNode.path("functions"), roleName, r); + assignRoleToUsers(roleNode.path("users"), roleName, r); + } + } catch (FileNotFoundException e) { + throw new AAIAuthException("Auth policy file could not be found", e); + } catch (JsonProcessingException e) { + throw new AAIAuthException("Error processing Auth policy file ", e); + } catch (IOException e) { + throw new AAIAuthException("Error reading Auth policy file", e); + } + + usersInitialized = true; + } + + private static void installFunctionOnRole(JsonNode functionsNode, String roleName, AAIAuthRole r) { + for (JsonNode functionNode : functionsNode) { + String function = functionNode.path("name").asText(); + JsonNode methodsNode = functionNode.path("methods"); + boolean hasMethods = false; + for (JsonNode method_node : methodsNode) { + String methodName = method_node.path("name").asText(); + hasMethods = true; + String func = methodName + ":" + function; + applicationLogger.debug("Installing function " + func + " on role " + roleName); + r.addAllowedFunction(func); + } + + if (!hasMethods) { + for (HTTP_METHODS meth : HTTP_METHODS.values()) { + String func = meth.toString() + ":" + function; + applicationLogger.debug("Installing (all methods) " + func + " on role " + roleName); + r.addAllowedFunction(func); + } + } + } + } + + private static void assignRoleToUsers(JsonNode usersNode, String roleName, AAIAuthRole r) { + for (JsonNode userNode : usersNode) { + String name = userNode.path("username").asText().toLowerCase(); + AAIAuthUser user; + if (users.containsKey(name)) { + user = users.get(name); + } else { + user = new AAIAuthUser(); + } + applicationLogger.debug("Assigning " + roleName + " to user " + name); + user.setUser(name); + user.addRole(roleName, r); + users.put(name, user); + } + } + + public static class AAIAuthUser { + private String username; + private HashMap<String, AAIAuthRole> roles; + + public AAIAuthUser() { + this.roles = new HashMap<>(); + } + + public String getUser() { + return this.username; + } + + public Map<String, AAIAuthRole> getRoles() { + return this.roles; + } + + public void addRole(String roleName, AAIAuthRole r) { + this.roles.put(roleName, r); + } + + public boolean checkAllowed(String checkFunc) { + for (Entry<String, AAIAuthRole> role_entry : roles.entrySet()) { + AAIAuthRole role = role_entry.getValue(); + if (role.hasAllowedFunction(checkFunc)) { + return true; + } + } + return false; + } + + public void setUser(String myuser) { + this.username = myuser; + } + + } + + public static class AAIAuthRole { + + private List<String> allowedFunctions; + + public AAIAuthRole() { + this.allowedFunctions = new ArrayList<>(); + } + + public void addAllowedFunction(String func) { + this.allowedFunctions.add(func); + } + + public void delAllowedFunction(String delFunc) { + if (this.allowedFunctions.contains(delFunc)) { + this.allowedFunctions.remove(delFunc); + } + } + + public boolean hasAllowedFunction(String afunc) { + return this.allowedFunctions.contains(afunc) ? true : false; + } + } + + public static boolean authorize(String username, String authFunction) throws AAIAuthException { + if (!usersInitialized || users == null) { + throw new AAIAuthException("Auth module not initialized"); + } + if (users.containsKey(username)) { + if (users.get(username).checkAllowed(authFunction)) { + logAuthenticationResult(username, authFunction, "AUTH ACCEPTED"); + return true; + } else { + logAuthenticationResult(username, authFunction, "AUTH FAILED"); + return false; + } + } else { + logAuthenticationResult(username, authFunction, "User not found"); + return false; + } + } + + private static void logAuthenticationResult(String username, String authFunction, String result) { + applicationLogger.debug(result + ": " + username + " on function " + authFunction); + } +} diff --git a/src/main/java/org/onap/aai/auth/FileWatcher.java b/src/main/java/org/onap/aai/auth/FileWatcher.java new file mode 100644 index 0000000..e3b9923 --- /dev/null +++ b/src/main/java/org/onap/aai/auth/FileWatcher.java @@ -0,0 +1,63 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.auth; + +import java.io.File; +import java.util.TimerTask; + +public abstract class FileWatcher extends TimerTask { + private long timeStamp; + private File file; + + /** + * Instantiates a new file watcher. + * + * @param file the file + */ + public FileWatcher(File file) { + this.file = file; + this.timeStamp = file.lastModified(); + } + + /** + * runs a timer task + * + * @see java.util.TimerTask.run + */ + @Override + public final void run() { + long newTimeStamp = file.lastModified(); + + if ((newTimeStamp - this.timeStamp) > 500) { + this.timeStamp = newTimeStamp; + onChange(file); + } + } + + /** + * On change. + * + * @param file the file + */ + protected abstract void onChange(File file); +} diff --git a/src/main/java/org/onap/aai/babel/config/BabelAuthConfig.java b/src/main/java/org/onap/aai/babel/config/BabelAuthConfig.java new file mode 100644 index 0000000..5fdc01f --- /dev/null +++ b/src/main/java/org/onap/aai/babel/config/BabelAuthConfig.java @@ -0,0 +1,51 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.config; + +import org.springframework.beans.factory.annotation.Value; + +public class BabelAuthConfig { + + @Value("${auth.authentication.disable}") + private boolean authenticationDisable; + + @Value("${auth.policy.file}") + private String authPolicyFile; + + public boolean isAuthenticationDisable() { + return authenticationDisable; + } + + public void setAuthenticationDisable(boolean authenticationDisable) { + this.authenticationDisable = authenticationDisable; + } + + public String getAuthPolicyFile() { + return authPolicyFile; + } + + public void setAuthPolicyFile(String authPolicyFile) { + this.authPolicyFile = authPolicyFile; + } + +} diff --git a/src/main/java/org/onap/aai/babel/csar/CsarConverterException.java b/src/main/java/org/onap/aai/babel/csar/CsarConverterException.java new file mode 100644 index 0000000..b9316fc --- /dev/null +++ b/src/main/java/org/onap/aai/babel/csar/CsarConverterException.java @@ -0,0 +1,40 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.csar; + +/** + * This class represents an exception encountered when attempting to convert the yml files in a csar archive into xml. + */ +public class CsarConverterException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Constructor for an instance of this exception with just a message. + * + * @param message information about the exception + */ + public CsarConverterException(String message) { + super(message); + } +} diff --git a/src/main/java/org/onap/aai/babel/csar/CsarToXmlConverter.java b/src/main/java/org/onap/aai/babel/csar/CsarToXmlConverter.java new file mode 100644 index 0000000..55cf652 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/csar/CsarToXmlConverter.java @@ -0,0 +1,88 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.csar; + +import java.util.List; +import java.util.Objects; +import org.onap.aai.babel.csar.extractor.InvalidArchiveException; +import org.onap.aai.babel.csar.extractor.YamlExtractor; +import org.onap.aai.babel.logging.ApplicationMsgs; +import org.onap.aai.babel.service.data.BabelArtifact; +import org.onap.aai.babel.xml.generator.XmlArtifactGenerationException; +import org.onap.aai.babel.xml.generator.ArtifactGenerator; +import org.onap.aai.babel.xml.generator.ModelGenerator; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; + +import org.openecomp.sdc.generator.data.Artifact; + +/** + * This class is responsible for converting content in a csar archive into one or more xml artifacts. + */ +public class CsarToXmlConverter { + private static Logger logger = LoggerFactory.getInstance().getLogger(CsarToXmlConverter.class); + + /** + * This method is responsible for extracting one or more yaml files from the given csarArtifact and then using them + * to generate xml artifacts. + * + * @param csarArchive the artifact that contains the csar archive to generate xml artifacts from + * @param name the name of the archive file + * @param version the version of the archive file + * @return List<org.openecomp.sdc.generator.data.Artifact> a list of generated xml artifacts + * @throws CsarConverterException if there is an error either extracting the yaml files or generating xml artifacts + */ + public List<BabelArtifact> generateXmlFromCsar(byte[] csarArchive, String name, String version) + throws CsarConverterException { + validateArguments(csarArchive, name, version); + + logger.info(ApplicationMsgs.DISTRIBUTION_EVENT, + "Starting to process csarArchive to convert contents to xml artifacts"); + List<BabelArtifact> xmlArtifacts; + + try { + logger.debug("Calling YamlExtractor to extract ymlFiles"); + List<Artifact> ymlFiles = YamlExtractor.extract(csarArchive, name, version); + + logger.debug("Calling XmlArtifactGenerator to generateXmlArtifacts"); + ArtifactGenerator modelGenerator = new ModelGenerator(); + xmlArtifacts = modelGenerator.generateArtifacts(ymlFiles); + + logger.debug(xmlArtifacts.size() + " xml artifacts have been generated"); + } catch (InvalidArchiveException e) { + throw new CsarConverterException( + "An error occurred trying to extract the yml files from the csar file : " + e); + } catch (XmlArtifactGenerationException e) { + throw new CsarConverterException( + "An error occurred trying to generate xml files from a collection of yml files : " + e); + } + + return xmlArtifacts; + } + + private void validateArguments(byte[] csarArchive, String name, String version) { + Objects.requireNonNull(csarArchive); + Objects.requireNonNull(name); + Objects.requireNonNull(version); + } +} diff --git a/src/main/java/org/onap/aai/babel/csar/extractor/InvalidArchiveException.java b/src/main/java/org/onap/aai/babel/csar/extractor/InvalidArchiveException.java new file mode 100644 index 0000000..aac893b --- /dev/null +++ b/src/main/java/org/onap/aai/babel/csar/extractor/InvalidArchiveException.java @@ -0,0 +1,50 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.csar.extractor; + +/** + * This class represents an exception encountered when processing an archive in memory. + */ +public class InvalidArchiveException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Constructor for an instance of this exception with just a message. + * + * @param message information about the exception + */ + InvalidArchiveException(String message) { + super(message); + } + + /** + * Constructor for an instance of this exception with a message and actual exception encountered. + * + * @param message information about the exception + * @param cause the actual exception that was encountered + */ + InvalidArchiveException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/aai/babel/csar/extractor/YamlExtractor.java b/src/main/java/org/onap/aai/babel/csar/extractor/YamlExtractor.java new file mode 100644 index 0000000..fb51933 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/csar/extractor/YamlExtractor.java @@ -0,0 +1,149 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.csar.extractor; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipFile; +import org.apache.commons.compress.utils.SeekableInMemoryByteChannel; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.onap.aai.babel.logging.ApplicationMsgs; +import org.onap.aai.babel.xml.generator.ModelGenerator; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.openecomp.sdc.generator.data.Artifact; +import org.yaml.snakeyaml.Yaml; + +/** + * The purpose of this class is to process a .csar file in the form of a byte array and extract yaml files from it. + * + * A .csar file is a compressed archive like a zip file and this class will treat the byte array as it if were a zip + * file. + */ +public class YamlExtractor { + private static Logger logger = LoggerFactory.getInstance().getLogger(YamlExtractor.class); + + private static final String TYPE = "type"; + private static final Pattern YAMLFILE_EXTENSION_REGEX = Pattern.compile("(?i).*\\.ya?ml$"); + private static final Set<String> INVALID_TYPES = new HashSet<>(); + + static { + Collections.addAll(INVALID_TYPES, "CP", "VL", "VFC", "VFCMT", "ABSTRACT"); + } + + /** + * Private constructor + */ + private YamlExtractor() { + throw new IllegalAccessError("Utility class"); + } + + /** + * This method is responsible for filtering the contents of the supplied archive and returning a collection of + * {@link Artifact}s that represent the yml files that have been found in the archive.<br> + * <br> + * If the archive contains no yml files it will return an empty list.<br> + * + * @param archive the zip file in the form of a byte array containing one or more yml files + * @param name the name of the archive file + * @param version the version of the archive file + * @return List<Artifact> collection of yml files found in the archive + * @throws InvalidArchiveException if an error occurs trying to extract the yml files from the archive, if the + * archive is not a zip file or there are no yml files + */ + public static List<Artifact> extract(byte[] archive, String name, String version) throws InvalidArchiveException { + validateRequest(archive, name, version); + + logger.info(ApplicationMsgs.DISTRIBUTION_EVENT, "Extracting CSAR archive: " + name); + + List<Artifact> ymlFiles = new ArrayList<>(); + try (SeekableInMemoryByteChannel inMemoryByteChannel = new SeekableInMemoryByteChannel(archive); + ZipFile zipFile = new ZipFile(inMemoryByteChannel)) { + for (Enumeration<ZipArchiveEntry> enumeration = zipFile.getEntries(); enumeration.hasMoreElements();) { + ZipArchiveEntry entry = enumeration.nextElement(); + if (fileShouldBeExtracted(zipFile, entry)) { + ymlFiles.add(ModelGenerator.createArtifact(IOUtils.toByteArray(zipFile.getInputStream(entry)), + entry.getName(), version)); + } + } + if (ymlFiles.isEmpty()) { + throw new InvalidArchiveException("No valid yml files were found in the csar file."); + } + } catch (IOException e) { + throw new InvalidArchiveException( + "An error occurred trying to create a ZipFile. Is the content being converted really a csar file?", + e); + } + + logger.debug(ApplicationMsgs.DISTRIBUTION_EVENT, ymlFiles.size() + " YAML files extracted."); + + return ymlFiles; + } + + private static void validateRequest(byte[] archive, String name, String version) throws InvalidArchiveException { + if (archive == null || archive.length == 0) { + throw new InvalidArchiveException("An archive must be supplied for processing."); + } else if (StringUtils.isBlank(name)) { + throw new InvalidArchiveException("The name of the archive must be supplied for processing."); + } else if (StringUtils.isBlank(version)) { + throw new InvalidArchiveException("The version must be supplied for processing."); + } + } + + @SuppressWarnings("unchecked") + private static boolean fileShouldBeExtracted(ZipFile zipFile, ZipArchiveEntry entry) throws IOException { + logger.debug(ApplicationMsgs.DISTRIBUTION_EVENT, "Checking if " + entry.getName() + " should be extracted..."); + + boolean extractFile = false; + if (YAMLFILE_EXTENSION_REGEX.matcher(entry.getName()).matches()) { + try { + Yaml yamlParser = new Yaml(); + HashMap<String, Object> yaml = + (LinkedHashMap<String, Object>) yamlParser.load(zipFile.getInputStream(entry)); + HashMap<String, Object> metadata = (LinkedHashMap<String, Object>) yaml.get("metadata"); + + extractFile = metadata != null && metadata.containsKey(TYPE) + && !INVALID_TYPES.contains(metadata.get(TYPE).toString().toUpperCase()) + && !metadata.get(TYPE).toString().isEmpty(); + } catch (Exception e) { + logger.error(ApplicationMsgs.DISTRIBUTION_EVENT, + "Unable to verify " + entry.getName() + " contains a valid resource type: " + e.getMessage()); + } + } + + logger.debug(ApplicationMsgs.DISTRIBUTION_EVENT, "Keeping file: " + entry.getName() + "? : " + extractFile); + + return extractFile; + } +} + diff --git a/src/main/java/org/onap/aai/babel/logging/ApplicationMsgs.java b/src/main/java/org/onap/aai/babel/logging/ApplicationMsgs.java new file mode 100644 index 0000000..9b9f9d5 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/logging/ApplicationMsgs.java @@ -0,0 +1,50 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.logging; + +import com.att.eelf.i18n.EELFResourceManager; +import org.onap.aai.cl.eelf.LogMessageEnum; + +public enum ApplicationMsgs implements LogMessageEnum { + //@formatter:off + /** + * Arguments: {0} = message. + */ + DISTRIBUTION_EVENT, + + PROCESS_REQUEST_ERROR, + + INVALID_CSAR_FILE, + + INVALID_REQUEST_JSON; + + //@formatter:on + + /** + * Static initializer to ensure the resource bundles for this class are loaded... Here this application loads + * messages from three bundles + */ + static { + EELFResourceManager.loadMessageBundle("babel-logging-resources"); + } +} diff --git a/src/main/java/org/onap/aai/babel/service/GenerateArtifactsService.java b/src/main/java/org/onap/aai/babel/service/GenerateArtifactsService.java new file mode 100644 index 0000000..bb7b721 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/service/GenerateArtifactsService.java @@ -0,0 +1,51 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.service; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import org.onap.aai.auth.AAIAuthException; + +/** + * Generate artifacts from the specified request content + */ +@Path("/") +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +public interface GenerateArtifactsService { + + @POST + @Path("/generateArtifacts") + Response generateArtifacts(@Context UriInfo uriInfo, @Context HttpHeaders headers, + @Context HttpServletRequest servletRequest, String request) throws AAIAuthException; + + +} diff --git a/src/main/java/org/onap/aai/babel/service/GenerateArtifactsServiceImpl.java b/src/main/java/org/onap/aai/babel/service/GenerateArtifactsServiceImpl.java new file mode 100644 index 0000000..bdb45b5 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/service/GenerateArtifactsServiceImpl.java @@ -0,0 +1,148 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.service; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonSyntaxException; +import java.util.Base64; +import java.util.List; +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; +import org.onap.aai.auth.AAIAuthException; +import org.onap.aai.auth.AAIMicroServiceAuth; +import org.onap.aai.auth.AAIMicroServiceAuthCore; +import org.onap.aai.babel.csar.CsarConverterException; +import org.onap.aai.babel.csar.CsarToXmlConverter; +import org.onap.aai.babel.logging.ApplicationMsgs; +import org.onap.aai.babel.service.data.BabelArtifact; +import org.onap.aai.babel.service.data.BabelRequest; +import org.onap.aai.babel.util.RequestValidationException; +import org.onap.aai.babel.util.RequestValidator; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; + + +/** + * Generate SDC Artifacts by passing in a CSAR payload, Artifact Name and Artifact version + */ +public class GenerateArtifactsServiceImpl implements GenerateArtifactsService { + private static Logger applicationLogger = LoggerFactory.getInstance().getLogger(GenerateArtifactsServiceImpl.class); + + private AAIMicroServiceAuth aaiMicroServiceAuth; + + /** + * @param authorization + */ + @Inject + public GenerateArtifactsServiceImpl(final AAIMicroServiceAuth authorization) { + this.aaiMicroServiceAuth = authorization; + } + + /* + * (non-Javadoc) + * + * @see org.onap.aai.babel.service.GenerateArtifactsService#generateArtifacts(javax.ws.rs.core.UriInfo, + * javax.ws.rs.core.HttpHeaders, javax.servlet.http.HttpServletRequest, java.lang.String) + */ + @Override + public Response generateArtifacts(UriInfo uriInfo, HttpHeaders headers, HttpServletRequest servletRequest, + String requestBody) throws AAIAuthException { + applicationLogger.debug("Received request: " + requestBody); + + Response response; + try { + boolean authorized = aaiMicroServiceAuth.validateRequest(headers, servletRequest, + AAIMicroServiceAuthCore.HTTP_METHODS.POST, uriInfo.getPath(false)); + + response = authorized ? generateArtifacts(requestBody) + : buildResponse(Status.UNAUTHORIZED, "User not authorized to perform the operation."); + } catch (AAIAuthException e) { + applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e); + throw e; + } + + applicationLogger.debug("Sending response: " + response.getStatus() + " " + response.getEntity().toString()); + return response; + } + + + /** + * Generate XML model artifacts from request body. + * + * @param requestBody the request body in JSON format + * @return response object containing the generated XML models + */ + protected Response generateArtifacts(String requestBody) { + Response response; + + try { + Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + + BabelRequest babelRequest = gson.fromJson(requestBody, BabelRequest.class); + RequestValidator.validateRequest(babelRequest); + byte[] csarFile = Base64.getDecoder().decode(babelRequest.getCsar()); + List<BabelArtifact> xmlArtifacts = new CsarToXmlConverter().generateXmlFromCsar(csarFile, + babelRequest.getArtifactName(), babelRequest.getArtifactVersion()); + response = buildResponse(Status.OK, gson.toJson(xmlArtifacts)); + + } catch (JsonSyntaxException e) { + applicationLogger.error(ApplicationMsgs.INVALID_REQUEST_JSON, e); + response = buildResponse(Status.BAD_REQUEST, "Malformed request."); + } catch (CsarConverterException e) { + applicationLogger.error(ApplicationMsgs.INVALID_CSAR_FILE, e); + response = buildResponse(Status.INTERNAL_SERVER_ERROR, "Error converting CSAR artifact to XML model."); + } catch (RequestValidationException e) { + applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e); + response = buildResponse(Status.BAD_REQUEST, e.getLocalizedMessage()); + } catch (Exception e) { + applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e); + response = buildResponse(Status.INTERNAL_SERVER_ERROR, + "Error while processing request. Please check the babel service logs for more details.\n"); + } + + return response; + } + + /** + * Helper method to create a REST response object. + * + * @param status response status code + * @param entity response payload + * @return + */ + private Response buildResponse(Status status, String entity) { + //@formatter:off + return Response + .status(status) + .entity(entity) + .type(MediaType.TEXT_PLAIN) + .build(); + //@formatter:on + } +} diff --git a/src/main/java/org/onap/aai/babel/service/data/BabelArtifact.java b/src/main/java/org/onap/aai/babel/service/data/BabelArtifact.java new file mode 100644 index 0000000..986aed9 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/service/data/BabelArtifact.java @@ -0,0 +1,63 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.service.data; + +/** + * Bean representing the return artifacts of the Babel microservice. + */ +public class BabelArtifact { + String name; + String type; + byte[] payload; + + public BabelArtifact(String name, String type, byte[] payload) { + super(); + this.name = name; + this.type = type; + this.payload = payload; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public byte[] getPayload() { + return payload; + } + + public void setPayload(byte[] payload) { + this.payload = payload; + } +} diff --git a/src/main/java/org/onap/aai/babel/service/data/BabelRequest.java b/src/main/java/org/onap/aai/babel/service/data/BabelRequest.java new file mode 100644 index 0000000..20a101f --- /dev/null +++ b/src/main/java/org/onap/aai/babel/service/data/BabelRequest.java @@ -0,0 +1,53 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.service.data; + +public class BabelRequest { + private String csar; + private String artifactVersion; + private String artifactName; + + public String getCsar() { + return csar; + } + + public void setCsar(String csar) { + this.csar = csar; + } + + public String getArtifactVersion() { + return artifactVersion; + } + + public void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + + public String getArtifactName() { + return artifactName; + } + + public void setArtifactName(String artifactName) { + this.artifactName = artifactName; + } +} diff --git a/src/main/java/org/onap/aai/babel/util/RequestValidationException.java b/src/main/java/org/onap/aai/babel/util/RequestValidationException.java new file mode 100644 index 0000000..5e3be5e --- /dev/null +++ b/src/main/java/org/onap/aai/babel/util/RequestValidationException.java @@ -0,0 +1,42 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.util; + +/** + * This exception is thrown when the request fails validation. + */ +public class RequestValidationException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Constructor for an instance of this exception with just a message. + * + * @param message information about the exception + */ + public RequestValidationException(String message) { + super(message); + } +} + + diff --git a/src/main/java/org/onap/aai/babel/util/RequestValidator.java b/src/main/java/org/onap/aai/babel/util/RequestValidator.java new file mode 100644 index 0000000..ecc9d2b --- /dev/null +++ b/src/main/java/org/onap/aai/babel/util/RequestValidator.java @@ -0,0 +1,50 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.util; + +import org.onap.aai.babel.service.data.BabelRequest; + +public class RequestValidator { + + private RequestValidator() {} + + + /** + * Validates that the request body contains the required attributes + * + * @param request the request body to validate + */ + public static void validateRequest(BabelRequest request) throws RequestValidationException { + if (request.getCsar() == null) { + throw new RequestValidationException("No csar attribute found in the request body."); + } + + if (request.getArtifactVersion() == null) { + throw new RequestValidationException("No artifact version attribute found in the request body."); + } + + if (request.getArtifactName() == null) { + throw new RequestValidationException("No artifact name attribute found in the request body."); + } + } +} diff --git a/src/main/java/org/onap/aai/babel/xml/generator/ArtifactGenerator.java b/src/main/java/org/onap/aai/babel/xml/generator/ArtifactGenerator.java new file mode 100644 index 0000000..4fd51aa --- /dev/null +++ b/src/main/java/org/onap/aai/babel/xml/generator/ArtifactGenerator.java @@ -0,0 +1,39 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.xml.generator; + +import java.util.List; +import org.onap.aai.babel.service.data.BabelArtifact; +import org.openecomp.sdc.generator.data.Artifact; + +public interface ArtifactGenerator { + + /** + * Generate a {@link List} of {@link BabelArtifact}s from the Artifacts obtained from the CSAR + * + * @param csarArtifacts artifacts obtained from the CSAR file + * @return generated {@link BabelArtifact}s + */ + List<BabelArtifact> generateArtifacts(List<Artifact> csarArtifacts) throws XmlArtifactGenerationException; + +} diff --git a/src/main/java/org/onap/aai/babel/xml/generator/ModelGenerator.java b/src/main/java/org/onap/aai/babel/xml/generator/ModelGenerator.java new file mode 100644 index 0000000..c6def3d --- /dev/null +++ b/src/main/java/org/onap/aai/babel/xml/generator/ModelGenerator.java @@ -0,0 +1,136 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.xml.generator; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import org.onap.aai.babel.logging.ApplicationMsgs; +import org.onap.aai.babel.service.data.BabelArtifact; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.openecomp.sdc.generator.data.AdditionalParams; +import org.openecomp.sdc.generator.data.Artifact; +import org.openecomp.sdc.generator.data.GenerationData; +import org.openecomp.sdc.generator.data.GeneratorUtil; +import org.openecomp.sdc.generator.data.GroupType; +import org.openecomp.sdc.generator.service.ArtifactGenerationService; + +/** + * This class is responsible for generating xml model artifacts from a collection of csar file artifacts + */ +public class ModelGenerator implements ArtifactGenerator { + + private static Logger logger = LoggerFactory.getInstance().getLogger(ModelGenerator.class); + + private static final String GENERATORCONFIG = "{\"artifactTypes\": [\"AAI\"]}"; + private static final Pattern UUID_NORMATIVE_NEW_VERSION = Pattern.compile("^\\d{1,}.0"); + private static final String VERSION_DELIMITER = "."; + private static final String VERSION_DELIMITER_REGEXP = "\\" + VERSION_DELIMITER; + private static final String DEFAULT_SERVICE_VERSION = "1.0"; + + /** + * Invokes the TOSCA artifact generator API with the input artifacts. + * + * @param csarArtifacts the input artifacts + * @return {@link List} of output artifacts + * @throws XmlArtifactGenerationException if there is an error trying to generate xml artifacts + */ + @Override + public List<BabelArtifact> generateArtifacts(List<Artifact> csarArtifacts) throws XmlArtifactGenerationException { + logger.info(ApplicationMsgs.DISTRIBUTION_EVENT, + "Generating XML for " + csarArtifacts.size() + " CSAR artifacts."); + + // Get the service version to pass into the generator + String toscaVersion = csarArtifacts.get(0).getVersion(); + logger.debug( + "Getting the service version for Tosca Version of the yml file. The Tosca Version is " + toscaVersion); + String serviceVersion = getServiceVersion(toscaVersion); + logger.debug("The service version is " + serviceVersion); + Map<String, String> additionalParams = new HashMap<>(); + additionalParams.put(AdditionalParams.ServiceVersion.getName(), serviceVersion); + + // Call ArtifactGenerator API + logger.debug("Obtaining instance of ArtifactGenerationService"); + ArtifactGenerationService generationService = ArtifactGenerationService.lookup(); + logger.debug("About to call generationService.generateArtifact()"); + GenerationData data = generationService.generateArtifact(csarArtifacts, GENERATORCONFIG, additionalParams); + logger.debug("Call generationService.generateArtifact() has finished"); + + // Convert results into BabelArtifacts + if (data.getErrorData().isEmpty()) { + return data.getResultData().stream().map(a -> new BabelArtifact(a.getName(), a.getType(), a.getPayload())) + .collect(Collectors.toList()); + } else { + throw new XmlArtifactGenerationException( + "Error occurred during artifact generation: " + data.getErrorData().toString()); + } + } + + /** + * Creates an instance of an input artifact for the generator. + * + * @param payload the payload downloaded from SDC + * @param artifactName name of the artifact to create + * @param artifactVersion version of the artifact to create + * @return an {@link Artifact} object constructed from the payload and artifactInfo + */ + public static Artifact createArtifact(byte[] payload, String artifactName, String artifactVersion) { + logger.info(ApplicationMsgs.DISTRIBUTION_EVENT, "Creating artifact for: " + artifactName); + + // Convert payload into an input Artifact + String checksum = GeneratorUtil.checkSum(payload); + byte[] encodedPayload = GeneratorUtil.encode(payload); + Artifact artifact = new Artifact("TOSCA", GroupType.DEPLOYMENT.name(), checksum, encodedPayload); + artifact.setName(artifactName); + artifact.setLabel(artifactName); + artifact.setDescription(artifactName); + artifact.setVersion(artifactVersion); + return artifact; + } + + private static String getServiceVersion(String artifactVersion) { + String serviceVersion; + + try { + if (UUID_NORMATIVE_NEW_VERSION.matcher(artifactVersion).matches()) { + serviceVersion = artifactVersion; + } else { + String[] versionParts = artifactVersion.split(VERSION_DELIMITER_REGEXP); + Integer majorVersion = Integer.parseInt(versionParts[0]); + + serviceVersion = (majorVersion + 1) + VERSION_DELIMITER + "0"; + } + } catch (Exception e) { + logger.warn(ApplicationMsgs.DISTRIBUTION_EVENT, + "Error generating service version from artifact version: " + artifactVersion + + ". Using default service version of: " + DEFAULT_SERVICE_VERSION + ". Error details: " + + e); + return DEFAULT_SERVICE_VERSION; + } + + return serviceVersion; + } +} diff --git a/src/main/java/org/onap/aai/babel/xml/generator/XmlArtifactGenerationException.java b/src/main/java/org/onap/aai/babel/xml/generator/XmlArtifactGenerationException.java new file mode 100644 index 0000000..bff6ab3 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/xml/generator/XmlArtifactGenerationException.java @@ -0,0 +1,40 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.xml.generator; + +/** + * This class represents an exception encountered when generating an Artifact. + */ +public class XmlArtifactGenerationException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Constructor for an instance of this exception with just a message. + * + * @param message information about the exception + */ + public XmlArtifactGenerationException(String message) { + super(message); + } +} |