1 package org
.argeo
.security
.jackrabbit
;
3 import java
.security
.Principal
;
4 import java
.util
.HashSet
;
5 import java
.util
.Properties
;
8 import javax
.jcr
.Credentials
;
9 import javax
.jcr
.Repository
;
10 import javax
.jcr
.RepositoryException
;
11 import javax
.jcr
.Session
;
12 import javax
.security
.auth
.Subject
;
13 import javax
.security
.auth
.callback
.CallbackHandler
;
14 import javax
.security
.auth
.x500
.X500Principal
;
16 import org
.apache
.jackrabbit
.api
.security
.user
.UserManager
;
17 import org
.apache
.jackrabbit
.core
.DefaultSecurityManager
;
18 import org
.apache
.jackrabbit
.core
.security
.AMContext
;
19 import org
.apache
.jackrabbit
.core
.security
.AccessManager
;
20 import org
.apache
.jackrabbit
.core
.security
.SecurityConstants
;
21 import org
.apache
.jackrabbit
.core
.security
.SystemPrincipal
;
22 import org
.apache
.jackrabbit
.core
.security
.authentication
.AuthContext
;
23 import org
.apache
.jackrabbit
.core
.security
.authentication
.CallbackHandlerImpl
;
24 import org
.apache
.jackrabbit
.core
.security
.authorization
.WorkspaceAccessManager
;
25 import org
.apache
.jackrabbit
.core
.security
.principal
.AdminPrincipal
;
26 import org
.apache
.jackrabbit
.core
.security
.principal
.PrincipalProvider
;
27 import org
.argeo
.api
.cms
.CmsSession
;
28 import org
.argeo
.api
.cms
.DataAdminPrincipal
;
29 import org
.argeo
.api
.cms
.CmsLog
;
30 import org
.argeo
.api
.cms
.AnonymousPrincipal
;
31 import org
.argeo
.api
.cms
.CmsConstants
;
32 import org
.argeo
.cms
.osgi
.CmsOsgiUtils
;
33 import org
.osgi
.framework
.BundleContext
;
34 import org
.osgi
.framework
.FrameworkUtil
;
36 /** Customises Jackrabbit security. */
37 public class ArgeoSecurityManager
extends DefaultSecurityManager
{
38 private final static CmsLog log
= CmsLog
.getLog(ArgeoSecurityManager
.class);
40 private BundleContext cmsBundleContext
= null;
42 public ArgeoSecurityManager() {
43 if (FrameworkUtil
.getBundle(CmsSession
.class) != null) {
44 cmsBundleContext
= FrameworkUtil
.getBundle(CmsSession
.class).getBundleContext();
48 public AuthContext
getAuthContext(Credentials creds
, Subject subject
, String workspaceName
)
49 throws RepositoryException
{
52 CallbackHandler cbHandler
= new CallbackHandlerImpl(creds
, getSystemSession(), getPrincipalProviderRegistry(),
53 adminId
, anonymousId
);
54 String appName
= "Jackrabbit";
55 return new ArgeoAuthContext(appName
, subject
, cbHandler
);
59 public AccessManager
getAccessManager(Session session
, AMContext amContext
) throws RepositoryException
{
60 synchronized (getSystemSession()) {
61 return super.getAccessManager(session
, amContext
);
66 public UserManager
getUserManager(Session session
) throws RepositoryException
{
67 synchronized (getSystemSession()) {
68 return super.getUserManager(session
);
73 protected PrincipalProvider
createDefaultPrincipalProvider(Properties
[] moduleConfig
) throws RepositoryException
{
74 return super.createDefaultPrincipalProvider(moduleConfig
);
77 /** Called once when the session is created */
79 public String
getUserID(Subject subject
, String workspaceName
) throws RepositoryException
{
80 boolean isAnonymous
= !subject
.getPrincipals(AnonymousPrincipal
.class).isEmpty();
81 boolean isDataAdmin
= !subject
.getPrincipals(DataAdminPrincipal
.class).isEmpty();
82 boolean isJackrabbitSystem
= !subject
.getPrincipals(SystemPrincipal
.class).isEmpty();
83 Set
<X500Principal
> userPrincipal
= subject
.getPrincipals(X500Principal
.class);
84 boolean isRegularUser
= !userPrincipal
.isEmpty();
85 CmsSession cmsSession
= null;
86 if (cmsBundleContext
!= null) {
87 cmsSession
= CmsOsgiUtils
.getCmsSession(cmsBundleContext
, subject
);
88 if (log
.isTraceEnabled())
89 log
.trace("Opening JCR session for CMS session " + cmsSession
);
93 if (isDataAdmin
|| isJackrabbitSystem
|| isRegularUser
)
94 throw new IllegalStateException("Inconsistent " + subject
);
96 return CmsConstants
.ROLE_ANONYMOUS
;
97 } else if (isRegularUser
) {// must be before DataAdmin
98 if (isAnonymous
|| isJackrabbitSystem
)
99 throw new IllegalStateException("Inconsistent " + subject
);
101 if (userPrincipal
.size() > 1) {
102 StringBuilder buf
= new StringBuilder();
103 for (X500Principal principal
: userPrincipal
)
104 buf
.append(' ').append('\"').append(principal
).append('\"');
105 throw new RuntimeException("Multiple user principals:" + buf
);
107 return userPrincipal
.iterator().next().getName();
109 } else if (isDataAdmin
) {
110 if (isAnonymous
|| isJackrabbitSystem
|| isRegularUser
)
111 throw new IllegalStateException("Inconsistent " + subject
);
113 assert !subject
.getPrincipals(AdminPrincipal
.class).isEmpty();
114 return CmsConstants
.ROLE_DATA_ADMIN
;
116 } else if (isJackrabbitSystem
) {
117 if (isAnonymous
|| isDataAdmin
|| isRegularUser
)
118 throw new IllegalStateException("Inconsistent " + subject
);
120 return super.getUserID(subject
, workspaceName
);
122 throw new IllegalStateException("Unrecognized subject type: " + subject
);
127 protected WorkspaceAccessManager
createDefaultWorkspaceAccessManager() {
128 WorkspaceAccessManager wam
= super.createDefaultWorkspaceAccessManager();
129 ArgeoWorkspaceAccessManagerImpl workspaceAccessManager
= new ArgeoWorkspaceAccessManagerImpl(wam
);
130 if (log
.isTraceEnabled())
131 log
.trace("Created workspace access manager");
132 return workspaceAccessManager
;
135 private class ArgeoWorkspaceAccessManagerImpl
implements SecurityConstants
, WorkspaceAccessManager
{
136 private final WorkspaceAccessManager wam
;
138 public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam
) {
143 public void init(Session systemSession
) throws RepositoryException
{
144 wam
.init(systemSession
);
145 Repository repository
= systemSession
.getRepository();
146 if (log
.isTraceEnabled())
147 log
.trace("Initialised workspace access manager on repository " + repository
148 + ", systemSession workspace: " + systemSession
.getWorkspace().getName());
151 public void close() throws RepositoryException
{
154 public boolean grants(Set
<Principal
> principals
, String workspaceName
) throws RepositoryException
{
155 // TODO: implements finer access to workspaces
156 if (log
.isTraceEnabled())
157 log
.trace("Grants " + new HashSet
<>(principals
) + " access to workspace '" + workspaceName
+ "'");
159 // return wam.grants(principals, workspaceName);