Introduce org.argeo.security.dao.cli and console callback handler
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 22 Mar 2013 14:25:03 +0000 (14:25 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 22 Mar 2013 14:25:03 +0000 (14:25 +0000)
https://www.argeo.org/bugzilla/show_bug.cgi?id=154

git-svn-id: https://svn.argeo.org/commons/trunk@6198 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

demo/argeo_node_cli.properties [new file with mode: 0644]
security/modules/org.argeo.security.dao.cli/.project [new file with mode: 0644]
security/modules/org.argeo.security.dao.cli/META-INF/spring/security-cli-osgi.xml [new file with mode: 0644]
security/modules/org.argeo.security.dao.cli/META-INF/spring/security-cli.xml [new file with mode: 0644]
security/modules/org.argeo.security.dao.cli/pom.xml [new file with mode: 0644]
security/modules/org.argeo.security.dao.cli/security.properties [new file with mode: 0644]
security/modules/pom.xml
security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ConsoleCallbackHandler.java [new file with mode: 0644]

diff --git a/demo/argeo_node_cli.properties b/demo/argeo_node_cli.properties
new file mode 100644 (file)
index 0000000..1c33311
--- /dev/null
@@ -0,0 +1,8 @@
+argeo.osgi.start.1.node=\
+org.springframework.osgi.extender,\
+
+argeo.osgi.start.3.node=\
+org.argeo.node.repo.jackrabbit,\
+org.argeo.security.dao.cli,\
+
+log4j.configuration=file:../../log4j.properties
diff --git a/security/modules/org.argeo.security.dao.cli/.project b/security/modules/org.argeo.security.dao.cli/.project
new file mode 100644 (file)
index 0000000..807ba67
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.argeo.security.dao.cli</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+       </natures>
+</projectDescription>
diff --git a/security/modules/org.argeo.security.dao.cli/META-INF/spring/security-cli-osgi.xml b/security/modules/org.argeo.security.dao.cli/META-INF/spring/security-cli-osgi.xml
new file mode 100644 (file)
index 0000000..c46f276
--- /dev/null
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans:beans xmlns="http://www.springframework.org/schema/osgi"\r
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"\r
+       xmlns:util="http://www.springframework.org/schema/util"\r
+       xsi:schemaLocation="http://www.springframework.org/schema/osgi  \r
+       http://www.springframework.org/schema/osgi/spring-osgi-1.1.xsd\r
+       http://www.springframework.org/schema/beans   \r
+       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+       http://www.springframework.org/schema/util\r
+       http://www.springframework.org/schema/util/spring-util-2.5.xsd">\r
+\r
+       <!-- REFERENCE -->\r
+       <reference id="nodeRepository" interface="javax.jcr.Repository"\r
+               filter="(argeo.jcr.repository.alias=node)" />\r
+\r
+       <!-- SERVICES -->\r
+       <service ref="authenticationManager"\r
+               interface="org.springframework.security.AuthenticationManager" />\r
+\r
+       <!-- User management -->\r
+       <service ref="userDetailsManager"\r
+               interface="org.springframework.security.userdetails.UserDetailsService"\r
+               context-class-loader="service-provider" />\r
+       <service ref="userDetailsManager"\r
+               interface="org.springframework.security.userdetails.UserDetailsManager"\r
+               context-class-loader="service-provider" />\r
+       <service ref="userDetailsManager" interface="org.argeo.security.UserAdminService"\r
+               context-class-loader="service-provider" />\r
+\r
+       <!-- Callback handler and keyring -->\r
+       <service interface="javax.security.auth.callback.CallbackHandler"\r
+               ref="defaultCallbackHandler" />\r
+       <service interface="org.argeo.security.crypto.CryptoKeyring"\r
+               ref="keyring" />\r
+\r
+</beans:beans>
\ No newline at end of file
diff --git a/security/modules/org.argeo.security.dao.cli/META-INF/spring/security-cli.xml b/security/modules/org.argeo.security.dao.cli/META-INF/spring/security-cli.xml
new file mode 100644 (file)
index 0000000..c3f6c81
--- /dev/null
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+       <bean
+               class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+               <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
+               <property name="locations">
+                       <value>osgibundle:security.properties</value>
+               </property>
+       </bean>
+
+       <bean id="argeoDataModel" class="org.argeo.jackrabbit.JackrabbitWrapper"
+               init-method="init" destroy-method="destroy">
+               <description><![CDATA[Make sure that Argeo base data model is registered]]></description>
+               <property name="cndFiles">
+                       <list>
+                               <value>/org/argeo/jcr/argeo.cnd</value>
+                       </list>
+               </property>
+               <property name="repository" ref="nodeRepository" />
+               <property name="bundleContext" ref="bundleContext" />
+       </bean>
+
+       <bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
+               <property name="providers">
+                       <list>
+                               <ref bean="authByAdapterProvider" />
+                               <ref bean="osJcrAuthenticationProvider" />
+                       </list>
+               </property>
+       </bean>
+
+       <!-- Authentication providers -->
+       <bean id="osJcrAuthenticationProvider" class="org.argeo.security.jcr.OsJcrAuthenticationProvider"
+               init-method="init" destroy-method="destroy" depends-on="argeoDataModel">
+               <property name="repository" ref="nodeRepository" />
+               <property name="jcrSecurityModel" ref="jcrSecurityModel" />
+       </bean>
+
+       <bean name="jcrSecurityModel" class="org.argeo.security.jackrabbit.JackrabbitSecurityModel" />
+
+       <bean id="authByAdapterProvider"
+               class="org.springframework.security.adapters.AuthByAdapterProvider">
+               <description><![CDATA[System authentication]]></description>
+               <property name="key" value="${argeo.security.systemKey}" />
+       </bean>
+
+       <!-- Internal authentication, used by the general authentication process 
+               himself, in order to prevent the following dependency cycle: Repository.login() 
+               <= AuthenticationManager <= osJcrAuthenticationProvider <= Repository.login() 
+               in init() -->
+       <bean id="internalAuthenticationManager" class="org.springframework.security.providers.ProviderManager">
+               <property name="providers">
+                       <list>
+                               <ref bean="authByAdapterProvider" />
+                       </list>
+               </property>
+       </bean>
+
+       <bean
+               class="org.argeo.security.core.AuthenticatedApplicationContextInitialization">
+               <description><![CDATA[Executes initialization with a system authentication]]></description>
+               <property name="authenticationManager" ref="internalAuthenticationManager" />
+       </bean>
+
+       <!-- Dummy user manager -->
+       <bean id="userDetailsManager" class="org.argeo.security.jcr.OsJcrUserAdminService"
+               init-method="init" destroy-method="destroy">
+               <property name="repository" ref="nodeRepository" />
+       </bean>
+
+       <!-- Default callback handler and keyring -->
+       <bean id="defaultCallbackHandler" class="org.argeo.security.core.ConsoleCallbackHandler" />
+
+       <bean id="nodeSession" class="org.argeo.jcr.spring.ThreadBoundSession">
+               <property name="repository" ref="nodeRepository" />
+       </bean>
+
+       <bean id="keyring" class="org.argeo.security.jcr.JcrKeyring">
+               <property name="session" ref="nodeSession" />
+               <property name="defaultCallbackHandler" ref="defaultCallbackHandler" />
+               <property name="secreteKeyLength" value="${argeo.keyring.secreteKeyLength}" />
+       </bean>
+</beans>
\ No newline at end of file
diff --git a/security/modules/org.argeo.security.dao.cli/pom.xml b/security/modules/org.argeo.security.dao.cli/pom.xml
new file mode 100644 (file)
index 0000000..2ee756c
--- /dev/null
@@ -0,0 +1,27 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>org.argeo.commons.security</groupId>
+               <version>2.1.1-SNAPSHOT</version>
+               <artifactId>modules</artifactId>
+               <relativePath>..</relativePath>
+       </parent>
+       <artifactId>org.argeo.security.dao.cli</artifactId>
+       <name>Commons Security DAO CLI</name>
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <configuration>
+                                       <instructions>
+                                               <Import-Package>
+                                                       *,
+                                                       org.argeo.jcr,
+                                               </Import-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+</project>
\ No newline at end of file
diff --git a/security/modules/org.argeo.security.dao.cli/security.properties b/security/modules/org.argeo.security.dao.cli/security.properties
new file mode 100644 (file)
index 0000000..42df925
--- /dev/null
@@ -0,0 +1,3 @@
+argeo.security.systemKey=argeo
+argeo.node.repo.securityWorkspace=security
+argeo.keyring.secreteKeyLength=256
index 0ac639c6f7617a1cf6d795ba5675373541f66477..1338eba611742f90a8397b87940d4d2002384dc6 100644 (file)
@@ -11,6 +11,7 @@
        <packaging>pom</packaging>
        <name>Commons Security Modules</name>
        <modules>
+               <module>org.argeo.security.dao.cli</module>
                <module>org.argeo.security.dao.os</module>
                <module>org.argeo.security.dao.jackrabbit</module>
                <module>org.argeo.security.dao.ldap</module>
diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ConsoleCallbackHandler.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/ConsoleCallbackHandler.java
new file mode 100644 (file)
index 0000000..3bd4b57
--- /dev/null
@@ -0,0 +1,68 @@
+package org.argeo.security.core;
+
+import java.io.Console;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Locale;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextOutputCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.argeo.ArgeoException;
+import org.argeo.util.LocaleCallback;
+
+/** Callback handler to be used with a command line UI. */
+public class ConsoleCallbackHandler implements CallbackHandler {
+
+       @Override
+       public void handle(Callback[] callbacks) throws IOException,
+                       UnsupportedCallbackException {
+               Console console = System.console();
+               if (console == null)
+                       throw new ArgeoException("No console available");
+
+               PrintWriter writer = console.writer();
+               for (int i = 0; i < callbacks.length; i++) {
+                       if (callbacks[i] instanceof TextOutputCallback) {
+                               TextOutputCallback callback = (TextOutputCallback) callbacks[i];
+                               writer.write(callback.getMessage());
+                       } else if (callbacks[i] instanceof NameCallback) {
+                               NameCallback callback = (NameCallback) callbacks[i];
+                               writer.write(callback.getPrompt());
+                               if (callback.getDefaultName() != null)
+                                       writer.write(" (" + callback.getDefaultName() + ")");
+                               writer.write(" : ");
+                               String answer = console.readLine();
+                               if (callback.getDefaultName() != null
+                                               && answer.trim().equals(""))
+                                       callback.setName(callback.getDefaultName());
+                               else
+                                       callback.setName(answer);
+                       } else if (callbacks[i] instanceof PasswordCallback) {
+                               PasswordCallback callback = (PasswordCallback) callbacks[i];
+                               writer.write(callback.getPrompt());
+                               char[] answer = console.readPassword();
+                               callback.setPassword(answer);
+                       } else if (callbacks[i] instanceof LocaleCallback) {
+                               LocaleCallback callback = (LocaleCallback) callbacks[i];
+                               writer.write(callback.getPrompt());
+                               writer.write("\n");
+                               for (int j = 0; j < callback.getAvailableLocales().size(); j++) {
+                                       Locale locale = callback.getAvailableLocales().get(j);
+                                       writer.print(j + " : " + locale.getDisplayName() + "\n");
+                               }
+                               writer.write("(" + callback.getDefaultIndex() + ") : ");
+                               String answer = console.readLine();
+                               if (answer.trim().equals(""))
+                                       callback.setSelectedIndex(callback.getDefaultIndex());
+                               else
+                                       callback.setSelectedIndex(new Integer(answer.trim()));
+                       }
+               }
+       }
+
+}