From ba20dff39a897ff8dbd71260c42da923c9bdcf7a Mon Sep 17 00:00:00 2001 From: Trevor Bramwell Date: Mon, 12 Sep 2016 11:06:56 -0700 Subject: Move ODL-AAA-MOON under 'upstream' Directory Change-Id: Ie010fbe3899e151421940908dbe8675aade54e2d Signed-off-by: Trevor Bramwell (cherry picked from commit cf864337c13b4638c588badf3f589f9e39318c95) --- .../java/org/opendaylight/aaa/shiro/Activator.java | 45 --- .../org/opendaylight/aaa/shiro/ServiceProxy.java | 94 ------ .../aaa/shiro/accounting/Accounter.java | 38 --- .../aaa/shiro/authorization/DefaultRBACRules.java | 78 ----- .../aaa/shiro/authorization/RBACRule.java | 170 ---------- .../opendaylight/aaa/shiro/filters/AAAFilter.java | 72 ---- .../aaa/shiro/filters/AAAShiroFilter.java | 51 --- .../aaa/shiro/filters/AuthenticationListener.java | 52 --- .../shiro/filters/AuthenticationTokenUtils.java | 129 ------- .../aaa/shiro/filters/MoonOAuthFilter.java | 186 ----------- .../shiro/filters/ODLHttpAuthenticationFilter.java | 78 ----- .../opendaylight/aaa/shiro/moon/MoonPrincipal.java | 160 --------- .../aaa/shiro/moon/MoonTokenEndpoint.java | 30 -- .../opendaylight/aaa/shiro/realm/MoonRealm.java | 99 ------ .../aaa/shiro/realm/ODLJndiLdapRealm.java | 315 ------------------ .../aaa/shiro/realm/ODLJndiLdapRealmAuthNOnly.java | 102 ------ .../opendaylight/aaa/shiro/realm/RadiusRealm.java | 37 --- .../opendaylight/aaa/shiro/realm/TACACSRealm.java | 38 --- .../aaa/shiro/realm/TokenAuthRealm.java | 369 --------------------- .../aaa/shiro/web/env/KarafIniWebEnvironment.java | 125 ------- .../aaa-shiro/src/main/resources/WEB-INF/web.xml | 48 --- .../aaa/aaa-shiro/src/main/resources/shiro.ini | 106 ------ 22 files changed, 2422 deletions(-) delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/Activator.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/ServiceProxy.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/accounting/Accounter.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/authorization/DefaultRBACRules.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/authorization/RBACRule.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AAAFilter.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AAAShiroFilter.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AuthenticationListener.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AuthenticationTokenUtils.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/MoonOAuthFilter.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/ODLHttpAuthenticationFilter.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/moon/MoonPrincipal.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/moon/MoonTokenEndpoint.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/MoonRealm.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/ODLJndiLdapRealm.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/ODLJndiLdapRealmAuthNOnly.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/RadiusRealm.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/TACACSRealm.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/TokenAuthRealm.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/web/env/KarafIniWebEnvironment.java delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/resources/WEB-INF/web.xml delete mode 100644 odl-aaa-moon/aaa/aaa-shiro/src/main/resources/shiro.ini (limited to 'odl-aaa-moon/aaa/aaa-shiro/src/main') diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/Activator.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/Activator.java deleted file mode 100644 index 2f1c98f7..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/Activator.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.shiro; - -import org.apache.felix.dm.DependencyActivatorBase; -import org.apache.felix.dm.DependencyManager; -import org.osgi.framework.BundleContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This scaffolding allows the use of AAA Filters without AuthN or AuthZ - * enabled. This is done to support workflows such as those included in the - * odl-restconf-noauth feature. - * - * This class is also responsible for offering contextual DEBUG - * level clues concerning the activation of the aaa-shiro bundle. - * To enable these debug messages, issue the following command in the karaf - * shell: log:set debug org.opendaylight.aaa.shiro.Activator - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - */ -public class Activator extends DependencyActivatorBase { - - private static final Logger LOG = LoggerFactory.getLogger(Activator.class); - - @Override - public void destroy(BundleContext bc, DependencyManager dm) throws Exception { - final String DEBUG_MESSAGE = "Destroying the aaa-shiro bundle"; - LOG.debug(DEBUG_MESSAGE); - } - - @Override - public void init(BundleContext bc, DependencyManager dm) throws Exception { - final String DEBUG_MESSAGE = "Initializing the aaa-shiro bundle"; - LOG.debug(DEBUG_MESSAGE); - } - -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/ServiceProxy.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/ServiceProxy.java deleted file mode 100644 index e4485d73..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/ServiceProxy.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2016 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.shiro; - -import org.opendaylight.aaa.shiro.filters.AAAFilter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Responsible for enabling and disabling the AAA service. By default, the - * service is disabled; the AAAFilter will not require AuthN or AuthZ. The - * service is enabled through calling - * ServiceProxy.getInstance().setEnabled(true). AuthN and AuthZ are - * disabled by default in order to support workflows such as the feature - * odl-restconf-noauth. - * - * The AAA service is enabled through installing the odl-aaa-shiro - * feature. The org.opendaylight.aaa.shiroact.Activator() - * constructor calls enables AAA through the ServiceProxy, which in turn enables - * the AAAFilter. - * - * ServiceProxy is a singleton; access to the ServiceProxy is granted through - * the getInstance() function. - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - * @see resconf - * web,xml - * @see org.opendaylight.aaa.shiro.Activator - * @see org.opendaylight.aaa.shiro.filters.AAAFilter - */ -public class ServiceProxy { - private static final Logger LOG = LoggerFactory.getLogger(ServiceProxy.class); - - /** - * AuthN and AuthZ are disabled by default to support workflows included in - * features such as odl-restconf-noauth - */ - public static final boolean DEFAULT_AA_ENABLE_STATUS = false; - - private static ServiceProxy instance = new ServiceProxy(); - private volatile boolean enabled = false; - private AAAFilter filter; - - /** - * private for singleton pattern - */ - private ServiceProxy() { - final String INFO_MESSAGE = "Creating the ServiceProxy"; - LOG.info(INFO_MESSAGE); - } - - /** - * @return ServiceProxy, a feature level singleton - */ - public static ServiceProxy getInstance() { - return instance; - } - - /** - * Enables/disables the feature, cascading the state information to the - * AAAFilter. - * - * @param enabled A flag indicating whether to enable the Service. - */ - public synchronized void setEnabled(final boolean enabled) { - this.enabled = enabled; - final String SERVICE_ENABLED_INFO_MESSAGE = "Setting ServiceProxy enabled to " + enabled; - LOG.info(SERVICE_ENABLED_INFO_MESSAGE); - // check for null because of non-determinism in bundle load - if (filter != null) { - filter.setEnabled(enabled); - } - } - - /** - * Extract whether the service is enabled. - * - * @param filter - * register an optional Filter for callback if enable state - * changes - * @return Whether the service is enabled - */ - public synchronized boolean getEnabled(final AAAFilter filter) { - this.filter = filter; - return enabled; - } -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/accounting/Accounter.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/accounting/Accounter.java deleted file mode 100644 index e768ea59..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/accounting/Accounter.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.aaa.shiro.accounting; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Accounter is a common place to output AAA messages. Use this class through - * invoking Logger.output("message"). - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - */ -public class Accounter { - - private static final Logger LOG = LoggerFactory.getLogger(Accounter.class); - - /* - * Essentially makes Accounter a singleton, avoiding the verbosity of - * Accounter.getInstance().output("message"). - */ - private Accounter() { - } - - /** - * Account for a particular message - * - * @param message A message for the aggregated AAA log. - */ - public static void output(final String message) { - LOG.debug(message); - } -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/authorization/DefaultRBACRules.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/authorization/DefaultRBACRules.java deleted file mode 100644 index 9e84c988..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/authorization/DefaultRBACRules.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.aaa.shiro.authorization; - -import com.google.common.collect.Sets; -import java.util.Collection; -import java.util.HashSet; - -/** - * A singleton container of default authorization rules that are installed as - * part of Shiro initialization. This class defines an immutable set of rules - * that are needed to provide system-wide security. These include protecting - * certain MD-SAL leaf nodes that contain AAA data from random access. This is - * not a place to define your custom rule set; additional RBAC rules are - * configured through the shiro initialization file: - * $KARAF_HOME/shiro.ini - * - * An important distinction to consider is that Shiro URL rules work to protect - * the system at the Web layer, and AuthzDomDataBroker works to - * protect the system down further at the DOM layer. - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - * - */ -public class DefaultRBACRules { - - private static DefaultRBACRules instance; - - /** - * a collection of the default security rules - */ - private Collection rbacRules = new HashSet(); - - /** - * protects the AAA MD-SAL store by preventing access to the leaf nodes to - * non-admin users. - */ - private static final RBACRule PROTECT_AAA_MDSAL = RBACRule.createAuthorizationRule( - "*/authorization/*", Sets.newHashSet("admin")); - - /* - * private for singleton pattern - */ - private DefaultRBACRules() { - // rbacRules.add(PROTECT_AAA_MDSAL); - } - - /** - * - * @return the container instance for the default RBAC Rules - */ - public static final DefaultRBACRules getInstance() { - if (null == instance) { - instance = new DefaultRBACRules(); - } - return instance; - } - - /** - * - * @return a copy of the default rules, so any modifications to the returned - * reference do not affect the DefaultRBACRules. - */ - public final Collection getRBACRules() { - // Returns a copy of the rbacRules set such that the original set keeps - // its contract of remaining immutable. Calls to rbacRules.add() are - // encapsulated solely in DefaultRBACRules. - // - // Since this method is only called at shiro initialiation time, - // memory consumption of creating a new set is a non-issue. - return Sets.newHashSet(rbacRules); - } -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/authorization/RBACRule.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/authorization/RBACRule.java deleted file mode 100644 index 0da95eb4..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/authorization/RBACRule.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.aaa.shiro.authorization; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A container for RBAC Rules. An RBAC Rule is composed of a url pattern which - * may contain asterisk characters (*), and a collection of roles. These are - * represented in shiro.ini in the following format: - * urlPattern=roles[atLeastOneCommaSeperatedRole] - * - * RBACRules are immutable; that is, you cannot change the url pattern or the - * roles after creation. This is done for security purposes. RBACRules are - * created through utilizing a static factory method: - * RBACRule.createRBACRule() - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - * - */ -public class RBACRule { - - private static final Logger LOG = LoggerFactory.getLogger(RBACRule.class); - - /** - * a url pattern that can optional contain asterisk characters (*) - */ - private String urlPattern; - - /** - * a collection of role names, such as "admin" and "user" - */ - private Collection roles = new HashSet(); - - /** - * Creates an RBAC Rule. Made private for static factory method. - * - * @param urlPattern - * Cannot be null or the empty string. - * @param roles - * Must contain at least one role. - * @throws NullPointerException - * if urlPattern or roles is null - * @throws IllegalArgumentException - * if urlPattern is an empty string or - * roles is an empty collection. - */ - private RBACRule(final String urlPattern, final Collection roles) - throws NullPointerException, IllegalArgumentException { - - this.setUrlPattern(urlPattern); - this.setRoles(roles); - } - - /** - * The static factory method used to create RBACRules. - * - * @param urlPattern - * Cannot be null or the empty string. - * @param roles - * Cannot be null or an emtpy collection. - * @return An immutable RBACRule - */ - public static RBACRule createAuthorizationRule(final String urlPattern, - final Collection roles) { - - RBACRule authorizationRule = null; - try { - authorizationRule = new RBACRule(urlPattern, roles); - } catch (Exception e) { - LOG.error("Cannot instantiate the AuthorizationRule", e); - } - return authorizationRule; - } - - /** - * - * @return the urlPattern for the RBACRule - */ - public String getUrlPattern() { - return urlPattern; - } - - /* - * helper to ensure the url pattern is not the empty string - */ - private static void checkUrlPatternLength(final String urlPattern) - throws IllegalArgumentException { - - final String EXCEPTION_MESSAGE = "Empty String is not allowed for urlPattern"; - if (urlPattern.isEmpty()) { - throw new IllegalArgumentException(EXCEPTION_MESSAGE); - } - } - - private void setUrlPattern(final String urlPattern) throws NullPointerException, - IllegalArgumentException { - - Preconditions.checkNotNull(urlPattern); - checkUrlPatternLength(urlPattern); - this.urlPattern = urlPattern; - } - - /** - * - * @return a copy of the rule, so any modifications to the returned - * reference do not affect the immutable RBACRule. - */ - public Collection getRoles() { - // Returns a copy of the roles collection such that the original set - // keeps - // its contract of remaining immutable. - // - // Since this method is only called at shiro initialiation time, - // memory consumption of creating a new set is a non-issue. - return Sets.newHashSet(roles); - } - - /* - * check to ensure the roles collection is not empty - */ - private static void checkRolesCollectionSize(final Collection roles) - throws IllegalArgumentException { - - final String EXCEPTION_MESSAGE = "roles must contain at least 1 role"; - if (roles.isEmpty()) { - throw new IllegalArgumentException(EXCEPTION_MESSAGE); - } - } - - private void setRoles(final Collection roles) throws NullPointerException, - IllegalArgumentException { - - Preconditions.checkNotNull(roles); - checkRolesCollectionSize(roles); - this.roles = roles; - } - - /** - * Generates a string representation of the RBACRule roles in - * shiro form. - * - * @return roles string representation in the form - * roles[roleOne,roleTwo] - */ - public String getRolesInShiroFormat() { - final String ROLES_STRING = "roles"; - return ROLES_STRING + Arrays.toString(roles.toArray()); - } - - /** - * Generates the string representation of the RBACRule in shiro - * form. For example: urlPattern=roles[admin,user] - */ - @Override - public String toString() { - return String.format("%s=%s", urlPattern, getRolesInShiroFormat()); - } -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AAAFilter.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AAAFilter.java deleted file mode 100644 index 47dd9549..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AAAFilter.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.shiro.filters; - -import org.apache.shiro.web.servlet.ShiroFilter; -import org.opendaylight.aaa.shiro.ServiceProxy; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The RESTCONF AAA JAX-RS 1.X Web Filter. This class is also responsible for - * delivering debug information; to enable these debug statements, please issue - * the following in the karaf shell: - * - * log:set debug org.opendaylight.aaa.shiro.filters.AAAFilter - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - * @see javax.servlet.Filter - * @see org.apache.shiro.web.servlet.ShiroFilter - */ -public class AAAFilter extends ShiroFilter { - - private static final Logger LOG = LoggerFactory.getLogger(AAAFilter.class); - - public AAAFilter() { - super(); - final String DEBUG_MESSAGE = "Creating the AAAFilter"; - LOG.debug(DEBUG_MESSAGE); - } - - /* - * (non-Javadoc) - * - * Adds context clues that aid in debugging. Also initializes the enable - * status to correspond with - * ServiceProxy.getInstance.getEnabled(). - * - * @see org.apache.shiro.web.servlet.ShiroFilter#init() - */ - @Override - public void init() throws Exception { - super.init(); - final String DEBUG_MESSAGE = "Initializing the AAAFilter"; - LOG.debug(DEBUG_MESSAGE); - // sets the filter to the startup value. Because of non-determinism in - // bundle loading, this passes an instance of itself along so that if - // the - // enable status changes, then AAAFilter enable status is changed. - setEnabled(ServiceProxy.getInstance().getEnabled(this)); - } - - /* - * (non-Javadoc) - * - * Adds context clues to aid in debugging whether the filter is enabled. - * - * @see - * org.apache.shiro.web.servlet.OncePerRequestFilter#setEnabled(boolean) - */ - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - final String DEBUG_MESSAGE = "Setting AAAFilter enabled to " + enabled; - LOG.debug(DEBUG_MESSAGE); - } -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AAAShiroFilter.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AAAShiroFilter.java deleted file mode 100644 index 530acfac..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AAAShiroFilter.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2016 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.shiro.filters; - -import org.apache.shiro.web.servlet.ShiroFilter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The default AAA JAX-RS 1.X Web Filter. Unlike AAAFilter, which is aimed towards - * supporting RESTCONF and its existing API mechanisms, AAAShiroFilter is a generic - * ShiroFilter for use with any other ODL Servlets. The main difference - * is that AAAFilter was designed to support the existing noauth - * mechanism, while this filter cannot be disabled. - * - * This class is also responsible for delivering debug information; to enable these - * debug statements, please issue the following in the karaf shell: - * - * log:set debug org.opendaylight.aaa.shiro.filters.AAAShiroFilter - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - * @see javax.servlet.Filter - * @see org.apache.shiro.web.servlet.ShiroFilter - */ -public class AAAShiroFilter extends ShiroFilter { - - private static final Logger LOG = LoggerFactory.getLogger(AAAShiroFilter.class); - - public AAAShiroFilter() { - LOG.debug("Creating the AAAShiroFilter"); - } - - /* - * (non-Javadoc) - * - * Adds context clues that aid in debugging. - * - * @see org.apache.shiro.web.servlet.ShiroFilter#init() - */ - @Override - public void init() throws Exception { - super.init(); - LOG.debug("Initializing the AAAShiroFilter"); - } -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AuthenticationListener.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AuthenticationListener.java deleted file mode 100644 index 080ab114..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AuthenticationListener.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2016 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.shiro.filters; - -import org.apache.shiro.authc.AuthenticationException; -import org.apache.shiro.authc.AuthenticationInfo; -import org.apache.shiro.authc.AuthenticationToken; -import org.apache.shiro.subject.PrincipalCollection; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Follows the event-listener pattern; the Authenticator notifies this class about - * authentication attempts. AuthenticationListener logs successful and unsuccessful - * authentication attempts appropriately. Log messages are emitted at the DEBUG log - * level. To enable the messages out of the box, use the following command from karaf: - * log:set DEBUG org.opendaylight.aaa.shiro.authc.AuthenicationListener - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - */ -public class AuthenticationListener implements org.apache.shiro.authc.AuthenticationListener { - - private static final Logger LOG = LoggerFactory.getLogger(AuthenticationListener.class); - - @Override - public void onSuccess(final AuthenticationToken authenticationToken, final AuthenticationInfo authenticationInfo) { - if (LOG.isDebugEnabled()) { - final String successMessage = AuthenticationTokenUtils.generateSuccessfulAuthenticationMessage(authenticationToken); - LOG.debug(successMessage); - } - } - - @Override - public void onFailure(final AuthenticationToken authenticationToken, final AuthenticationException e) { - if (LOG.isDebugEnabled()) { - final String failureMessage = AuthenticationTokenUtils.generateUnsuccessfulAuthenticationMessage(authenticationToken); - LOG.debug(failureMessage); - } - } - - @Override - public void onLogout(final PrincipalCollection principalCollection) { - // Do nothing; AAA is aimed at RESTCONF, which stateless by definition. - // Including this output would very quickly pollute the log. - } -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AuthenticationTokenUtils.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AuthenticationTokenUtils.java deleted file mode 100644 index a5f0c10d..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/AuthenticationTokenUtils.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2016 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.shiro.filters; - -import com.google.common.base.Preconditions; -import org.apache.shiro.authc.AuthenticationToken; -import org.apache.shiro.authc.UsernamePasswordToken; - -/** - * Utility methods for forming audit trail output based on an AuthenticationToken. - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - */ -public class AuthenticationTokenUtils { - - /** - * default value used in messaging when the "user" field is unparsable from the HTTP REST request - */ - static final String DEFAULT_USERNAME = "an unknown user"; - - /** - * default value used in messaging when the "user" field is not present in the HTTP REST request, implying - * a different implementation of AuthenticationToken such as CasToken. - */ - static final String DEFAULT_TOKEN = "an un-parsable token type"; - - /** - * default value used in messaging when the "host" field cannot be determined. - */ - static final String DEFAULT_HOSTNAME = "an unknown host"; - - private AuthenticationTokenUtils() { - // private to prevent instantiation - } - - /** - * Determines whether the supplied Token is a UsernamePasswordToken. - * - * @param token A generic Token, which might be a UsernamePasswordToken - * @return Whether the supplied Token is a UsernamePasswordToken - */ - public static boolean isUsernamePasswordToken(final AuthenticationToken token) { - return token instanceof UsernamePasswordToken; - } - - /** - * Extracts the username if possible. If the supplied token is a UsernamePasswordToken - * and the username field is not set, DEFAULT_USERNAME is returned. If the supplied - * token is not a UsernamePasswordToken (i.e., a CasToken or other - * implementation of AuthenticationToken), then DEFAULT_TOKEN is - * returned. - * - * @param token An AuthenticationToken, possibly a UsernamePasswordToken - * @return the username, DEFAULT_USERNAME or DEFAULT_TOKEN depending on input - */ - public static String extractUsername(final AuthenticationToken token) { - if (isUsernamePasswordToken(token)) { - final UsernamePasswordToken upt = (UsernamePasswordToken) token; - return extractField(upt.getUsername(), DEFAULT_USERNAME); - } - return DEFAULT_TOKEN; - } - - /** - * Extracts the hostname if possible. If the supplied token is a UsernamePasswordToken - * and the hostname field is not set, DEFAULT_HOSTNAME is returned. If the supplied - * token is not a UsernamePasswordToken (i.e., a CasToken or other - * implementation of AuthenticationToken), then DEFAULT_HOSTNAME is - * returned. - * - * @param token An AuthenticationToken, possibly a UsernamePasswordToken - * @return the hostname, or DEFAULT_USERNAME depending on input - */ - public static String extractHostname(final AuthenticationToken token) { - if (isUsernamePasswordToken(token)) { - final UsernamePasswordToken upt = (UsernamePasswordToken) token; - return extractField(upt.getHost(), DEFAULT_HOSTNAME); - } - return DEFAULT_HOSTNAME; - } - - /** - * Utility method to generate a generic message indicating Authentication was unsuccessful. - * - * @param token An AuthenticationToken, possibly a UsernamePasswordToken - * @return A message indicating authentication was unsuccessful - */ - public static String generateUnsuccessfulAuthenticationMessage(final AuthenticationToken token) { - final String username = extractUsername(token); - final String remoteHostname = extractHostname(token); - return String.format("Unsuccessful authentication attempt by %s from %s", username, remoteHostname); - } - - /** - * Utility method to generate a generic message indicating Authentication was successful. - * - * @param token An AuthenticationToken, possibly a UsernamePasswordToken - * @return A message indicating authentication was successful - */ - public static String generateSuccessfulAuthenticationMessage(final AuthenticationToken token) { - final String username = extractUsername(token); - final String remoteHostname = extractHostname(token); - return String.format("Successful authentication attempt by %s from %s", username, remoteHostname); - } - - /** - * Utility method that returns field, or defaultValue if field is null. - * - * @param field A generic string, which is possibly null. - * @param defaultValue A non-null value returned if field is null - * @return field or defaultValue if field is null - * @throws IllegalArgumentException If defaultValue is null - */ - private static String extractField(final String field, final String defaultValue) - throws IllegalArgumentException { - - Preconditions.checkNotNull(defaultValue, "defaultValue can't be null"); - if (field != null) { - return field; - } - return defaultValue; - } -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/MoonOAuthFilter.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/MoonOAuthFilter.java deleted file mode 100644 index 241b7c28..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/MoonOAuthFilter.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.shiro.filters; - -import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; -import static javax.servlet.http.HttpServletResponse.SC_CREATED; -import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; -import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED; - -import java.io.IOException; -import java.io.PrintWriter; - -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.oltu.oauth2.as.response.OAuthASResponse; -import org.apache.oltu.oauth2.common.exception.OAuthProblemException; -import org.apache.oltu.oauth2.common.exception.OAuthSystemException; -import org.apache.oltu.oauth2.common.message.OAuthResponse; -import org.apache.oltu.oauth2.common.message.types.TokenType; -import org.apache.shiro.SecurityUtils; -import org.apache.shiro.authc.AuthenticationException; -import org.apache.shiro.authc.AuthenticationToken; -import org.apache.shiro.authc.UsernamePasswordToken; -import org.apache.shiro.subject.Subject; -import org.apache.shiro.web.filter.authc.AuthenticatingFilter; -import org.opendaylight.aaa.AuthenticationBuilder; -import org.opendaylight.aaa.ClaimBuilder; -import org.opendaylight.aaa.api.Authentication; -import org.opendaylight.aaa.api.Claim; -import org.opendaylight.aaa.shiro.moon.MoonPrincipal; -import org.opendaylight.aaa.sts.OAuthRequest; -import org.opendaylight.aaa.sts.ServiceLocator; - -/** - * MoonOAuthFilter filters oauth1 requests form token based authentication - * @author Alioune BA alioune.ba@orange.com - * - */ -public class MoonOAuthFilter extends AuthenticatingFilter{ - - private static final String DOMAIN_SCOPE_REQUIRED = "Domain scope required"; - private static final String NOT_IMPLEMENTED = "not_implemented"; - private static final String UNAUTHORIZED = "unauthorized"; - private static final String UNAUTHORIZED_CREDENTIALS = "Unauthorized: Login/Password incorrect"; - - static final String TOKEN_GRANT_ENDPOINT = "/token"; - static final String TOKEN_REVOKE_ENDPOINT = "/revoke"; - static final String TOKEN_VALIDATE_ENDPOINT = "/validate"; - - @Override - protected UsernamePasswordToken createToken(ServletRequest request, ServletResponse response) throws Exception { - // TODO Auto-generated method stub - HttpServletRequest httpRequest = (HttpServletRequest) request; - OAuthRequest oauthRequest = new OAuthRequest(httpRequest); - return new UsernamePasswordToken(oauthRequest.getUsername(),oauthRequest.getPassword()); - } - - @Override - protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { - // TODO Auto-generated method stub - Subject currentUser = SecurityUtils.getSubject(); - return executeLogin(request, response); - } - - protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, - ServletRequest request, ServletResponse response) throws Exception { - HttpServletResponse httpResponse= (HttpServletResponse) response; - MoonPrincipal principal = (MoonPrincipal) subject.getPrincipals().getPrimaryPrincipal(); - Claim claim = principal.principalToClaim(); - oauthAccessTokenResponse(httpResponse,claim,"",principal.getToken()); - return true; - } - - protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, - ServletRequest request, ServletResponse response) { - HttpServletResponse resp = (HttpServletResponse) response; - error(resp, SC_BAD_REQUEST, UNAUTHORIZED_CREDENTIALS); - return false; - } - - protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception { - - HttpServletRequest req= (HttpServletRequest) request; - HttpServletResponse resp = (HttpServletResponse) response; - try { - if (req.getServletPath().equals(TOKEN_GRANT_ENDPOINT)) { - UsernamePasswordToken token = createToken(request, response); - if (token == null) { - String msg = "A valid non-null AuthenticationToken " + - "must be created in order to execute a login attempt."; - throw new IllegalStateException(msg); - } - try { - Subject subject = getSubject(request, response); - subject.login(token); - return onLoginSuccess(token, subject, request, response); - } catch (AuthenticationException e) { - return onLoginFailure(token, e, request, response); - } - } else if (req.getServletPath().equals(TOKEN_REVOKE_ENDPOINT)) { - //TODO: deleteAccessToken(req, resp); - } else if (req.getServletPath().equals(TOKEN_VALIDATE_ENDPOINT)) { - //TODO: validateToken(req, resp); - } - } catch (AuthenticationException e) { - error(resp, SC_UNAUTHORIZED, e.getMessage()); - } catch (OAuthProblemException oe) { - error(resp, oe); - } catch (Exception e) { - error(resp, e); - } - return false; - } - - private void oauthAccessTokenResponse(HttpServletResponse resp, Claim claim, String clientId, String token) - throws OAuthSystemException, IOException { - if (claim == null) { - throw new AuthenticationException(UNAUTHORIZED); - } - - // Cache this token... - Authentication auth = new AuthenticationBuilder(new ClaimBuilder(claim).setClientId( - clientId).build()).setExpiration(tokenExpiration()).build(); - ServiceLocator.getInstance().getTokenStore().put(token, auth); - - OAuthResponse r = OAuthASResponse.tokenResponse(SC_CREATED).setAccessToken(token) - .setTokenType(TokenType.BEARER.toString()) - .setExpiresIn(Long.toString(auth.expiration())) - .buildJSONMessage(); - write(resp, r); - } - - private void write(HttpServletResponse resp, OAuthResponse r) throws IOException { - resp.setStatus(r.getResponseStatus()); - PrintWriter pw = resp.getWriter(); - pw.print(r.getBody()); - pw.flush(); - pw.close(); - } - - private long tokenExpiration() { - return ServiceLocator.getInstance().getTokenStore().tokenExpiration(); - } - - // Emit an error OAuthResponse with the given HTTP code - private void error(HttpServletResponse resp, int httpCode, String error) { - try { - OAuthResponse r = OAuthResponse.errorResponse(httpCode).setError(error) - .buildJSONMessage(); - write(resp, r); - } catch (Exception e1) { - // Nothing to do here - } - } - - private void error(HttpServletResponse resp, OAuthProblemException e) { - try { - OAuthResponse r = OAuthResponse.errorResponse(SC_BAD_REQUEST).error(e) - .buildJSONMessage(); - write(resp, r); - } catch (Exception e1) { - // Nothing to do here - } - } - - private void error(HttpServletResponse resp, Exception e) { - try { - OAuthResponse r = OAuthResponse.errorResponse(SC_INTERNAL_SERVER_ERROR) - .setError(e.getClass().getName()) - .setErrorDescription(e.getMessage()).buildJSONMessage(); - write(resp, r); - } catch (Exception e1) { - // Nothing to do here - } - } - -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/ODLHttpAuthenticationFilter.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/ODLHttpAuthenticationFilter.java deleted file mode 100644 index 90b0101e..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/filters/ODLHttpAuthenticationFilter.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.shiro.filters; - -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; - -import org.apache.shiro.codec.Base64; -import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter; -import org.apache.shiro.web.util.WebUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Extends BasicHttpAuthenticationFilter to include ability to - * authenticate OAuth2 tokens, which is needed for backwards compatibility with - * TokenAuthFilter. - * - * This behavior is enabled by default for backwards compatibility. To disable - * OAuth2 functionality, just comment out the following line from the - * etc/shiro.ini file: - * authcBasic = org.opendaylight.aaa.shiro.filters.ODLHttpAuthenticationFilter - * then restart the karaf container. - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - * - */ -public class ODLHttpAuthenticationFilter extends BasicHttpAuthenticationFilter { - - private static final Logger LOG = LoggerFactory.getLogger(ODLHttpAuthenticationFilter.class); - - // defined in lower-case for more efficient string comparison - protected static final String BEARER_SCHEME = "bearer"; - - protected static final String OPTIONS_HEADER = "OPTIONS"; - - public ODLHttpAuthenticationFilter() { - super(); - LOG.info("Creating the ODLHttpAuthenticationFilter"); - } - - @Override - protected String[] getPrincipalsAndCredentials(String scheme, String encoded) { - final String decoded = Base64.decodeToString(encoded); - // attempt to decode username/password; otherwise decode as token - if (decoded.contains(":")) { - return decoded.split(":"); - } - return new String[] { encoded }; - } - - @Override - protected boolean isLoginAttempt(String authzHeader) { - final String authzScheme = getAuthzScheme().toLowerCase(); - final String authzHeaderLowerCase = authzHeader.toLowerCase(); - return authzHeaderLowerCase.startsWith(authzScheme) - || authzHeaderLowerCase.startsWith(BEARER_SCHEME); - } - - @Override - protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, - Object mappedValue) { - final HttpServletRequest httpRequest = WebUtils.toHttp(request); - final String httpMethod = httpRequest.getMethod(); - if (OPTIONS_HEADER.equalsIgnoreCase(httpMethod)) { - return true; - } else { - return super.isAccessAllowed(httpRequest, response, mappedValue); - } - } -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/moon/MoonPrincipal.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/moon/MoonPrincipal.java deleted file mode 100644 index 9dd2fd4f..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/moon/MoonPrincipal.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.aaa.shiro.moon; - -import com.google.common.collect.ImmutableSet; - -import java.io.Serializable; -import java.util.Set; - -import org.opendaylight.aaa.api.Claim; - -/** - * MoonPrincipal contains all user's information returned by moon on successful authentication - * @author Alioune BA alioune.ba@orange.com - * - */ -public class MoonPrincipal { - - private final String username; - private final String domain; - private final String userId; - private final Set roles; - private final String token; - - - public MoonPrincipal(String username, String domain, String userId, Set roles, String token) { - this.username = username; - this.domain = domain; - this.userId = userId; - this.roles = roles; - this.token = token; - } - - public MoonPrincipal createODLPrincipal(String username, String domain, - String userId, Set roles, String token) { - - return new MoonPrincipal(username, domain, userId, roles,token); - } - - public Claim principalToClaim (){ - return new MoonClaim("", this.getUserId(), this.getUsername(), this.getDomain(), this.getRoles()); - } - - public String getUsername() { - return this.username; - } - - public String getDomain() { - return this.domain; - } - - public String getUserId() { - return this.userId; - } - - public Set getRoles() { - return this.roles; - } - - public String getToken(){ - return this.token; - } - - public class MoonClaim implements Claim, Serializable { - private static final long serialVersionUID = -8115027645190209125L; - private int hashCode = 0; - private String clientId; - private String userId; - private String user; - private String domain; - private ImmutableSet roles; - - public MoonClaim(String clientId, String userId, String user, String domain, Set roles) { - this.clientId = clientId; - this.userId = userId; - this.user = user; - this.domain = domain; - this.roles = ImmutableSet. builder().addAll(roles).build(); - - if (userId.isEmpty() || user.isEmpty() || roles.isEmpty() || roles.contains("")) { - throw new IllegalStateException("The Claim is missing one or more of the required fields."); - } - } - - @Override - public String clientId() { - return clientId; - } - - @Override - public String userId() { - return userId; - } - - @Override - public String user() { - return user; - } - - @Override - public String domain() { - return domain; - } - - @Override - public Set roles() { - return roles; - } - public String getClientId() { - return clientId; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public String getUser() { - return user; - } - - public void setUser(String user) { - this.user = user; - } - - public String getDomain() { - return domain; - } - - public void setDomain(String domain) { - this.domain = domain; - } - - public ImmutableSet getRoles() { - return roles; - } - - public void setRoles(ImmutableSet roles) { - this.roles = roles; - } - - @Override - public String toString() { - return "clientId:" + clientId + "," + "userId:" + userId + "," + "userName:" + user - + "," + "domain:" + domain + "," + "roles:" + roles ; - } - } -} \ No newline at end of file diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/moon/MoonTokenEndpoint.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/moon/MoonTokenEndpoint.java deleted file mode 100644 index a954a606..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/moon/MoonTokenEndpoint.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.shiro.moon; - - -import java.io.IOException; - -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MoonTokenEndpoint extends HttpServlet{ - - private static final long serialVersionUID = 4980356362831585417L; - private static final Logger LOG = LoggerFactory.getLogger(MoonTokenEndpoint.class); - - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { - LOG.debug("MoonTokenEndpoint Servlet doPost"); - } - -} \ No newline at end of file diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/MoonRealm.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/MoonRealm.java deleted file mode 100644 index 9ebbb4d7..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/MoonRealm.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.aaa.shiro.realm; - -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.WebResource; -import com.sun.jersey.api.client.config.ClientConfig; -import com.sun.jersey.api.client.config.DefaultClientConfig; - -import java.util.LinkedHashSet; -import java.util.Set; - -import org.apache.shiro.authc.AuthenticationException; -import org.apache.shiro.authc.AuthenticationInfo; -import org.apache.shiro.authc.AuthenticationToken; -import org.apache.shiro.authc.SimpleAuthenticationInfo; -import org.apache.shiro.authc.UsernamePasswordToken; -import org.apache.shiro.authz.AuthorizationInfo; -import org.apache.shiro.realm.AuthorizingRealm; -import org.apache.shiro.subject.PrincipalCollection; -import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONTokener; -import org.opendaylight.aaa.shiro.moon.MoonPrincipal; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -/** - * MoonRealm is a Shiro Realm that authenticates users from OPNFV/moon platform - * @author Alioune BA alioune.ba@orange.com - * - */ -public class MoonRealm extends AuthorizingRealm{ - - private static final Logger LOG = LoggerFactory.getLogger(MoonRealm.class); - @Override - protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) { - // TODO Auto-generated method stub - return null; - } - - @Override - protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { - // TODO Auto-generated method stub - String username = ""; - String password = ""; - String domain = "sdn"; - username = (String) authenticationToken.getPrincipal(); - final UsernamePasswordToken upt = (UsernamePasswordToken) authenticationToken; - password = new String(upt.getPassword()); - final MoonPrincipal moonPrincipal = moonAuthenticate(username,password,domain); - if (moonPrincipal!=null){ - return new SimpleAuthenticationInfo(moonPrincipal, password.toCharArray(),getName()); - }else{ - return null; - } - } - - public MoonPrincipal moonAuthenticate(String username, String password, String domain){ - - String output = ""; - ClientConfig config = new DefaultClientConfig(); - Client client = Client.create(config); - JSONTokener tokener; - JSONObject object =null; - Set UserRoles = new LinkedHashSet<>(); - - String server = System.getenv("MOON_SERVER_ADDR"); - String port = System.getenv("MOON_SERVER_PORT"); - String URL = "http://" +server+ ":" +port+ "/moon/auth/tokens"; - LOG.debug("Moon server is at: {} ", server); - WebResource webResource = client.resource(URL); - String input = "{\"username\": \""+ username + "\"," + "\"password\":" + "\"" + password + "\"," + "\"project\":" + "\"" + domain + "\"" + "}";; - ClientResponse response = webResource.type("application/json").post(ClientResponse.class, input); - output = response.getEntity(String.class); - tokener = new JSONTokener(output); - object = new JSONObject(tokener); - try { - if (object.getString("token")!=null){ - String token = object.getString("token"); - String userID = username+"@"+domain; - for (int i=0; i< object.getJSONArray("roles").length(); i++){ - UserRoles.add((String) object.getJSONArray("roles").get(i)); - } - MoonPrincipal principal = new MoonPrincipal(username,domain,userID,UserRoles,token); - return principal; - } - }catch (JSONException e){ - throw new IllegalStateException("Authentication Error : "+ object.getJSONObject("error").getString("title")); - } - return null; - } - -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/ODLJndiLdapRealm.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/ODLJndiLdapRealm.java deleted file mode 100644 index 7d0bafd7..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/ODLJndiLdapRealm.java +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) 2015, 2016 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.shiro.realm; - -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.Set; - -import javax.naming.NamingEnumeration; -import javax.naming.NamingException; -import javax.naming.directory.Attribute; -import javax.naming.directory.Attributes; -import javax.naming.directory.SearchControls; -import javax.naming.directory.SearchResult; -import javax.naming.ldap.LdapContext; - -import org.apache.shiro.authc.AuthenticationException; -import org.apache.shiro.authc.AuthenticationInfo; -import org.apache.shiro.authc.AuthenticationToken; -import org.apache.shiro.authz.AuthorizationInfo; -import org.apache.shiro.authz.SimpleAuthorizationInfo; -import org.apache.shiro.realm.ldap.JndiLdapRealm; -import org.apache.shiro.realm.ldap.LdapContextFactory; -import org.apache.shiro.realm.ldap.LdapUtils; -import org.apache.shiro.subject.PrincipalCollection; -import org.apache.shiro.util.Nameable; -import org.opendaylight.aaa.shiro.accounting.Accounter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * An extended implementation of - * org.apache.shiro.realm.ldap.JndiLdapRealm which includes - * additional Authorization capabilities. To enable this Realm, add the - * following to shiro.ini: - * - *#ldapRealm = org.opendaylight.aaa.shiro.realm.ODLJndiLdapRealmAuthNOnly - *#ldapRealm.userDnTemplate = uid={0},ou=People,dc=DOMAIN,dc=TLD - *#ldapRealm.contextFactory.url = ldap://URL:389 - *#ldapRealm.searchBase = dc=DOMAIN,dc=TLD - *#ldapRealm.ldapAttributeForComparison = objectClass - *# The CSV list of enabled realms. In order to enable a realm, add it to the - *# list below: - * securityManager.realms = $tokenAuthRealm, $ldapRealm - * - * The values above are specific to the deployed LDAP domain. If the defaults - * are not sufficient, alternatives can be derived through enabling - * TRACE level logging. To enable TRACE level - * logging, issue the following command in the karaf shell: - * log:set TRACE org.opendaylight.aaa.shiro.realm.ODLJndiLdapRealm - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - * @see org.apache.shiro.realm.ldap.JndiLdapRealm - * @see Shiro - * documentation - */ -public class ODLJndiLdapRealm extends JndiLdapRealm implements Nameable { - - private static final Logger LOG = LoggerFactory.getLogger(ODLJndiLdapRealm.class); - - /** - * When an LDAP Authorization lookup is made for a user account, a list of - * attributes are returned. The attributes are used to determine LDAP - * grouping, which is equivalent to ODL role(s). The default value is - * set to "objectClass", which is common attribute for LDAP systems. - * The actual value may be configured through setting - * ldapAttributeForComparison. - */ - private static final String DEFAULT_LDAP_ATTRIBUTE_FOR_COMPARISON = "objectClass"; - - /** - * The LDAP nomenclature for user ID, which is used in the authorization query process. - */ - private static final String UID = "uid"; - - /** - * The searchBase for the ldap query, which indicates the LDAP realms to - * search. By default, this is set to the - * super.getUserDnSuffix(). - */ - private String searchBase = super.getUserDnSuffix(); - - /** - * When an LDAP Authorization lookup is made for a user account, a list of - * attributes is returned. The attributes are used to determine LDAP - * grouping, which is equivalent to ODL role(s). The default is set to - * DEFAULT_LDAP_ATTRIBUTE_FOR_COMPARISON. - */ - private String ldapAttributeForComparison = DEFAULT_LDAP_ATTRIBUTE_FOR_COMPARISON; - - /* - * Adds debugging information surrounding creation of ODLJndiLdapRealm - */ - public ODLJndiLdapRealm() { - super(); - final String DEBUG_MESSAGE = "Creating ODLJndiLdapRealm"; - LOG.debug(DEBUG_MESSAGE); - } - - /* - * (non-Javadoc) Overridden to expose important audit trail information for - * accounting. - * - * @see - * org.apache.shiro.realm.ldap.JndiLdapRealm#doGetAuthenticationInfo(org - * .apache.shiro.authc.AuthenticationToken) - */ - @Override - protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) - throws AuthenticationException { - - // Delegates all AuthN lookup responsibility to the super class - try { - final String username = getUsername(token); - logIncomingConnection(username); - return super.doGetAuthenticationInfo(token); - } catch (ClassCastException e) { - LOG.info("Couldn't service the LDAP connection", e); - } - return null; - } - - /** - * Logs an incoming LDAP connection - * - * @param username - * the requesting user - */ - protected void logIncomingConnection(final String username) { - LOG.info("AAA LDAP connection from {}", username); - Accounter.output("AAA LDAP connection from " + username); - } - - /** - * Extracts the username from token - * - * @param token Encoded token which could contain a username - * @return The extracted username - * @throws ClassCastException - * The incoming token is not username/password (i.e., X.509 - * certificate) - */ - public static String getUsername(AuthenticationToken token) throws ClassCastException { - if (null == token) { - return null; - } - return (String) token.getPrincipal(); - } - - @Override - protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { - - AuthorizationInfo ai = null; - try { - ai = this.queryForAuthorizationInfo(principals, getContextFactory()); - } catch (NamingException e) { - LOG.error("Unable to query for AuthZ info", e); - } - return ai; - } - - /** - * extracts a username from principals - * - * @param principals A single principal extracted for the username - * @return The username if possible - * @throws ClassCastException - * the PrincipalCollection contains an element that is not in - * username/password form (i.e., X.509 certificate) - */ - protected String getUsername(final PrincipalCollection principals) throws ClassCastException { - - if (null == principals) { - return null; - } - return (String) getAvailablePrincipal(principals); - } - - /* - * (non-Javadoc) - * - * This method is only called if doGetAuthenticationInfo(...) completes successfully AND - * the requested endpoint has an RBAC restriction. To add an RBAC restriction, edit the - * etc/shiro.ini file and add a url to the url section. E.g., - * - * /** = authcBasic, roles[person] - * - * @see org.apache.shiro.realm.ldap.JndiLdapRealm#queryForAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection, org.apache.shiro.realm.ldap.LdapContextFactory) - */ - @Override - protected AuthorizationInfo queryForAuthorizationInfo(PrincipalCollection principals, - LdapContextFactory ldapContextFactory) throws NamingException { - - AuthorizationInfo authorizationInfo = null; - try { - final String username = getUsername(principals); - final LdapContext ldapContext = ldapContextFactory.getSystemLdapContext(); - final Set roleNames; - - try { - roleNames = getRoleNamesForUser(username, ldapContext); - authorizationInfo = buildAuthorizationInfo(roleNames); - } finally { - LdapUtils.closeContext(ldapContext); - } - } catch (ClassCastException e) { - LOG.error("Unable to extract a valid user", e); - } - return authorizationInfo; - } - - public static AuthorizationInfo buildAuthorizationInfo(final Set roleNames) { - if (null == roleNames) { - return null; - } - return new SimpleAuthorizationInfo(roleNames); - } - - /** - * extracts the Set of roles associated with a user based on the username - * and ldap context (server). - * - * @param username The username for the request - * @param ldapContext The specific system context provided by shiro.ini - * @return A set of roles - * @throws NamingException If the ldap search fails - */ - protected Set getRoleNamesForUser(final String username, final LdapContext ldapContext) - throws NamingException { - - // Stores the role names, which are equivalent to the set of group names extracted - // from the LDAP query. - final Set roleNames = new LinkedHashSet(); - - final SearchControls searchControls = createSearchControls(); - - LOG.debug("Asking the configured LDAP about which groups uid=\"{}\" belongs to using " - + "searchBase=\"{}\" ldapAttributeForComparison=\"{}\"", - username, searchBase, ldapAttributeForComparison); - final NamingEnumeration answer = ldapContext.search(searchBase, - String.format("%s=%s", UID, username), searchControls); - - // Cursor based traversal over the LDAP query result - while (answer.hasMoreElements()) { - final SearchResult searchResult = answer.next(); - final Attributes attrs = searchResult.getAttributes(); - if (attrs != null) { - // Extract the attributes from the LDAP search. - // attrs.getAttr(String) was not chosen, since all attributes should be exposed - // in trace logging should the operator wish to use an alternate attribute. - final NamingEnumeration ae = attrs.getAll(); - while (ae.hasMore()) { - final Attribute attr = ae.next(); - LOG.trace("LDAP returned \"{}\" attribute for \"{}\"", attr.getID(), username); - if (attr.getID().equals(ldapAttributeForComparison)) { - // Stresses the point that LDAP groups are EQUIVALENT to ODL role names - // TODO make this configurable via a Strategy pattern so more interesting mappings can be made - final Collection groupNamesExtractedFromLdap = LdapUtils.getAllAttributeValues(attr); - final Collection roleNamesFromLdapGroups = groupNamesExtractedFromLdap; - if (LOG.isTraceEnabled()) { - for (String roleName : roleNamesFromLdapGroups) { - LOG.trace("Mapped the \"{}\" LDAP group to ODL role for \"{}\"", roleName, username); - } - } - roleNames.addAll(roleNamesFromLdapGroups); - } - } - } - } - return roleNames; - } - - /** - * A utility method to help create the search controls for the LDAP lookup - * - * @return A generic set of search controls for LDAP scoped to subtree - */ - protected static SearchControls createSearchControls() { - SearchControls searchControls = new SearchControls(); - searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); - return searchControls; - } - - @Override - public String getUserDnSuffix() { - return super.getUserDnSuffix(); - } - - /** - * Injected from shiro.ini configuration. - * - * @param searchBase The desired value for searchBase - */ - public void setSearchBase(final String searchBase) { - // public for injection reasons - this.searchBase = searchBase; - } - - /** - * Injected from shiro.ini configuration. - * - * @param ldapAttributeForComparison The attribute from which groups are extracted - */ - public void setLdapAttributeForComparison(final String ldapAttributeForComparison) { - // public for injection reasons - this.ldapAttributeForComparison = ldapAttributeForComparison; - } -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/ODLJndiLdapRealmAuthNOnly.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/ODLJndiLdapRealmAuthNOnly.java deleted file mode 100644 index 978266c5..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/ODLJndiLdapRealmAuthNOnly.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2016 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.shiro.realm; - -import org.apache.shiro.authc.AuthenticationException; -import org.apache.shiro.authc.AuthenticationInfo; -import org.apache.shiro.authc.AuthenticationToken; -import org.apache.shiro.realm.ldap.JndiLdapRealm; -import org.opendaylight.aaa.shiro.accounting.Accounter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Wrapper class for org.apache.shiro.realm.ldap.JndiLdapRealm. - * This implementation disables Authorization so any LDAP user is able to access - * server resources. This is particularly useful for quickly prototyping ODL - * without worrying about resolving LDAP attributes (groups) to OpenDaylight - * roles. - * - * The motivation for subclassing Shiro's implementation is two-fold: 1) Enhance - * the default logging of Shiro. This allows us to more easily log incoming - * connections, providing some security auditing. 2) Provide a common package in - * the classpath for ODL supported Realm implementations (i.e., - * org.opendaylight.aaa.shiro.realm), which consolidates the number - * of Import-Package statements consumers need to enumerate. For - * example, the netconf project only needs to import - * org.opendaylight.aaa.shiro.realm, and does not need to worry - * about importing Shiro packages. - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - * - */ -public class ODLJndiLdapRealmAuthNOnly extends JndiLdapRealm { - - private static final Logger LOG = LoggerFactory.getLogger(ODLJndiLdapRealmAuthNOnly.class); - - private static final String LDAP_CONNECTION_MESSAGE = "AAA LDAP connection from "; - - /* - * Adds debugging information surrounding creation of ODLJndiLdapRealm - */ - public ODLJndiLdapRealmAuthNOnly() { - super(); - LOG.debug("Creating ODLJndiLdapRealmAuthNOnly"); - } - - /* - * (non-Javadoc) Overridden to expose important audit trail information for - * accounting. - * - * @see - * org.apache.shiro.realm.ldap.JndiLdapRealm#doGetAuthenticationInfo(org - * .apache.shiro.authc.AuthenticationToken) - */ - @Override - protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) - throws AuthenticationException { - - try { - final String username = getUsername(token); - logIncomingConnection(username); - return super.doGetAuthenticationInfo(token); - } catch (ClassCastException e) { - LOG.info("Couldn't service the LDAP connection", e); - } - return null; - } - - /** - * Logs an incoming LDAP connection - * - * @param username - * the requesting user - */ - protected void logIncomingConnection(final String username) { - final String message = LDAP_CONNECTION_MESSAGE + username; - LOG.info(message); - Accounter.output(message); - } - - /** - * Extracts the username from token - * - * @param token Which possibly contains a username - * @return the username if it can be extracted - * @throws ClassCastException - * The incoming token is not username/password (i.e., X.509 - * certificate) - */ - public static String getUsername(AuthenticationToken token) throws ClassCastException { - if (null == token) { - return null; - } - return (String) token.getPrincipal(); - } -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/RadiusRealm.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/RadiusRealm.java deleted file mode 100644 index 51d4bfbf..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/RadiusRealm.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.aaa.shiro.realm; - -import org.apache.shiro.authc.AuthenticationException; -import org.apache.shiro.authc.AuthenticationInfo; -import org.apache.shiro.authc.AuthenticationToken; -import org.apache.shiro.authz.AuthorizationInfo; -import org.apache.shiro.realm.AuthorizingRealm; -import org.apache.shiro.subject.PrincipalCollection; - -/** - * Implementation of a Radius AuthorizingRealm. - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - */ -public class RadiusRealm extends AuthorizingRealm { - - @Override - protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) { - // TODO use JRadius to extract Authorization Info - return null; - } - - @Override - protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) - throws AuthenticationException { - // TODO use JRadius to extract Authentication Info - return null; - } - -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/TACACSRealm.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/TACACSRealm.java deleted file mode 100644 index 38d7d91a..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/TACACSRealm.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.shiro.realm; - -import org.apache.shiro.authc.AuthenticationException; -import org.apache.shiro.authc.AuthenticationInfo; -import org.apache.shiro.authc.AuthenticationToken; -import org.apache.shiro.authz.AuthorizationInfo; -import org.apache.shiro.realm.AuthorizingRealm; -import org.apache.shiro.subject.PrincipalCollection; - -/** - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - * - */ -public class TACACSRealm extends AuthorizingRealm { - - @Override - protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) { - // TODO Extract AuthorizationInfo using JNetLib - return null; - } - - @Override - protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) - throws AuthenticationException { - // TODO Extract AuthenticationInfo using JNetLib - return null; - } - -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/TokenAuthRealm.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/TokenAuthRealm.java deleted file mode 100644 index f9ae5051..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/realm/TokenAuthRealm.java +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.shiro.realm; - -import com.google.common.base.Strings; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.shiro.authc.AuthenticationException; -import org.apache.shiro.authc.AuthenticationInfo; -import org.apache.shiro.authc.AuthenticationToken; -import org.apache.shiro.authc.SimpleAuthenticationInfo; -import org.apache.shiro.authc.UsernamePasswordToken; -import org.apache.shiro.authz.AuthorizationInfo; -import org.apache.shiro.authz.SimpleAuthorizationInfo; -import org.apache.shiro.codec.Base64; -import org.apache.shiro.realm.AuthorizingRealm; -import org.apache.shiro.subject.PrincipalCollection; -import org.opendaylight.aaa.api.Authentication; -import org.opendaylight.aaa.api.TokenAuth; -import org.opendaylight.aaa.basic.HttpBasicAuth; -import org.opendaylight.aaa.sts.ServiceLocator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * TokenAuthRealm is an adapter between the AAA shiro subsystem and the existing - * TokenAuth mechanisms. Thus, one can enable use of - * IDMStore and IDMMDSALStore. - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - */ -public class TokenAuthRealm extends AuthorizingRealm { - - private static final String USERNAME_DOMAIN_SEPARATOR = "@"; - - /** - * The unique identifying name for TokenAuthRealm - */ - private static final String TOKEN_AUTH_REALM_DEFAULT_NAME = "TokenAuthRealm"; - - /** - * The message that is displayed if no TokenAuth interface is - * available yet - */ - private static final String AUTHENTICATION_SERVICE_UNAVAILABLE_MESSAGE = "{\"error\":\"Authentication service unavailable\"}"; - - /** - * The message that is displayed if credentials are missing or malformed - */ - private static final String FATAL_ERROR_DECODING_CREDENTIALS = "{\"error\":\"Unable to decode credentials\"}"; - - /** - * The message that is displayed if non-Basic Auth is attempted - */ - private static final String FATAL_ERROR_BASIC_AUTH_ONLY = "{\"error\":\"Only basic authentication is supported by TokenAuthRealm\"}"; - - /** - * The purposefully generic message displayed if TokenAuth is - * unable to validate the given credentials - */ - private static final String UNABLE_TO_AUTHENTICATE = "{\"error\":\"Could not authenticate\"}"; - - private static final Logger LOG = LoggerFactory.getLogger(TokenAuthRealm.class); - - public TokenAuthRealm() { - super(); - super.setName(TOKEN_AUTH_REALM_DEFAULT_NAME); - } - - /* - * (non-Javadoc) - * - * Roles are derived from TokenAuth.authenticate(). Shiro roles - * are identical to existing IDM roles. - * - * @see - * org.apache.shiro.realm.AuthorizingRealm#doGetAuthorizationInfo(org.apache - * .shiro.subject.PrincipalCollection) - */ - @Override - protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { - final Object primaryPrincipal = principalCollection.getPrimaryPrincipal(); - final ODLPrincipal odlPrincipal; - try { - odlPrincipal = (ODLPrincipal) primaryPrincipal; - return new SimpleAuthorizationInfo(odlPrincipal.getRoles()); - } catch(ClassCastException e) { - LOG.error("Couldn't decode authorization request", e); - } - return new SimpleAuthorizationInfo(); - } - - /** - * Bridge new to old style TokenAuth interface. - * - * @param username The request username - * @param password The request password - * @param domain The request domain - * @return username:password:domain - */ - static String getUsernamePasswordDomainString(final String username, final String password, - final String domain) { - return username + HttpBasicAuth.AUTH_SEP + password + HttpBasicAuth.AUTH_SEP + domain; - } - - /** - * - * @param credentialToken - * @return Base64 encoded token - */ - static String getEncodedToken(final String credentialToken) { - return Base64.encodeToString(credentialToken.getBytes()); - } - - /** - * - * @param encodedToken - * @return Basic encodedToken - */ - static String getTokenAuthHeader(final String encodedToken) { - return HttpBasicAuth.BASIC_PREFIX + encodedToken; - } - - /** - * - * @param tokenAuthHeader - * @return a map with the basic auth header - */ - Map> formHeadersWithToken(final String tokenAuthHeader) { - final Map> headers = new HashMap>(); - final List headerValue = new ArrayList(); - headerValue.add(tokenAuthHeader); - headers.put(HttpBasicAuth.AUTH_HEADER, headerValue); - return headers; - } - - /** - * Adapter between basic authentication mechanism and existing - * TokenAuth interface. - * - * @param username Username from the request - * @param password Password from the request - * @param domain Domain from the request - * @return input map for TokenAuth.validate() - */ - Map> formHeaders(final String username, final String password, - final String domain) { - String usernamePasswordToken = getUsernamePasswordDomainString(username, password, domain); - String encodedToken = getEncodedToken(usernamePasswordToken); - String tokenAuthHeader = getTokenAuthHeader(encodedToken); - return formHeadersWithToken(tokenAuthHeader); - } - - /** - * Adapter to check for available TokenAuth implementations. - * - * @return - */ - boolean isTokenAuthAvailable() { - return ServiceLocator.getInstance().getAuthenticationService() != null; - } - - /* - * (non-Javadoc) - * - * Authenticates against any TokenAuth registered with the - * ServiceLocator - * - * @see - * org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org - * .apache.shiro.authc.AuthenticationToken) - */ - @Override - protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) - throws AuthenticationException { - - String username = ""; - String password = ""; - String domain = HttpBasicAuth.DEFAULT_DOMAIN; - - try { - final String qualifiedUser = extractUsername(authenticationToken); - if (qualifiedUser.contains(USERNAME_DOMAIN_SEPARATOR)) { - final String [] qualifiedUserArray = qualifiedUser.split(USERNAME_DOMAIN_SEPARATOR); - try { - username = qualifiedUserArray[0]; - domain = qualifiedUserArray[1]; - } catch (ArrayIndexOutOfBoundsException e) { - LOG.trace("Couldn't parse domain from {}; trying without one", - qualifiedUser, e); - } - } else { - username = qualifiedUser; - } - password = extractPassword(authenticationToken); - - } catch (NullPointerException e) { - throw new AuthenticationException(FATAL_ERROR_DECODING_CREDENTIALS, e); - } catch (ClassCastException e) { - throw new AuthenticationException(FATAL_ERROR_BASIC_AUTH_ONLY, e); - } - - // check to see if there are TokenAuth implementations available - if (!isTokenAuthAvailable()) { - throw new AuthenticationException(AUTHENTICATION_SERVICE_UNAVAILABLE_MESSAGE); - } - - // if the password is empty, this is an OAuth2 request, not a Basic HTTP - // Auth request - if (!Strings.isNullOrEmpty(password)) { - if (ServiceLocator.getInstance().getAuthenticationService().isAuthEnabled()) { - Map> headers = formHeaders(username, password, domain); - // iterate over TokenAuth implementations and - // attempt to - // authentication with each one - final List tokenAuthCollection = ServiceLocator.getInstance() - .getTokenAuthCollection(); - for (TokenAuth ta : tokenAuthCollection) { - try { - LOG.debug("Authentication attempt using {}", ta.getClass().getName()); - final Authentication auth = ta.validate(headers); - if (auth != null) { - LOG.debug("Authentication attempt successful"); - ServiceLocator.getInstance().getAuthenticationService().set(auth); - final ODLPrincipal odlPrincipal = ODLPrincipal.createODLPrincipal(auth); - return new SimpleAuthenticationInfo(odlPrincipal, password.toCharArray(), - getName()); - } - } catch (AuthenticationException ae) { - LOG.debug("Authentication attempt unsuccessful"); - throw new AuthenticationException(UNABLE_TO_AUTHENTICATE, ae); - } - } - } - } - - // extract the authentication token and attempt validation of the token - final String token = extractUsername(authenticationToken); - final Authentication auth; - try { - auth = validate(token); - if (auth != null) { - final ODLPrincipal odlPrincipal = ODLPrincipal.createODLPrincipal(auth); - return new SimpleAuthenticationInfo(odlPrincipal, "", getName()); - } - } catch (AuthenticationException e) { - LOG.debug("Unknown OAuth2 Token Access Request", e); - } - - LOG.debug("Authentication failed: exhausted TokenAuth resources"); - return null; - } - - private Authentication validate(final String token) { - Authentication auth = ServiceLocator.getInstance().getTokenStore().get(token); - if (auth == null) { - throw new AuthenticationException("Could not validate the token " + token); - } else { - ServiceLocator.getInstance().getAuthenticationService().set(auth); - } - return auth; - } - - /** - * extract the username from an AuthenticationToken - * - * @param authenticationToken - * @return - * @throws ClassCastException - * @throws NullPointerException - */ - static String extractUsername(final AuthenticationToken authenticationToken) - throws ClassCastException, NullPointerException { - - return (String) authenticationToken.getPrincipal(); - } - - /** - * extract the password from an AuthenticationToken - * - * @param authenticationToken - * @return - * @throws ClassCastException - * @throws NullPointerException - */ - static String extractPassword(final AuthenticationToken authenticationToken) - throws ClassCastException, NullPointerException { - - final UsernamePasswordToken upt = (UsernamePasswordToken) authenticationToken; - return new String(upt.getPassword()); - } - - /** - * Since TokenAuthRealm is an AuthorizingRealm, it supports - * individual steps for authentication and authorization. In ODL's existing TokenAuth - * mechanism, authentication and authorization are currently done in a single monolithic step. - * ODLPrincipal is abstracted as a DTO between the two steps. It fulfills the - * responsibility of a Principal, since it contains identification information - * but no credential information. - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - */ - private static class ODLPrincipal { - - private final String username; - private final String domain; - private final String userId; - private final Set roles; - - private ODLPrincipal(final String username, final String domain, final String userId, final Set roles) { - this.username = username; - this.domain = domain; - this.userId = userId; - this.roles = roles; - } - - /** - * A static factory method to create ODLPrincipal instances. - * - * @param username The authenticated user - * @param domain The domain username belongs to. - * @param userId The unique key for username - * @param roles The roles associated with username@domain - * @return A Principal for the given session; essentially a DTO. - */ - static ODLPrincipal createODLPrincipal(final String username, final String domain, - final String userId, final Set roles) { - - return new ODLPrincipal(username, domain, userId, roles); - } - - /** - * A static factory method to create ODLPrincipal instances. - * - * @param auth Contains identifying information for the particular request. - * @return A Principal for the given session; essentially a DTO. - */ - static ODLPrincipal createODLPrincipal(final Authentication auth) { - return createODLPrincipal(auth.user(), auth.domain(), auth.userId(), auth.roles()); - } - - String getUsername() { - return this.username; - } - - String getDomain() { - return this.domain; - } - - String getUserId() { - return this.userId; - } - - Set getRoles() { - return this.roles; - } - } -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/web/env/KarafIniWebEnvironment.java b/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/web/env/KarafIniWebEnvironment.java deleted file mode 100644 index acf4022c..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/java/org/opendaylight/aaa/shiro/web/env/KarafIniWebEnvironment.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.aaa.shiro.web.env; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.Collection; -import org.apache.shiro.config.Ini; -import org.apache.shiro.config.Ini.Section; -import org.apache.shiro.web.env.IniWebEnvironment; -import org.opendaylight.aaa.shiro.accounting.Accounter; -import org.opendaylight.aaa.shiro.authorization.DefaultRBACRules; -import org.opendaylight.aaa.shiro.authorization.RBACRule; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Identical to IniWebEnvironment except the Ini is loaded from - * $KARAF_HOME/etc/shiro.ini. - * - * @author Ryan Goulding (ryandgoulding@gmail.com) - * - */ -public class KarafIniWebEnvironment extends IniWebEnvironment { - - private static final Logger LOG = LoggerFactory.getLogger(KarafIniWebEnvironment.class); - public static final String DEFAULT_SHIRO_INI_FILE = "etc/shiro.ini"; - public static final String SHIRO_FILE_PREFIX = "file:/"; - - public KarafIniWebEnvironment() { - } - - @Override - public void init() { - // Initialize the Shiro environment from etc/shiro.ini then delegate to - // the parent class - Ini ini; - try { - ini = createDefaultShiroIni(); - // appendCustomIniRules(ini); - setIni(ini); - } catch (FileNotFoundException e) { - final String ERROR_MESSAGE = "Could not find etc/shiro.ini"; - LOG.error(ERROR_MESSAGE, e); - } - super.init(); - } - - /** - * A hook for installing custom default RBAC rules for security purposes. - * - * @param ini - */ - private void appendCustomIniRules(final Ini ini) { - final String INSTALL_MESSAGE = "Installing the RBAC rule: %s"; - Section urlSection = getOrCreateUrlSection(ini); - Collection rbacRules = DefaultRBACRules.getInstance().getRBACRules(); - for (RBACRule rbacRule : rbacRules) { - urlSection.put(rbacRule.getUrlPattern(), rbacRule.getRolesInShiroFormat()); - Accounter.output(String.format(INSTALL_MESSAGE, rbacRule)); - } - } - - /** - * Extracts the url section of the Ini file, or creates one if it doesn't - * already exist - * - * @param ini - * @return - */ - private Section getOrCreateUrlSection(final Ini ini) { - final String URL_SECTION_TITLE = "urls"; - Section urlSection = ini.getSection(URL_SECTION_TITLE); - if (urlSection == null) { - LOG.debug("shiro.ini does not contain a [urls] section; creating one"); - urlSection = ini.addSection(URL_SECTION_TITLE); - } else { - LOG.debug("shiro.ini contains a [urls] section; appending rules to existing"); - } - return urlSection; - } - - /** - * - * @return Ini associated with $KARAF_HOME/etc/shiro.ini - * @throws FileNotFoundException - */ - static Ini createDefaultShiroIni() throws FileNotFoundException { - return createShiroIni(DEFAULT_SHIRO_INI_FILE); - } - - /** - * - * @param path - * the file path, which is either absolute or relative to - * $KARAF_HOME - * @return Ini loaded from path - */ - static Ini createShiroIni(final String path) throws FileNotFoundException { - File f = new File(path); - Ini ini = new Ini(); - final String fileBasedIniPath = createFileBasedIniPath(f.getAbsolutePath()); - ini.loadFromPath(fileBasedIniPath); - return ini; - } - - /** - * - * @param path - * the file path, which is either absolute or relative to - * $KARAF_HOME - * @return file:/$KARAF_HOME/etc/shiro.ini - */ - static String createFileBasedIniPath(final String path) { - String fileBasedIniPath = SHIRO_FILE_PREFIX + path; - LOG.debug(fileBasedIniPath); - return fileBasedIniPath; - } -} diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/resources/WEB-INF/web.xml b/odl-aaa-moon/aaa/aaa-shiro/src/main/resources/WEB-INF/web.xml deleted file mode 100644 index 63288c23..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/resources/WEB-INF/web.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - MOON - org.opendaylight.aaa.shiro.moon.MoonTokenEndpoint - 1 - - - - MOON - /token - - - MOON - /revoke - - - MOON - /validate - - - MOON - /* - - - - - shiroEnvironmentClass - org.opendaylight.aaa.shiro.web.env.KarafIniWebEnvironment - - - - org.apache.shiro.web.env.EnvironmentLoaderListener - - - - ShiroFilter - org.opendaylight.aaa.shiro.filters.AAAFilter - - - - ShiroFilter - /* - - \ No newline at end of file diff --git a/odl-aaa-moon/aaa/aaa-shiro/src/main/resources/shiro.ini b/odl-aaa-moon/aaa/aaa-shiro/src/main/resources/shiro.ini deleted file mode 100644 index b48abe96..00000000 --- a/odl-aaa-moon/aaa/aaa-shiro/src/main/resources/shiro.ini +++ /dev/null @@ -1,106 +0,0 @@ -# -# Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved. -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v1.0 which accompanies this distribution, -# and is available at http://www.eclipse.org/legal/epl-v10.html -# - -############################################################################### -# shiro.ini # -# # -# Configuration of OpenDaylight's aaa-shiro feature. Provided Realm # -# implementations include: # -# - TokenAuthRealm (enabled by default) # -# - ODLJndiLdapRealm (disabled by default) # -# - ODLJndiLdapRealmAuthNOnly (disabled by default) # -# Basic user configuration through shiro.ini is disabled for security # -# purposes. # -############################################################################### - - - -[main] -############################################################################### -# realms # -# # -# This section is dedicated to setting up realms for OpenDaylight. Realms # -# are essentially different methods for providing AAA. ODL strives to provide# -# highly-configurable AAA by providing pluggable infrastructure. By deafult, # -# TokenAuthRealm is enabled out of the box (which bridges to the existing AAA # -# mechanisms). More than one realm can be enabled, and the realms are # -# tried Round-Robin until: # -# 1) a realm successfully authenticates the incoming request # -# 2) all realms are exhausted, and 401 is returned # -############################################################################### - -# ODL provides a few LDAP implementations, which are disabled out of the box. -# ODLJndiLdapRealm includes authorization functionality based on LDAP elements -# extracted through and LDAP search. This requires a bit of knowledge about -# how your LDAP system is setup. An example is provided below: -#ldapRealm = org.opendaylight.aaa.shiro.realm.ODLJndiLdapRealm -#ldapRealm.userDnTemplate = uid={0},ou=People,dc=DOMAIN,dc=TLD -#ldapRealm.contextFactory.url = ldap://:389 -#ldapRealm.searchBase = dc=DOMAIN,dc=TLD -#ldapRealm.ldapAttributeForComparison = objectClass - -# ODL also provides ODLJndiLdapRealmAuthNOnly. Essentially, this allows -# access through AAAFilter to any user that can authenticate against the -# provided LDAP server. -#ldapRealm = org.opendaylight.aaa.shiro.realm.ODLJndiLdapRealmAuthNOnly -#ldapRealm.userDnTemplate = uid={0},ou=People,dc=DOMAIN,dc=TLD -#ldapRealm.contextFactory.url = ldap://:389 - -# Bridge to existing h2/idmlight/mdsal authentication/authorization mechanisms. -# This realm is enabled by default, and utilizes h2-store by default. -#tokenAuthRealm = org.opendaylight.aaa.shiro.realm.TokenAuthRealm -# Defining moon realm -moonAuthRealm = org.opendaylight.aaa.shiro.realm.MoonRealm - -# The CSV list of enabled realms. In order to enable a realm, add it to the -# list below: -#securityManager.realms = $tokenAuthRealm -# Configure the Shiro Security Manager to use Moon Realm -securityManager.realms = $moonAuthRealm - -# adds a custom AuthenticationFilter to support OAuth2 for backwards -# compatibility. To disable OAuth2 access, just comment out the next line -# and authcBasic will default to BasicHttpAuthenticationFilter, a -# Shiro-provided class. -authcBasic = org.opendaylight.aaa.shiro.filters.ODLHttpAuthenticationFilter -# OAuth2 Filer for moon token AuthN -rest = org.opendaylight.aaa.shiro.filters.MoonOAuthFilter - -# add in AuthenticationListener, a Listener that records whether -# authentication attempts are successful or unsuccessful. This audit -# information is disabled by default, to avoid log flooding. To enable, -# issue the following in karaf: -# >log:set DEBUG org.opendaylight.aaa.shiro.filters.AuthenticationListener -accountingListener = org.opendaylight.aaa.shiro.filters.AuthenticationListener -securityManager.authenticator.authenticationListeners = $accountingListener - - - -[urls] -############################################################################### -# url authorization section # -# # -# This section is dedicated to defining url-based authorization according to: # -# http://shiro.apache.org/web.html # -############################################################################### - -# Restrict AAA endpoints to users w/ admin role -/v1/users/** = authcBasic -/v1/domains/** = authcBasic -/v1/roles/** = authcBasic - -#Filter OAuth2 request$ -/token = rest - -# General access through AAAFilter requires valid credentials (AuthN only). -/** = authcBasic - -# Access to the credential store is limited to the valid users who have the -# admin role. The following line is only needed if the mdsal store is enabled -#(the mdsal store is disabled by default). -/config/aaa-authn-model** = authcBasic,roles[admin] -- cgit 1.2.3-korg