diff options
author | Instrumental <jonathan.gathman@att.com> | 2018-09-07 11:41:35 -0500 |
---|---|---|
committer | Instrumental <jonathan.gathman@att.com> | 2018-09-07 11:41:44 -0500 |
commit | 824dc7b5fc0e1ccdf7f460479aff344727f0f01e (patch) | |
tree | 2cc956ba4bca9dd05bdfecc682a92f5b806678e3 /cadi/servlet-sample/src | |
parent | b8369a2668ad8f011d118de83a7b70f75f247332 (diff) |
Add Servlet Samples
Issue-ID: AAF-472
Change-Id: I69aae6509d65340942c4dee718b5dfe7726aab04
Signed-off-by: Instrumental <jonathan.gathman@att.com>
Diffstat (limited to 'cadi/servlet-sample/src')
6 files changed, 538 insertions, 0 deletions
diff --git a/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/MyServlet.java b/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/MyServlet.java new file mode 100644 index 00000000..466c02da --- /dev/null +++ b/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/MyServlet.java @@ -0,0 +1,126 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.sample.cadi; + +import java.io.IOException; +import java.security.Principal; + +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; + +import org.onap.aaf.cadi.aaf.v2_0.AAFCon; +import org.onap.aaf.cadi.client.Future; +import org.onap.aaf.cadi.principal.TaggedPrincipal; + +// Uncomment if you utilized the "MiniJASPIWrap" in the Servlet setup in "main()", and want to protect your service via Permission or mapped role +// @RolesAllowed({"com.att.aaf.myPerm|myInstance|myAction"}) + public class MyServlet implements Servlet { + private ServletConfig servletConfig; + + public void init(ServletConfig config) throws ServletException { + servletConfig = config; + } + + public ServletConfig getServletConfig() { + return servletConfig; + } + + public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { + HttpServletRequest request; + try { + request = (HttpServletRequest)req; + } catch (ClassCastException e) { + throw new ServletException("Only serving HTTP today",e); + } + + res.getOutputStream().println("<html><header><title>CSP Servlet Test</title></header><body><h1>You're good to go!</h1><pre>" + + request.getUserPrincipal()); + + String perm = request.getParameter("PERM"); + if(perm!=null) { + if(request.isUserInRole(perm)) { + if(perm.indexOf('|')<0) { + res.getOutputStream().println("\nCongrats!, You are in Role " + perm); + } else { + res.getOutputStream().println("\nCongrats!, You have Permission " + perm); + } + } else { + if(perm.indexOf('|')<0) { + res.getOutputStream().println("\nSorry, you are NOT in Role " + perm); + } else { + res.getOutputStream().println("\nSorry, you do NOT have Permission " + perm); + } + } + } + + // You can get the working AAFCon from Trans + AAFCon<?> aafcon = AAFCon.obtain(req); + if(aafcon!=null) { + try { + res.getOutputStream().println("----- Perms JSON from direct call -----"); + final Principal up = request.getUserPrincipal(); + TaggedPrincipal tp; + if(up instanceof TaggedPrincipal) { + tp = (TaggedPrincipal)up; + } else { + tp = new TaggedPrincipal() { + @Override + public String getName() { + return up.getName(); + } + + @Override + public String tag() { + return "Unknown"; + } + }; + } + // This call will be "as the user calling", but only if permission is set to trust. +// Future<String> future = aafcon.clientAs("2.0",tp).read("/authz/perms/user/"+request.getUserPrincipal().getName(),"application/Perms+json"); + Future<String> future = aafcon.client("2.0").read("/authz/perms/user/"+request.getUserPrincipal().getName(),"application/Perms+json"); + if(future.get(4000 /* timeout */)) { + res.getOutputStream().print(future.value); + } else { + System.err.println(future.code() + ", " + future.body()); + res.getOutputStream().print(future.code() + ", " + future.body()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } else { + res.getOutputStream().println("No AAFCon instantiated"); + } + res.getOutputStream().print("</pre></body></html>"); + + } + + public String getServletInfo() { + return "MyServlet"; + } + + public void destroy() { + } + }
\ No newline at end of file diff --git a/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/jetty/Config.java b/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/jetty/Config.java new file mode 100644 index 00000000..17f9b198 --- /dev/null +++ b/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/jetty/Config.java @@ -0,0 +1,45 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.sample.cadi.jetty; + +import java.util.EnumSet; + +import javax.servlet.DispatcherType; + +import org.eclipse.jetty.webapp.WebAppContext; +import org.onap.aaf.cadi.filter.CadiFilter; + + + +public class Config { + /** + * Method to make jetty configurations (others?) with more complex function possible + * + * @param sc + */ + public static final void addToContext(WebAppContext sc, String propFile) { + sc.addFilter(CadiFilter.class,"/*",EnumSet.of(DispatcherType.REQUEST)); + sc.setInitParameter(org.onap.aaf.cadi.config.Config.CADI_PROP_FILES, propFile); + } + + +} diff --git a/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/jetty/JettyServletServer.java b/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/jetty/JettyServletServer.java new file mode 100644 index 00000000..2d1fc097 --- /dev/null +++ b/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/jetty/JettyServletServer.java @@ -0,0 +1,112 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.sample.cadi.jetty; + +import java.net.Inet4Address; +import java.util.concurrent.ArrayBlockingQueue; + +import javax.servlet.Servlet; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.servlet.FilterHolder; +import org.eclipse.jetty.servlet.FilterMapping; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.onap.aaf.cadi.Access.Level; +import org.onap.aaf.cadi.PropAccess; +import org.onap.aaf.cadi.config.Config; +import org.onap.aaf.cadi.config.SecurityInfo; +import org.onap.aaf.cadi.filter.CadiFilter; + +public abstract class JettyServletServer implements Servlet { + + public static Server run(PropAccess access, String context, Class<? extends Servlet> servletCls, int port, String ...args) throws Exception { + // Defaults: + int blockingQueueSize = 10; + int corePoolSize = 10; + int maxPoolSize = 10; + int keepAliveTime = 3000; + String hostname = access.getProperty(Config.HOSTNAME, null); + if(hostname==null) { + hostname = Inet4Address.getLocalHost().getHostName(); + } + + // Add your own Properties to override defaults + + ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(blockingQueueSize); + QueuedThreadPool pool = new QueuedThreadPool(maxPoolSize,corePoolSize,keepAliveTime,queue); + Server server = new Server(pool); + + String protocol; + if(access.getProperty(Config.CADI_KEYSTORE_PASSWORD,null)==null) { + ServerConnector conn = new ServerConnector(server); + conn.setHost(hostname); + conn.setPort(port); + server.addConnector(conn); + protocol = "http"; + } else { + // Setup Security + SecurityInfo securityInfo = new SecurityInfo(access); + SslContextFactory scf = new SslContextFactory(); + scf.setSslContext(securityInfo.getSSLContext()); + scf.setWantClientAuth(true); + ServerConnector sslConnector = new ServerConnector(server,scf); + sslConnector.setHost(hostname); + sslConnector.setPort(port); + server.addConnector(sslConnector); + protocol = "https"; + } + + // Setup Sample Servlet + CadiFilter cf = new CadiFilter(true,access); + FilterHolder cfh = new FilterHolder(cf); + + ServletHandler shand = new ServletHandler(); + shand.addFilterWithMapping(cfh, "/*", FilterMapping.ALL); + // To use normal Servlets, just add the class here... Actually, bug in Jetty... need to add with ServletHolder + ServletHolder sh = new ServletHolder(); + sh.setServlet(servletCls.newInstance()); + shand.addServletWithMapping(sh,"/*"); + + // To use JASPI Authorization Style to protect the servlet, wrap the Servlet + // with the "MiniJSAPIWrap class, as shown here. Then add "@RolesAllowed" on your + // servlet (see sample). Use Pipe delimited Permissions, not AAF Roles in the line + // shand.addServletWithMapping(new MiniJASPIWrap(MyServlet.class),"/*"); + // call initialize after start + ContextHandler ch = new ServletContextHandler(); + ch.setContextPath(context); + ch.setHandler(shand); + server.setHandler(ch); + // Startup the Server + server.setStopAtShutdown(true); + server.start(); + + access.log(Level.INFO,"TestServlet is running at " + protocol + "://"+hostname+':'+port+context); + return server; + } + +} diff --git a/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/jetty/JettyStandalone.java b/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/jetty/JettyStandalone.java new file mode 100644 index 00000000..049e45e8 --- /dev/null +++ b/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/jetty/JettyStandalone.java @@ -0,0 +1,46 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.sample.cadi.jetty; + +import org.eclipse.jetty.server.Server; +import org.onap.aaf.cadi.Access.Level; +import org.onap.aaf.sample.cadi.MyServlet; +import org.onap.aaf.cadi.PropAccess; + + + + +public class JettyStandalone { + public static void main(String[] args) { + PropAccess access = new PropAccess(args); + try { + Server server = JettyServletServer.run(access, "/caditest", MyServlet.class, 3456); + server.join(); + } catch (Exception e) { + access.log(Level.ERROR, e); + } finally { + access.log(Level.INFO,"Stopping Service"); + } + + } + +} diff --git a/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/jetty/MiniJASPIWrap.java b/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/jetty/MiniJASPIWrap.java new file mode 100644 index 00000000..904f3cdc --- /dev/null +++ b/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/jetty/MiniJASPIWrap.java @@ -0,0 +1,101 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.sample.cadi.jetty; + +import java.io.IOException; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.UnavailableException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.servlet.ServletHolder; +import org.onap.aaf.cadi.filter.RolesAllowed; + + + +/** + * MiniJASPIWrap + * + * Support the ability to check JASPI Annotation Style Authorizations. + * + * This can be a clean way to enforce API Authorization without mistakes in code. + * + * @author JonathanGathman + * + */ +public class MiniJASPIWrap extends ServletHolder { + private RolesAllowed rolesAllowed; + //private String roles; + public MiniJASPIWrap(Class<? extends Servlet> servlet) { + super(servlet); + this.rolesAllowed = servlet.getAnnotation(RolesAllowed.class); + StringBuilder sb = new StringBuilder(); + boolean first = true; + if(rolesAllowed!=null) { + for(String str : rolesAllowed.value()) { + if(first)first=false; + else sb.append(','); + sb.append(str); + } + } + //roles = sb.toString(); + } + + /** + * handle + * + * When utilized, this class authorizes the transaction by first calling the standard J2EE API call + * "isUserInRole" with the role(s) found in the class Annotations (JASPI Style) + */ + @Override + public void handle(Request baseRequest, ServletRequest request, ServletResponse response) throws ServletException, UnavailableException, IOException { + if(rolesAllowed==null) { + super.handle(baseRequest, request, response); + } else { // Validate + try { + + HttpServletRequest hreq = (HttpServletRequest)request; + boolean proceed = false; + for(String role : rolesAllowed.value()) { + if(hreq.isUserInRole(role)) { + proceed = true; + break; + } + } + if(proceed) { + super.handle(baseRequest, request, response); + } else { + //baseRequest.getServletContext().log(hreq.getUserPrincipal().getName()+" Refused " + roles); + ((HttpServletResponse)response).sendError(403); // forbidden + } + } catch(ClassCastException e) { + throw new ServletException("JASPIWrap only supports HTTPServletRequest/HttpServletResponse"); + } + } + } + +} diff --git a/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/tomcate/TomcatEmbedded.java b/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/tomcate/TomcatEmbedded.java new file mode 100644 index 00000000..415283a5 --- /dev/null +++ b/cadi/servlet-sample/src/test/java/org/onap/aaf/sample/cadi/tomcate/TomcatEmbedded.java @@ -0,0 +1,108 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.sample.cadi.tomcate; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; + +import org.apache.catalina.Service; +import org.apache.catalina.connector.Connector; +import org.apache.catalina.startup.Tomcat; +import org.apache.log4j.chainsaw.Main; +import org.onap.aaf.cadi.Access; +import org.onap.aaf.cadi.Access.Level; +import org.onap.aaf.cadi.PropAccess; + +/** + * @author JonathanGathman + * + */ +public class TomcatEmbedded { + + public static void main(String[] args) throws Exception { + System.setProperty("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE", "true"); + Tomcat tomcat = new Tomcat(); + + Service service = tomcat.getService(); + service.addConnector(getSslConnector(new PropAccess(args), 8081)); + + tomcat.addWebapp("/caditest", getRootFolder().getAbsolutePath()); + + tomcat.start(); + tomcat.getServer().await(); + + } + + private static Connector getSslConnector(PropAccess access, int port) throws IOException { + Connector connector = new Connector(); + connector.setPort(port); + connector.setSecure(true); + connector.setScheme("https"); + setAttr(connector,access,"keyAlias","cadi_alias"); + setAttr(connector,access,"keystoreFile","cadi_keystore"); + connector.setAttribute("keystoreType", "PKCS12"); + setAttr(connector,access,"keystorePass","cadi_keystore_password"); + setAttr(connector,access,"truststoreFile","cadi_truststore"); + connector.setAttribute("truststoreType", "JKS"); + setAttr(connector,access,"truststorePass","cadi_truststore_password"); + connector.setAttribute("clientAuth", "want"); + connector.setAttribute("protocol", "HTTP/1.1"); + connector.setAttribute("sslProtocol", "TLS"); + connector.setAttribute("maxThreads", "200"); + connector.setAttribute("protocol", "org.apache.coyote.http11.Http11AprProtocol"); + connector.setAttribute("SSLEnabled", true); + return connector; + } + + private static void setAttr(Connector connector, Access access, String ctag, String atag) throws IOException { + String value = access.getProperty(atag, null); + if(value==null) { + access.log(Level.ERROR, atag, "is null"); + } else { + if(value.startsWith("enc:")) { + access.log(Level.INIT,atag,"=enc:************"); + value = access.decrypt(value, false); + } else { + access.log(Level.INIT,atag,"=",value); + } + connector.setAttribute(ctag, value); + } + } + + private static File getRootFolder() { + try { + File root; + String runningJarPath = Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath().replaceAll("\\\\", "/"); + int lastIndexOf = runningJarPath.lastIndexOf("/target/"); + if (lastIndexOf < 0) { + root = new File(""); + } else { + root = new File(runningJarPath.substring(0, lastIndexOf)); + } + System.out.println("application resolved root folder: " + root.getAbsolutePath()); + return root; + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } +} |