diff options
author | Instrumental <jonathan.gathman@att.com> | 2018-10-15 07:37:28 -0500 |
---|---|---|
committer | Instrumental <jonathan.gathman@att.com> | 2018-10-15 07:38:55 -0500 |
commit | 93871ff58e90a91d359f72b00a92fe1e28310b82 (patch) | |
tree | 199885fe72c46ae15ef06d95ff3be28ce9469b83 /cadi/servlet-sample/src/main | |
parent | 1ccc1ca3fbd7bc1357a4d63d5fa5a29ce3f0ab67 (diff) |
Add Servlet Sample
Includes CA Bootstrap names for K8
Issue-ID: AAF-451
Change-Id: Ibc34a21cad0b38c5d56dbc20d84deb5bf66e9d64
Signed-off-by: Instrumental <jonathan.gathman@att.com>
Diffstat (limited to 'cadi/servlet-sample/src/main')
5 files changed, 431 insertions, 0 deletions
diff --git a/cadi/servlet-sample/src/main/java/org/onap/aaf/sample/cadi/MyServlet.java b/cadi/servlet-sample/src/main/java/org/onap/aaf/sample/cadi/MyServlet.java new file mode 100644 index 00000000..7d1eae96 --- /dev/null +++ b/cadi/servlet-sample/src/main/java/org/onap/aaf/sample/cadi/MyServlet.java @@ -0,0 +1,127 @@ +/** + * ============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.config.Config; +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(Config.AAF_DEFAULT_VERSION,tp).read("/authz/perms/user/"+request.getUserPrincipal().getName(),"application/Perms+json"); + Future<String> future = aafcon.client(Config.AAF_DEFAULT_VERSION).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/main/java/org/onap/aaf/sample/cadi/jetty/Config.java b/cadi/servlet-sample/src/main/java/org/onap/aaf/sample/cadi/jetty/Config.java new file mode 100644 index 00000000..a45725d7 --- /dev/null +++ b/cadi/servlet-sample/src/main/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/main/java/org/onap/aaf/sample/cadi/jetty/JettyServletServer.java b/cadi/servlet-sample/src/main/java/org/onap/aaf/sample/cadi/jetty/JettyServletServer.java new file mode 100644 index 00000000..165acffb --- /dev/null +++ b/cadi/servlet-sample/src/main/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/main/java/org/onap/aaf/sample/cadi/jetty/JettyStandalone.java b/cadi/servlet-sample/src/main/java/org/onap/aaf/sample/cadi/jetty/JettyStandalone.java new file mode 100644 index 00000000..6edd6f5b --- /dev/null +++ b/cadi/servlet-sample/src/main/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/main/java/org/onap/aaf/sample/cadi/jetty/MiniJASPIWrap.java b/cadi/servlet-sample/src/main/java/org/onap/aaf/sample/cadi/jetty/MiniJASPIWrap.java new file mode 100644 index 00000000..4d170f3f --- /dev/null +++ b/cadi/servlet-sample/src/main/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"); + } + } + } + +} |