From ee5585e96c7c7d82782141943ab196472da084a2 Mon Sep 17 00:00:00 2001 From: Endi Sukma Dewata Date: Fri, 1 Feb 2013 13:05:38 -0500 Subject: WIP --- base/ca/shared/webapps/ca/WEB-INF/acl.properties | 14 ++ base/ca/shared/webapps/ca/WEB-INF/auth.properties | 16 +-- .../ca/CertificateAuthorityApplication.java | 4 +- .../com/netscape/certsrv/acls/ACLInterceptor.java | 16 +-- .../certsrv/authentication/AuthInterceptor.java | 152 +++++++++++++++++++++ .../certsrv/authentication/AuthMapping.java | 31 +++++ .../cms/servlet/csadmin/ConfigurationUtils.java | 1 + base/kra/shared/webapps/kra/WEB-INF/acl.properties | 12 ++ .../kra/shared/webapps/kra/WEB-INF/auth.properties | 12 -- .../kra/KeyRecoveryAuthorityApplication.java | 4 +- .../shared/webapps/ocsp/WEB-INF/acl.properties | 10 ++ .../shared/webapps/ocsp/WEB-INF/auth.properties | 10 -- .../src/com/netscape/ocsp/OCSPApplication.java | 4 +- base/tks/shared/webapps/tks/WEB-INF/acl.properties | 10 ++ .../tks/shared/webapps/tks/WEB-INF/auth.properties | 10 -- base/tks/src/com/netscape/tks/TKSApplication.java | 4 +- 16 files changed, 255 insertions(+), 55 deletions(-) create mode 100644 base/ca/shared/webapps/ca/WEB-INF/acl.properties create mode 100644 base/common/src/com/netscape/certsrv/authentication/AuthInterceptor.java create mode 100644 base/common/src/com/netscape/certsrv/authentication/AuthMapping.java create mode 100644 base/kra/shared/webapps/kra/WEB-INF/acl.properties delete mode 100644 base/kra/shared/webapps/kra/WEB-INF/auth.properties create mode 100644 base/ocsp/shared/webapps/ocsp/WEB-INF/acl.properties delete mode 100644 base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties create mode 100644 base/tks/shared/webapps/tks/WEB-INF/acl.properties delete mode 100644 base/tks/shared/webapps/tks/WEB-INF/auth.properties diff --git a/base/ca/shared/webapps/ca/WEB-INF/acl.properties b/base/ca/shared/webapps/ca/WEB-INF/acl.properties new file mode 100644 index 000000000..2e8283107 --- /dev/null +++ b/base/ca/shared/webapps/ca/WEB-INF/acl.properties @@ -0,0 +1,14 @@ +# Restful API authorization mapping info +# +# Format: +# , +# ex: admin.users = certServer.ca.users,read + +account.login = certServer.ca.account,login +account.logout = certServer.ca.account,logout +admin.users = certServer.ca.users,execute +admin.groups = certServer.ca.groups,execute +admin.kraconnector = certServer.ca.connectorInfo,modify +agent.certrequests = certServer.ca.certrequests,execute +agent.certs = certServer.ca.certs,execute +securityDomain.installToken = certServer.securitydomain.domainxml,read diff --git a/base/ca/shared/webapps/ca/WEB-INF/auth.properties b/base/ca/shared/webapps/ca/WEB-INF/auth.properties index b73b9ac10..54fbf2709 100644 --- a/base/ca/shared/webapps/ca/WEB-INF/auth.properties +++ b/base/ca/shared/webapps/ca/WEB-INF/auth.properties @@ -1,14 +1,8 @@ -# Restful API auth/authz mapping info +# Restful API auth mapping info # # Format: -# = , -# ex: admin.users = certServer.ca.users,read +# = +# ex: admin.users = anonymous,basic,client-cert,any -account.login = certServer.ca.account,login -account.logout = certServer.ca.account,logout -admin.users = certServer.ca.users,execute -admin.groups = certServer.ca.groups,execute -admin.kraconnector = certServer.ca.connectorInfo,modify -agent.certrequests = certServer.ca.certrequests,execute -agent.certs = certServer.ca.certs,execute -securityDomain.installToken = certServer.securitydomain.domainxml,read +default = any +securityDomain.installToken = basic diff --git a/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java b/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java index 14b44e5d7..35e93811c 100644 --- a/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java +++ b/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java @@ -7,6 +7,7 @@ import javax.ws.rs.core.Application; import com.netscape.certsrv.acls.ACLInterceptor; import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthInterceptor; import com.netscape.certsrv.base.EBaseException; import com.netscape.certsrv.base.IConfigStore; import com.netscape.certsrv.base.PKIException; @@ -85,7 +86,8 @@ public class CertificateAuthorityApplication extends Application { // exception mapper classes.add(PKIException.Mapper.class); - // ACL interceptor + // interceptors + singletons.add(new AuthInterceptor()); singletons.add(new ACLInterceptor()); } diff --git a/base/common/src/com/netscape/certsrv/acls/ACLInterceptor.java b/base/common/src/com/netscape/certsrv/acls/ACLInterceptor.java index c30740260..dd4985eab 100644 --- a/base/common/src/com/netscape/certsrv/acls/ACLInterceptor.java +++ b/base/common/src/com/netscape/certsrv/acls/ACLInterceptor.java @@ -54,7 +54,7 @@ import com.netscape.cmscore.realm.PKIPrincipal; @Precedence("SECURITY") public class ACLInterceptor implements PreProcessInterceptor { - Properties authProperties; + Properties aclProperties; @Context ServletContext servletContext; @@ -62,13 +62,13 @@ public class ACLInterceptor implements PreProcessInterceptor { @Context SecurityContext securityContext; - public synchronized void loadAuthProperties() throws IOException { + public synchronized void loadACLProperties() throws IOException { - if (authProperties != null) return; + if (aclProperties != null) return; - URL url = servletContext.getResource("/WEB-INF/auth.properties"); - authProperties = new Properties(); - authProperties.load(url.openStream()); + URL url = servletContext.getResource("/WEB-INF/acl.properties"); + aclProperties = new Properties(); + aclProperties.load(url.openStream()); } @Override @@ -111,10 +111,10 @@ public class ACLInterceptor implements PreProcessInterceptor { } try { - loadAuthProperties(); + loadACLProperties(); String name = aclMapping.value(); - String value = authProperties.getProperty(name); + String value = aclProperties.getProperty(name); // If no property defined, allow request. if (value == null) return null; diff --git a/base/common/src/com/netscape/certsrv/authentication/AuthInterceptor.java b/base/common/src/com/netscape/certsrv/authentication/AuthInterceptor.java new file mode 100644 index 000000000..249828d32 --- /dev/null +++ b/base/common/src/com/netscape/certsrv/authentication/AuthInterceptor.java @@ -0,0 +1,152 @@ +//--- BEGIN COPYRIGHT BLOCK --- +//This program is free software; you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation; version 2 of the License. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License along +//with this program; if not, write to the Free Software Foundation, Inc., +//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//(C) 2013 Red Hat, Inc. +//All rights reserved. +//--- END COPYRIGHT BLOCK --- +package com.netscape.certsrv.authentication; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URL; +import java.security.Principal; +import java.util.Collection; +import java.util.HashSet; +import java.util.Properties; + +import javax.servlet.ServletContext; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.SecurityContext; +import javax.ws.rs.ext.Provider; + +import org.jboss.resteasy.annotations.interception.Precedence; +import org.jboss.resteasy.annotations.interception.ServerInterceptor; +import org.jboss.resteasy.core.ResourceMethod; +import org.jboss.resteasy.core.ServerResponse; +import org.jboss.resteasy.spi.Failure; +import org.jboss.resteasy.spi.HttpRequest; +import org.jboss.resteasy.spi.interception.PreProcessInterceptor; + +import com.netscape.certsrv.base.ForbiddenException; +import com.netscape.cmscore.realm.PKIPrincipal; + + +/** + * @author Endi S. Dewata + */ +@Provider +@ServerInterceptor +@Precedence("SECURITY") +public class AuthInterceptor implements PreProcessInterceptor { + + Properties authProperties; + + @Context + ServletContext servletContext; + + @Context + SecurityContext securityContext; + + public synchronized void loadAuthProperties() throws IOException { + + if (authProperties != null) return; + + URL url = servletContext.getResource("/WEB-INF/auth.properties"); + authProperties = new Properties(); + authProperties.load(url.openStream()); + } + + @Override + public ServerResponse preProcess( + HttpRequest request, + ResourceMethod resourceMethod + ) throws Failure, ForbiddenException { + + Class clazz = resourceMethod.getResourceClass(); + Method method = resourceMethod.getMethod(); + System.out.println("AuthInterceptor: invoking "+clazz.getSimpleName()+"."+method.getName()+"()"); + + // Get authentication mapping for the method. + System.out.println("AuthInterceptor: checking method mapping"); + AuthMapping authMapping = method.getAnnotation(AuthMapping.class); + + // If not available, get authentication mapping for the class. + if (authMapping == null) { + System.out.println("AuthInterceptor: checking class mapping"); + authMapping = clazz.getAnnotation(AuthMapping.class); + } + + String name; + if (authMapping == null) { + // If not available, use the default mapping. + name = "default"; + } else { + // Get the method label + name = authMapping.value(); + } + + System.out.println("AuthInterceptor: mapping ID: "+name); + + try { + loadAuthProperties(); + + String value = authProperties.getProperty(name); + Collection authMethods = new HashSet(); + if (value != null) { + for (String v : value.split(",")) { + authMethods.add(v.trim()); + } + } + + System.out.println("AuthInterceptor: auth methods: "+authMethods); + + Principal principal = securityContext.getUserPrincipal(); + + // If unauthenticated, reject request. + if (principal == null) { + if (authMethods.isEmpty() || authMethods.contains("anonymous") || authMethods.contains("any")) { + System.out.println("AuthInterceptor: anonymous allowed"); + return null; + } + System.out.println("AuthInterceptor: anonymous not allowed"); + throw new ForbiddenException("No user principal provided."); + } + + // If unrecognized principal, reject request. + if (!(principal instanceof PKIPrincipal)) { + System.out.println("AuthInterceptor: invalid principal"); + throw new ForbiddenException("Invalid user principal"); + } + + PKIPrincipal pkiPrincipal = (PKIPrincipal)principal; + IAuthToken authToken = pkiPrincipal.getAuthToken(); + + // If missing auth token, reject request. + if (authToken == null) { + System.out.println("AuthInterceptor: missing authentication token"); + throw new ForbiddenException("No authentication token present."); + } + + Object authManager = authToken.get(AuthToken.TOKEN_AUTHMGR_INST_NAME); + System.out.println("Authentication manager: "+authManager); + + // Allow request. + return null; + + } catch (IOException e) { + e.printStackTrace(); + throw new Failure(e); + } + } +} diff --git a/base/common/src/com/netscape/certsrv/authentication/AuthMapping.java b/base/common/src/com/netscape/certsrv/authentication/AuthMapping.java new file mode 100644 index 000000000..e00cc9d63 --- /dev/null +++ b/base/common/src/com/netscape/certsrv/authentication/AuthMapping.java @@ -0,0 +1,31 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2013 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package com.netscape.certsrv.authentication; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + + +/** + * @author Endi S. Dewata + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface AuthMapping { + public String value(); +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java index a7ec566ce..b7abe268b 100644 --- a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java @@ -325,6 +325,7 @@ public class ConfigurationUtils { config.setServerURI("https://" + sdhost + ":" + sdport + "/ca"); config.setUsername(user); config.setPassword(passwd); + config.setInstanceCreationMode(true); PKIConnection connection = new PKIConnection(config); AccountClient accountClient = new AccountClient(connection); diff --git a/base/kra/shared/webapps/kra/WEB-INF/acl.properties b/base/kra/shared/webapps/kra/WEB-INF/acl.properties new file mode 100644 index 000000000..567747f5b --- /dev/null +++ b/base/kra/shared/webapps/kra/WEB-INF/acl.properties @@ -0,0 +1,12 @@ +# Restful API auth/authz mapping info +# +# Format: +# = , +# ex: admin.users = certServer.ca.users,read + +account.login = certServer.kra.account,login +account.logout = certServer.kra.account,logout +admin.users = certServer.kra.users,execute +admin.groups = certServer.kra.groups,execute +agent.keys = certServer.kra.keys,execute +agent.keyrequests = certServer.kra.keyrequests,execute diff --git a/base/kra/shared/webapps/kra/WEB-INF/auth.properties b/base/kra/shared/webapps/kra/WEB-INF/auth.properties deleted file mode 100644 index 567747f5b..000000000 --- a/base/kra/shared/webapps/kra/WEB-INF/auth.properties +++ /dev/null @@ -1,12 +0,0 @@ -# Restful API auth/authz mapping info -# -# Format: -# = , -# ex: admin.users = certServer.ca.users,read - -account.login = certServer.kra.account,login -account.logout = certServer.kra.account,logout -admin.users = certServer.kra.users,execute -admin.groups = certServer.kra.groups,execute -agent.keys = certServer.kra.keys,execute -agent.keyrequests = certServer.kra.keyrequests,execute diff --git a/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java b/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java index 0ed23f697..d256c0438 100644 --- a/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java +++ b/base/kra/src/com/netscape/kra/KeyRecoveryAuthorityApplication.java @@ -6,6 +6,7 @@ import java.util.Set; import javax.ws.rs.core.Application; import com.netscape.certsrv.acls.ACLInterceptor; +import com.netscape.certsrv.authentication.AuthInterceptor; import com.netscape.certsrv.base.PKIException; import com.netscape.cms.servlet.account.AccountService; import com.netscape.cms.servlet.admin.GroupMemberService; @@ -46,7 +47,8 @@ public class KeyRecoveryAuthorityApplication extends Application { // exception mapper classes.add(PKIException.Mapper.class); - // ACL interceptor + // interceptors + singletons.add(new AuthInterceptor()); singletons.add(new ACLInterceptor()); } diff --git a/base/ocsp/shared/webapps/ocsp/WEB-INF/acl.properties b/base/ocsp/shared/webapps/ocsp/WEB-INF/acl.properties new file mode 100644 index 000000000..cd2e14058 --- /dev/null +++ b/base/ocsp/shared/webapps/ocsp/WEB-INF/acl.properties @@ -0,0 +1,10 @@ +# Restful API auth/authz mapping info +# +# Format: +# = , +# ex: admin.users = certServer.ca.users,read + +account.login = certServer.ocsp.account,login +account.logout = certServer.ocsp.account,logout +admin.users = certServer.ocsp.users,execute +admin.groups = certServer.ocsp.groups,execute diff --git a/base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties b/base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties deleted file mode 100644 index cd2e14058..000000000 --- a/base/ocsp/shared/webapps/ocsp/WEB-INF/auth.properties +++ /dev/null @@ -1,10 +0,0 @@ -# Restful API auth/authz mapping info -# -# Format: -# = , -# ex: admin.users = certServer.ca.users,read - -account.login = certServer.ocsp.account,login -account.logout = certServer.ocsp.account,logout -admin.users = certServer.ocsp.users,execute -admin.groups = certServer.ocsp.groups,execute diff --git a/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java b/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java index 21b37f801..6a5f60f6e 100644 --- a/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java +++ b/base/ocsp/src/com/netscape/ocsp/OCSPApplication.java @@ -6,6 +6,7 @@ import java.util.Set; import javax.ws.rs.core.Application; import com.netscape.certsrv.acls.ACLInterceptor; +import com.netscape.certsrv.authentication.AuthInterceptor; import com.netscape.certsrv.base.PKIException; import com.netscape.cms.servlet.account.AccountService; import com.netscape.cms.servlet.admin.GroupMemberService; @@ -40,7 +41,8 @@ public class OCSPApplication extends Application { // exception mapper classes.add(PKIException.Mapper.class); - // ACL interceptor + // interceptors + singletons.add(new AuthInterceptor()); singletons.add(new ACLInterceptor()); } diff --git a/base/tks/shared/webapps/tks/WEB-INF/acl.properties b/base/tks/shared/webapps/tks/WEB-INF/acl.properties new file mode 100644 index 000000000..6de7f08e5 --- /dev/null +++ b/base/tks/shared/webapps/tks/WEB-INF/acl.properties @@ -0,0 +1,10 @@ +# Restful API auth/authz mapping info +# +# Format: +# = , +# ex: admin.users = certServer.ca.users,read + +account.login = certServer.tks.account,login +account.logout = certServer.tks.account,logout +admin.users = certServer.tks.users,execute +admin.groups = certServer.tks.groups,execute diff --git a/base/tks/shared/webapps/tks/WEB-INF/auth.properties b/base/tks/shared/webapps/tks/WEB-INF/auth.properties deleted file mode 100644 index 6de7f08e5..000000000 --- a/base/tks/shared/webapps/tks/WEB-INF/auth.properties +++ /dev/null @@ -1,10 +0,0 @@ -# Restful API auth/authz mapping info -# -# Format: -# = , -# ex: admin.users = certServer.ca.users,read - -account.login = certServer.tks.account,login -account.logout = certServer.tks.account,logout -admin.users = certServer.tks.users,execute -admin.groups = certServer.tks.groups,execute diff --git a/base/tks/src/com/netscape/tks/TKSApplication.java b/base/tks/src/com/netscape/tks/TKSApplication.java index 229a64c95..c79e0d0f2 100644 --- a/base/tks/src/com/netscape/tks/TKSApplication.java +++ b/base/tks/src/com/netscape/tks/TKSApplication.java @@ -6,6 +6,7 @@ import java.util.Set; import javax.ws.rs.core.Application; import com.netscape.certsrv.acls.ACLInterceptor; +import com.netscape.certsrv.authentication.AuthInterceptor; import com.netscape.certsrv.base.PKIException; import com.netscape.cms.servlet.account.AccountService; import com.netscape.cms.servlet.admin.GroupMemberService; @@ -40,7 +41,8 @@ public class TKSApplication extends Application { // exception mapper classes.add(PKIException.Mapper.class); - // ACL interceptor + // interceptors + singletons.add(new AuthInterceptor()); singletons.add(new ACLInterceptor()); } -- cgit