]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java
Fix add member to LDIF group
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / kernel / NodeSecurity.java
1 package org.argeo.cms.internal.kernel;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.net.URL;
6 import java.nio.file.ProviderNotFoundException;
7 import java.security.KeyStore;
8 import java.security.Provider;
9 import java.security.Security;
10 import java.util.Arrays;
11
12 import javax.security.auth.Subject;
13 import javax.security.auth.callback.Callback;
14 import javax.security.auth.callback.CallbackHandler;
15 import javax.security.auth.callback.NameCallback;
16 import javax.security.auth.callback.PasswordCallback;
17 import javax.security.auth.callback.UnsupportedCallbackException;
18 import javax.security.auth.login.LoginContext;
19 import javax.security.auth.login.LoginException;
20 import javax.security.auth.x500.X500Principal;
21
22 import org.apache.commons.io.FileUtils;
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.argeo.cms.CmsException;
26 import org.argeo.cms.KernelHeader;
27 import org.argeo.osgi.useradmin.AbstractUserDirectory;
28 import org.argeo.osgi.useradmin.LdapUserAdmin;
29 import org.argeo.osgi.useradmin.LdifUserAdmin;
30 import org.argeo.security.crypto.PkiUtils;
31 import org.bouncycastle.jce.provider.BouncyCastleProvider;
32 import org.osgi.framework.BundleContext;
33 import org.osgi.framework.ServiceRegistration;
34 import org.osgi.service.useradmin.UserAdmin;
35 import org.springframework.security.authentication.AuthenticationManager;
36 import org.springframework.security.core.Authentication;
37 import org.springframework.security.core.AuthenticationException;
38
39 /** Authentication and user management. */
40 class NodeSecurity implements AuthenticationManager {
41 private final static Log log;
42 static {
43 log = LogFactory.getLog(NodeSecurity.class);
44 // Make Bouncy Castle the default provider
45 Provider provider = new BouncyCastleProvider();
46 int position = Security.insertProviderAt(provider, 1);
47 if (position == -1)
48 log.error("Provider " + provider.getName()
49 + " already installed and could not be set as default");
50 Provider defaultProvider = Security.getProviders()[0];
51 if (!defaultProvider.getName().equals(KernelHeader.SECURITY_PROVIDER))
52 log.error("Provider name is " + defaultProvider.getName()
53 + " but it should be " + KernelHeader.SECURITY_PROVIDER);
54 }
55
56 private final BundleContext bundleContext;
57 private final NodeUserAdmin userAdmin;
58 private final Subject kernelSubject;
59
60 // private final OsAuthenticationProvider osAuth;
61 // private final InternalAuthenticationProvider internalAuth;
62 // private final AnonymousAuthenticationProvider anonymousAuth;
63 // private final JackrabbitUserAdminService userAdminService;
64
65 private ServiceRegistration<AuthenticationManager> authenticationManagerReg;
66 // private ServiceRegistration<UserAdminService> userAdminServiceReg;
67 // private ServiceRegistration<UserDetailsManager> userDetailsManagerReg;
68
69 private ServiceRegistration<UserAdmin> userAdminReg;
70
71 public NodeSecurity(BundleContext bundleContext) {
72 // Configure JAAS first
73 URL url = getClass().getClassLoader().getResource(
74 KernelConstants.JAAS_CONFIG);
75 System.setProperty("java.security.auth.login.config",
76 url.toExternalForm());
77
78 this.bundleContext = bundleContext;
79 this.kernelSubject = logKernel();
80
81 // osAuth = new OsAuthenticationProvider();
82 // internalAuth = new InternalAuthenticationProvider(
83 // Activator.getSystemKey());
84 // anonymousAuth = new AnonymousAuthenticationProvider(
85 // Activator.getSystemKey());
86
87 // user admin
88 // userAdminService = new JackrabbitUserAdminService();
89 // userAdminService.setRepository(node);
90 // userAdminService.setSecurityModel(new SimpleJcrSecurityModel());
91 // userAdminService.init();
92
93 userAdmin = new NodeUserAdmin();
94
95 File osgiInstanceDir = KernelUtils.getOsgiInstanceDir();
96 File homeDir = new File(osgiInstanceDir, "node");
97 homeDir.mkdirs();
98
99 String userAdminUri = KernelUtils
100 .getFrameworkProp(KernelConstants.USERADMIN_URI);
101 String baseDn = "dc=example,dc=com";
102 if (userAdminUri == null) {
103 File businessRolesFile = new File(homeDir, baseDn + ".ldif");
104 // userAdminUri = getClass().getResource(baseDn +
105 // ".ldif").toString();
106 if (!businessRolesFile.exists())
107 try {
108 FileUtils.copyInputStreamToFile(getClass()
109 .getResourceAsStream(baseDn + ".ldif"),
110 businessRolesFile);
111 } catch (IOException e) {
112 throw new CmsException("Cannot copy demo resource", e);
113 }
114 userAdminUri = businessRolesFile.toURI().toString();
115 }
116
117 AbstractUserDirectory businessRoles;
118 if (userAdminUri.startsWith("ldap"))
119 businessRoles = new LdapUserAdmin(userAdminUri);
120 else {
121 businessRoles = new LdifUserAdmin(userAdminUri);
122 }
123 businessRoles.init();
124 userAdmin.addUserAdmin(baseDn, businessRoles);
125
126 String baseNodeRoleDn = KernelHeader.ROLES_BASEDN;
127 File nodeRolesFile = new File(homeDir, baseNodeRoleDn + ".ldif");
128 if (!nodeRolesFile.exists())
129 try {
130 FileUtils.copyInputStreamToFile(
131 getClass().getResourceAsStream("demo.ldif"),
132 nodeRolesFile);
133 } catch (IOException e) {
134 throw new CmsException("Cannot copy demo resource", e);
135 }
136 LdifUserAdmin nodeRoles = new LdifUserAdmin(nodeRolesFile.toURI()
137 .toString(), false);
138 nodeRoles.setExternalRoles(userAdmin);
139 nodeRoles.init();
140 // nodeRoles.createRole(KernelHeader.ROLE_ADMIN, Role.GROUP);
141 userAdmin.addUserAdmin(baseNodeRoleDn, nodeRoles);
142
143 }
144
145 private Subject logKernel() {
146 final Subject kernelSubject = new Subject();
147 createKeyStoreIfNeeded();
148
149 CallbackHandler cbHandler = new CallbackHandler() {
150
151 @Override
152 public void handle(Callback[] callbacks) throws IOException,
153 UnsupportedCallbackException {
154 // alias
155 ((NameCallback) callbacks[1]).setName(KernelHeader.ROLE_KERNEL);
156 // store pwd
157 ((PasswordCallback) callbacks[2]).setPassword("changeit"
158 .toCharArray());
159 // key pwd
160 ((PasswordCallback) callbacks[3]).setPassword("changeit"
161 .toCharArray());
162 }
163 };
164 try {
165 LoginContext kernelLc = new LoginContext(
166 KernelConstants.LOGIN_CONTEXT_KERNEL, kernelSubject,
167 cbHandler);
168 kernelLc.login();
169 } catch (LoginException e) {
170 throw new CmsException("Cannot log in kernel", e);
171 }
172 return kernelSubject;
173 }
174
175 public void publish() {
176 authenticationManagerReg = bundleContext.registerService(
177 AuthenticationManager.class, this, null);
178 // userAdminServiceReg = bundleContext.registerService(
179 // UserAdminService.class, userAdminService, null);
180 // userDetailsManagerReg = bundleContext.registerService(
181 // UserDetailsManager.class, userAdminService, null);
182 userAdminReg = bundleContext.registerService(UserAdmin.class,
183 userAdmin, null);
184 }
185
186 void destroy() {
187 // try {
188 // userAdminService.destroy();
189 // } catch (RepositoryException e) {
190 // log.error("Error while destroying Jackrabbit useradmin");
191 // }
192 // userDetailsManagerReg.unregister();
193 // userAdminServiceReg.unregister();
194 authenticationManagerReg.unregister();
195
196 // userAdmin.destroy();
197 userAdminReg.unregister();
198
199 // Logout kernel
200 try {
201 LoginContext kernelLc = new LoginContext(
202 KernelConstants.LOGIN_CONTEXT_KERNEL, kernelSubject);
203 kernelLc.logout();
204 } catch (LoginException e) {
205 throw new CmsException("Cannot log in kernel", e);
206 }
207
208 Security.removeProvider(KernelHeader.SECURITY_PROVIDER);
209 }
210
211 public NodeUserAdmin getUserAdmin() {
212 return userAdmin;
213 }
214
215 public Subject getKernelSubject() {
216 return kernelSubject;
217 }
218
219 @Override
220 public Authentication authenticate(Authentication authentication)
221 throws AuthenticationException {
222 log.error("Authentication manager is deprectaed and should not be used.");
223 // Authentication auth = null;
224 // if (authentication instanceof InternalAuthentication)
225 // auth = internalAuth.authenticate(authentication);
226 // else if (authentication instanceof AnonymousAuthenticationToken)
227 // auth = anonymousAuth.authenticate(authentication);
228 // else if (authentication instanceof
229 // UsernamePasswordAuthenticationToken)
230 // auth = userAdminService.authenticate(authentication);
231 // else if (authentication instanceof OsAuthenticationToken)
232 // auth = osAuth.authenticate(authentication);
233 // if (auth == null)
234 // throw new CmsException("Could not authenticate " + authentication);
235 throw new ProviderNotFoundException(
236 "Authentication manager is deprectaed and should not be used.");
237 }
238
239 private void createKeyStoreIfNeeded() {
240 char[] ksPwd = "changeit".toCharArray();
241 char[] keyPwd = Arrays.copyOf(ksPwd, ksPwd.length);
242 File keyStoreFile = new File(KernelUtils.getOsgiInstanceDir(),
243 "node.p12");
244 if (!keyStoreFile.exists()) {
245 try {
246 keyStoreFile.getParentFile().mkdirs();
247 KeyStore keyStore = PkiUtils.getKeyStore(keyStoreFile, ksPwd);
248 PkiUtils.generateSelfSignedCertificate(keyStore,
249 new X500Principal(KernelHeader.ROLE_KERNEL), keyPwd);
250 PkiUtils.saveKeyStore(keyStoreFile, ksPwd, keyStore);
251
252 } catch (Exception e) {
253 throw new CmsException("Cannot create key store "
254 + keyStoreFile, e);
255 }
256 }
257 }
258
259 }