diff options
| author | Thomas Lenz <tlenz@iaik.tugraz.at> | 2015-02-18 13:47:14 +0100 | 
|---|---|---|
| committer | Thomas Lenz <tlenz@iaik.tugraz.at> | 2015-02-18 13:47:14 +0100 | 
| commit | bf086cff8ef680b73ca0300147c3c3b70ab32ae0 (patch) | |
| tree | 1174cdc916982f5f879cde1fc587147a7dced63d /id/server/idserverlib | |
| parent | 570527d48e3bf03444cdda08a4c1bcf8e7d4ff42 (diff) | |
| parent | 271e22add71f0260f5d421844a2171a09093f505 (diff) | |
| download | moa-id-spss-bf086cff8ef680b73ca0300147c3c3b70ab32ae0.tar.gz moa-id-spss-bf086cff8ef680b73ca0300147c3c3b70ab32ae0.tar.bz2 moa-id-spss-bf086cff8ef680b73ca0300147c3c3b70ab32ae0.zip | |
Merge branch 'datentechnik_modularization' into moa-id-2.2-merge
Conflicts:
	id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java
	id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java
	id/server/stork2-commons/pom.xml
	id/server/stork2-commons/src/main/java/eu/stork/peps/complex/attributes/.svn/entries
	id/server/stork2-commons/src/main/resources/.svn/entries
	id/server/stork2-saml-engine/pom.xml
	pom.xml
Diffstat (limited to 'id/server/idserverlib')
104 files changed, 6648 insertions, 789 deletions
| diff --git a/id/server/idserverlib/pom.xml b/id/server/idserverlib/pom.xml index 44a6c3e60..cab3c73e1 100644 --- a/id/server/idserverlib/pom.xml +++ b/id/server/idserverlib/pom.xml @@ -24,13 +24,26 @@  			<url>https://build.shibboleth.net/nexus/content/groups/public/</url>
  		</repository>
  	</repositories>
 -	
 +
  	<dependencies>
 -     <dependency>
 -     	<groupId>eu.stork</groupId>
 -      <artifactId>oasis-dss-api</artifactId>
 -      <version>1.0.0-RELEASE</version>
 -    </dependency>
 +		<!-- TestNG -->
 +		<dependency>
 +			<groupId>org.testng</groupId>
 +			<artifactId>testng</artifactId>
 +			<version>6.1.1</version>
 +			<scope>test</scope>
 +		</dependency>
 +	<dependency>
 +		<groupId>eu.stork</groupId>
 +		<artifactId>oasis-dss-api</artifactId>
 +		<version>1.0.0-RELEASE</version>
 +		<exclusions>
 +			<exclusion>
 +				<groupId>org.apache.commons</groupId>
 +				<artifactId>commons-io</artifactId>
 +			</exclusion>
 +		</exclusions>
 +	</dependency>
      <dependency>
      		<groupId>MOA.id.server</groupId>
 @@ -147,11 +160,13 @@  			<groupId>javax.mail</groupId>
  			<artifactId>mail</artifactId>
  		</dependency>
 +		<!--
  		<dependency>
  			<groupId>javax.servlet</groupId>
  			<artifactId>servlet-api</artifactId>
  			<scope>provided</scope>
  		</dependency>
 +		-->
          <dependency>
              <groupId>xalan-bin-dist</groupId>
 @@ -216,12 +231,7 @@              <artifactId>jul-to-slf4j</artifactId>
              <version>1.7.6</version>
          </dependency> -->
 -		
 -		<dependency>
 -			<groupId>junit</groupId>
 -			<artifactId>junit</artifactId>
 -			<scope>test</scope>
 -		</dependency>
 +
   		<dependency>
  			<groupId>commons-logging</groupId>
  			<artifactId>commons-logging</artifactId>
 @@ -367,15 +377,14 @@  			<artifactId>google-oauth-client-jetty</artifactId>
  			<version>1.19.0</version>
  			<scope>test</scope>
 +			<exclusions>
 +				<exclusion>
 +					<groupId>org.mortbay.jetty</groupId>
 +					<artifactId>servlet-api</artifactId>
 +				</exclusion>
 +			</exclusions>
  		</dependency>
 -		<!-- TestNG -->
 -		<dependency>
 -			<groupId>org.testng</groupId>
 -			<artifactId>testng</artifactId>
 -			<version>6.1.1</version>
 -			<scope>test</scope>
 -		</dependency>
  		<dependency>
  			<groupId>eu.stork</groupId>
  			<artifactId>DocumentService</artifactId>
 @@ -396,6 +405,66 @@  				</exclusion>
  			</exclusions>
  		</dependency>
 +
 +		<dependency>
 +			<groupId>javax.servlet</groupId>
 +			<artifactId>javax.servlet-api</artifactId>
 +			<scope>provided</scope>
 +		</dependency>
 +
 +		<!-- testing -->
 +		<dependency>
 +			<groupId>junit</groupId>
 +			<artifactId>junit</artifactId>
 +			<scope>test</scope>
 +		</dependency>
 +
 +		<dependency>
 +			<groupId>com.h2database</groupId>
 +			<artifactId>h2</artifactId>
 +			<version>1.4.178</version>
 +			<scope>runtime</scope>
 +		</dependency>
 +
 +		<!-- tools -->
 +		<dependency>
 +			<groupId>org.apache.commons</groupId>
 +			<artifactId>commons-collections4</artifactId>
 +		</dependency>
 +		<dependency>
 +			<groupId>commons-io</groupId>
 +			<artifactId>commons-io</artifactId>
 +		</dependency>
 +
 +		<!-- spring -->
 +		<dependency>
 +			<groupId>org.springframework</groupId>
 +			<artifactId>spring-core</artifactId>
 +			<exclusions>
 +				<exclusion>
 +					<groupId>commons-logging</groupId>
 +					<artifactId>commons-logging</artifactId>
 +				</exclusion>
 +			</exclusions>
 +		</dependency>
 +		<dependency>
 +			<groupId>org.springframework</groupId>
 +			<artifactId>spring-expression</artifactId>
 +		</dependency>
 +		<dependency>
 +			<groupId>org.springframework</groupId>
 +			<artifactId>spring-context</artifactId>
 +		</dependency>
 +		<dependency>
 +			<groupId>org.springframework</groupId>
 +			<artifactId>spring-webmvc</artifactId>
 +		</dependency>
 +		<dependency>
 +			<groupId>org.springframework</groupId>
 +			<artifactId>spring-test</artifactId>
 +			<scope>test</scope>
 +		</dependency>
 +
  	</dependencies>
  	<build>
 @@ -427,16 +496,7 @@  	        </executions>
  	      </plugin>
 -        		        		
 -			<plugin>
 -				<groupId>org.apache.maven.plugins</groupId>
 -				<artifactId>maven-compiler-plugin</artifactId>
 -				<configuration>
 -					<source>1.6</source>
 -					<target>1.6</target>
 -				</configuration>
 -			</plugin>
 -			
 +
  						<plugin>
  				<groupId>org.apache.maven.plugins</groupId>
  				<artifactId>maven-javadoc-plugin</artifactId>
 @@ -462,11 +522,10 @@  						</tag>
  					</tags>
  					<links>
 -						<link>http://java.sun.com/j2se/1.4/docs/api/</link>
 -						<link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
 +						<link>http://docs.oracle.com/javase/7/docs/api/</link>
  						<link>http://logging.apache.org/log4j/docs/api/</link>
  					</links>
 -					<target>1.5</target>
 +					<target>1.7</target>
  				</configuration>
  				<executions>
  					<execution>
 @@ -496,7 +555,30 @@  					</execution>
  				</executions>
  			</plugin>
 +
 +			<!-- enable co-existence of testng and junit -->
 +			<plugin>
 +				<artifactId>maven-surefire-plugin</artifactId>
 +				<version>${surefire.version}</version>
 +				<configuration>
 +					<threadCount>1</threadCount>
 +				</configuration>
 +				<dependencies>
 +					<dependency>
 +						<groupId>org.apache.maven.surefire</groupId>
 +						<artifactId>surefire-junit47</artifactId>
 +						<version>${surefire.version}</version>
 +					</dependency>
 +					<dependency>
 +						<groupId>org.apache.maven.surefire</groupId>
 +						<artifactId>surefire-testng</artifactId>
 +						<version>${surefire.version}</version>
 +					</dependency>
 +				</dependencies>
 +			</plugin>
 +
  		</plugins>
 +
  	</build>
  </project>
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java index 43384c58a..b9ce76d0c 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java @@ -311,27 +311,28 @@ public class AuthenticationServer implements MOAIDAuthConstants {  	}  	/** -	 * Processes an <code><InfoboxReadResponse></code> sent by the -	 * security layer implementation.<br> +	 * Processes an <code><InfoboxReadResponse></code> sent by the security layer implementation.<br>  	 * <ul>  	 * <li>Validates given <code><InfoboxReadResponse></code></li> -	 * <li>Parses identity link enclosed in -	 * <code><InfoboxReadResponse></code></li> +	 * <li>Parses identity link enclosed in <code><InfoboxReadResponse></code></li>  	 * <li>Verifies identity link by calling the MOA SP component</li>  	 * <li>Checks certificate authority of identity link</li>  	 * <li>Stores identity link in the session</li>  	 * <li>Verifies all additional infoboxes returned from the BKU</li>  	 * <li>Creates an authentication block to be signed by the user</li> -	 * <li>Creates and returns a <code><CreateXMLSignatureRequest></code> -	 * containg the authentication block, meant to be returned to the security -	 * layer implementation</li> +	 * <li>Creates and returns a <code><CreateXMLSignatureRequest></code> containg the authentication block, meant +	 * to be returned to the security layer implementation</li>  	 * </ul> -	 * -	 * @param sessionID                     ID of associated authentication session data -	 * @param infoboxReadResponseParameters The parameters from the response returned from the BKU -	 *                                      including the <code><InfoboxReadResponse></code> -	 * @return String representation of the -	 * <code><CreateXMLSignatureRequest></code> +	 *  +	 * @param sessionID +	 *            ID of associated authentication session data +	 * @param infoboxReadResponseParameters +	 *            The parameters from the response returned from the BKU including the +	 *            <code><InfoboxReadResponse></code> +	 * @return String "found!" in case the identity link could be retrieved and successfully validated, {@code null} in +	 *         case the identity link could not be retrieved (indicates that the card did not contain an identity link +	 *         which might indicate a foreign identity). Note that failing to parse or failing to validate the identity +	 *         link results in an Exception being thrown.  	 * @throws BKUException  	 */  	public String verifyIdentityLink(AuthenticationSession session, @@ -1095,14 +1096,14 @@ public class AuthenticationServer implements MOAIDAuthConstants {  	 * <li>Stores authentication data in the authentication data store indexed  	 * by the SAML artifact</li>  	 * <li>Deletes authentication session</li> -	 * <li>Returns the SAML artifact, encoded BASE64</li> +	 * <li><strike>Returns the SAML artifact, encoded BASE64</strike><br/>New id of the authenticated MOA session or {@code null} in case of mandate mode (???)</li>  	 * </ul>  	 *  	 * @param sessionID                         session ID of the running authentication session  	 * @param xmlCreateXMLSignatureReadResponse String representation of the  	 *                                          <code><CreateXMLSignatureResponse></code> -	 * @return SAML artifact needed for retrieving authentication data, encoded -	 * BASE64 +	 * @return <strike>SAML artifact needed for retrieving authentication data, encoded +	 * BASE64</strike><br/>New id of the authenticated MOA session or {@code null} in case of mandate mode (???)  	 * @throws BKUException  	 */  	public String verifyAuthenticationBlock(AuthenticationSession session, @@ -1362,17 +1363,16 @@ public class AuthenticationServer implements MOAIDAuthConstants {  	/**  	 * Gets the foreign authentication data.<br>  	 * <ul> -	 * <li>Creates authentication data</li> +	 * <li><strong>Creates authentication data</strong></li>  	 * <li>Creates a corresponding SAML artifact</li>  	 * <li>Stores authentication data in the authentication data store indexed  	 * by the SAML artifact</li>  	 * <li>Deletes authentication session</li> -	 * <li>Returns the SAML artifact, encoded BASE64</li> +	 * <li><strike>Returns the SAML artifact, encoded BASE64</strike></li>  	 * </ul>  	 *  	 * @param sessionID session ID of the running authentication session -	 * @return SAML artifact needed for retrieving authentication data, encoded -	 * BASE64 +	 * @return String "new Session"  	 */  	public String getForeignAuthenticationData(AuthenticationSession session)  			throws AuthenticationException, BuildException, ParseException, @@ -1381,46 +1381,6 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		if (session == null)  			throw new AuthenticationException("auth.10", new Object[]{  					REQ_VERIFY_AUTH_BLOCK, PARAM_SESSIONID}); - -		//        // post processing of the infoboxes -		//        Iterator iter = session.getInfoboxValidatorIterator(); -		//        boolean formpending = false; -		//        if (iter != null) { -		//            while (!formpending && iter.hasNext()) { -		//                Vector infoboxValidatorVector = (Vector) iter.next(); -		//                String identifier = (String) infoboxValidatorVector.get(0); -		//                String friendlyName = (String) infoboxValidatorVector.get(1); -		//                InfoboxValidator infoboxvalidator = (InfoboxValidator) infoboxValidatorVector -		//                        .get(2); -		//                InfoboxValidationResult infoboxValidationResult = null; -		//                try { -		//                    infoboxValidationResult = infoboxvalidator.validate(session -		//                            .getIdentityLink().getSamlAssertion()); -		//                } catch (ValidateException e) { -		//                    Logger.error("Error validating " + identifier + " infobox:" -		//                            + e.getMessage()); -		//                    throw new ValidateException("validator.44", -		//                            new Object[]{friendlyName}); -		//                } -		//                if (!infoboxValidationResult.isValid()) { -		//                    Logger.info("Validation of " + identifier -		//                            + " infobox failed."); -		//                    throw new ValidateException("validator.40", new Object[]{ -		//                            friendlyName, -		//                            infoboxValidationResult.getErrorMessage()}); -		//                } -		//                String form = infoboxvalidator.getForm(); -		//                if (ParepUtils.isEmpty(form)) { -		//                    AddAdditionalSAMLAttributes( -		//                            session, -		//                            infoboxValidationResult.getExtendedSamlAttributes(), -		//                            identifier, friendlyName); -		//                } else { -		//                    return "Redirect to Input Processor"; -		//                } -		//            } -		//        } -  		VerifyXMLSignatureResponse vsresp = new VerifyXMLSignatureResponse();  		X509Certificate cert = session.getSignerCertificate();  		vsresp.setX509certificate(cert); @@ -1442,8 +1402,8 @@ public class AuthenticationServer implements MOAIDAuthConstants {  	 * Retrieves a session from the session store.  	 *  	 * @param id session ID -	 * @return <code>AuthenticationSession</code> stored with given session ID, -	 * <code>null</code> if session ID unknown +	 * @return <code>AuthenticationSession</code> stored with given session ID (never {@code null}). +	 * @throws AuthenticationException in case the session id does not reflect a valic, active session.  	 */  	public static AuthenticationSession getSession(String id)  			throws AuthenticationException { @@ -1749,10 +1709,6 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		//        String acsURL = new DataURLBuilder().buildDataURL(issuerValue,   		//    			PEPSConnectorServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN, moasession.getSessionID()); -		//solve Problem with sessionIDs  -		String acsURL = issuerValue + PEPSConnectorServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN; - -		Logger.debug("MOA Assertion Consumer URL (PEPSConnctor): " + acsURL);  		String providerName = oaParam.getFriendlyName();  		Logger.debug("Issuer value: " + issuerValue); @@ -1787,12 +1743,18 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		List<String> value = new ArrayList<String>();  		Logger.debug("PEPS supports XMLSignatures:"+cpeps.isXMLSignatureSupported()); +		String acsURL;  		if(cpeps.isXMLSignatureSupported())//Send SignRequest to PEPS  		{ +			//solve Problem with sessionIDs  +			acsURL = issuerValue + PEPSConnectorServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN; +			  			value.add(generateDssSignRequest(CreateXMLSignatureRequestBuilder.buildForeignIDTextToBeSigned("wie im  Signaturzertifikat (as in my signature certificate)", oaParam, moasession),  					"application/xhtml+xml", moasession.getCcc()));  			newAttribute.setValue(value);  			attributeList.add(newAttribute); +			 +			// TODO[branch]: STORK AuthReq CPEPS acsURL "/PEPSConnector"  		}  		else//Process SignRequest locally with MOCCA  		{ @@ -1808,6 +1770,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {  			moasession.setSignedDoc(signedDoc);  			acsURL = issuerValue + PEPSConnectorWithLocalSigningServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN; +			// TODO[branch]: STORK AuthReq acsURL "/PEPSConnectorWithLocalSigning"  			try {  				AuthenticationSessionStoreage.storeSession(moasession);  			} catch (MOADatabaseException e) { @@ -1816,6 +1779,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {  			}  		} +		Logger.debug("MOA Assertion Consumer URL (PEPSConnctor): " + acsURL);  		if (Logger.isDebugEnabled()) {  			Logger.debug("The following attributes are requested for this OA:"); @@ -1900,6 +1864,8 @@ public class AuthenticationServer implements MOAIDAuthConstants {  			StringWriter writer = new StringWriter();  			template.merge(context, writer); +			// TODO[branch]: SAML2 Form Submit to CPEPS, response to acsURL Servlet +			  			resp.setContentType("text/html;charset=UTF-8");              			resp.getOutputStream().write(writer.toString().getBytes("UTF-8")); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java index db36356c0..d4ce8670e 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java @@ -148,12 +148,15 @@ public class MOAIDAuthInitializer {              }          } +        // FIXME[@tlenz]: iaik.prod:iaik_X509TrustManager requires iaik.IAIKRuntimeException which might have been moved to iaik.server.modules (iaik.prod:iaik_moa:1.51))           // Initializes IAIKX509TrustManager logging +        /*          String log4jConfigURL = System.getProperty("log4j.configuration");          Logger.info("Log4J Configuration: " + log4jConfigURL);          if (log4jConfigURL != null) {              IAIKX509TrustManager.initLog(new LoggerConfigImpl(log4jConfigURL));          } +         */          // Initializes the Axis secure socket factory for use in calling the          // MOA-SP web service diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java index 484fe1f9e..9a8372a2d 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java @@ -47,6 +47,15 @@ public class StartAuthenticationBuilder {  	} +	/** +	 * Depending on the selected citizen's country ({@code moasession.ccc}): +	 * <ul> +	 * <li><strong>Either</strong> creates an "IdentityLinkForm" with embedded {@code InfoBoxReadRequest} to be submitted to a citizen card +	 * environment for reading the subject's IdentityLink</li> +	 * </ul> +	 *  +	 * @return The IdentityLinkForm. +	 */  	public String build(AuthenticationSession moasession, HttpServletRequest req,  			HttpServletResponse resp) throws WrongParametersException, MOAIDException { @@ -54,25 +63,11 @@ public class StartAuthenticationBuilder {  			throw new AuthenticationException("auth.18", new Object[] { });  		} -	    STORKConfig storkConfig = AuthConfigurationProvider.getInstance().getStorkConfig(); -	     -	    Logger.info("Starting authentication for a citizen of country: " + (StringUtils.isEmpty(moasession.getCcc()) ? "AT" : moasession.getCcc())); -	    // STORK or normal authentication -	    if (storkConfig.isSTORKAuthentication(moasession.getCcc())) { -	    	//STORK authentication -	    	Logger.trace("Found C-PEPS configuration for citizen of country: " + moasession.getCcc()); -	    	Logger.debug("Starting STORK authentication"); -	    	 -	    	AuthenticationServer.startSTORKAuthentication(req, resp, moasession); -	    	return ""; -	    	 -	    } else { -	    	//normal MOA-ID authentication -	    	Logger.debug("Starting normal MOA-ID authentication"); -		    			    	    	 -	    	String getIdentityLinkForm = AuthenticationServer.getInstance().startAuthentication(moasession, req);	    +    	//normal MOA-ID authentication +    	Logger.debug("Starting normal MOA-ID authentication"); +	    			    	    	 +    	String getIdentityLinkForm = AuthenticationServer.getInstance().startAuthentication(moasession, req);	    -	    	return getIdentityLinkForm; -	    } +    	return getIdentityLinkForm;  	}  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java index 26c22fb4a..76bf93249 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java @@ -304,6 +304,8 @@ public class AuthenticationSession implements Serializable {  	private String authnContextClassRef;  	// private String requestedProtocolURL = null; +	private String processInstanceId; +	  	public String getAuthnContextClassRef() {  		return authnContextClassRef;  	} @@ -1110,6 +1112,22 @@ public class AuthenticationSession implements Serializable {  	 */  	public Date getSessionCreated() {  		return sessionCreated; -	}	 +	} + +	/** +	 * Returns the identifier of the process instance associated with this moaid session. +	 * @return The process instance id (may be {@code null} if no process has been created yet). +	 */ +	public String getProcessInstanceId() { +		return processInstanceId; +	} + +	/** +	 * Sets the process instance identifier in order to associate a certain process instance with this moaid session.  +	 * @param processInstanceId The process instance id. +	 */ +	public void setProcessInstanceId(String processInstanceId) { +		this.processInstanceId = processInstanceId; +	}  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java new file mode 100644 index 000000000..67ddd170a --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java @@ -0,0 +1,378 @@ +package at.gv.egovernment.moa.id.auth.modules;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +
 +import java.io.ByteArrayOutputStream;
 +import java.io.IOException;
 +import java.io.InputStream;
 +import java.util.Enumeration;
 +import java.util.HashMap;
 +import java.util.Iterator;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Map.Entry;
 +
 +import javax.servlet.RequestDispatcher;
 +import javax.servlet.ServletContext;
 +import javax.servlet.ServletException;
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.fileupload.FileItem;
 +import org.apache.commons.fileupload.FileItemFactory;
 +import org.apache.commons.fileupload.FileUploadException;
 +import org.apache.commons.fileupload.disk.DiskFileItemFactory;
 +import org.apache.commons.fileupload.servlet.ServletFileUpload;
 +import org.apache.commons.lang3.ArrayUtils;
 +
 +import at.gv.egovernment.moa.id.advancedlogging.StatisticLogger;
 +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.servlet.AuthServlet;
 +import at.gv.egovernment.moa.id.config.ConfigurationException;
 +import at.gv.egovernment.moa.id.entrypoints.DispatcherServlet;
 +import at.gv.egovernment.moa.id.process.springweb.MoaIdTask;
 +import at.gv.egovernment.moa.id.storage.DBExceptionStoreImpl;
 +import at.gv.egovernment.moa.id.storage.IExceptionStore;
 +import at.gv.egovernment.moa.id.util.ServletUtils;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.util.MiscUtil;
 +
 +/**
 + * Task based counterpart to {@link AuthServlet}, providing the same utility methods (error handling, parameter parsing
 + * etc.).</p> The code has been taken from {@link AuthServlet}.
 + */
 +public abstract class AbstractAuthServletTask extends MoaIdTask {
 +
 +	protected static final String ERROR_CODE_PARAM = "errorid";
 +
 +	protected void handleErrorNoRedirect(String errorMessage, Throwable exceptionThrown,
 +			HttpServletRequest req, HttpServletResponse resp) {
 +
 +		if (null != errorMessage) {
 +			Logger.error(errorMessage);
 +			req.setAttribute("ErrorMessage", errorMessage);
 +		}
 +
 +		if (null != exceptionThrown) {
 +			if (null == errorMessage)
 +				errorMessage = exceptionThrown.getMessage();
 +			Logger.error(errorMessage, exceptionThrown);
 +			req.setAttribute("ExceptionThrown", exceptionThrown);
 +		}
 +
 +		if (Logger.isDebugEnabled()) {
 +			req.setAttribute("LogLevel", "debug");
 +		}
 +		
 +		
 +		StatisticLogger logger = StatisticLogger.getInstance();
 +		logger.logErrorOperation(exceptionThrown);
 +		
 +		
 +		// forward this to errorpage-auth.jsp where the HTML error page is
 +		// generated
 +		ServletContext context = req.getServletContext();
 +		RequestDispatcher dispatcher = context
 +				.getRequestDispatcher("/errorpage-auth.jsp");
 +		try {
 +
 +			resp.setHeader(HEADER_EXPIRES, HEADER_VALUE_EXPIRES);
 +			resp.setHeader(HEADER_PRAGMA, HEADER_VALUE_PRAGMA);
 +			resp.setHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL);
 +			resp.addHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL_IE);
 +
 +			dispatcher.forward(req, resp);
 +		} catch (ServletException e) {
 +			Logger.error(e);
 +		} catch (IOException e) {
 +			Logger.error(e);
 +		}
 +	}
 +	
 +	/**
 +	 * Handles an error. <br>>
 +	 * <ul>
 +	 * <li>Logs the error</li>
 +	 * <li>Places error message and exception thrown into the request as request
 +	 * attributes (to be used by <code>"/errorpage-auth.jsp"</code>)</li>
 +	 * <li>Sets HTTP status 500 (internal server error)</li>
 +	 * </ul>
 +	 * 
 +	 * @param errorMessage
 +	 *            error message
 +	 * @param exceptionThrown
 +	 *            exception thrown
 +	 * @param req
 +	 *            servlet request
 +	 * @param resp
 +	 *            servlet response
 +	 */
 +	protected void handleError(String errorMessage, Throwable exceptionThrown,
 +			HttpServletRequest req, HttpServletResponse resp, String pendingRequestID) {
 +
 +		if (null != errorMessage) {
 +			Logger.error(errorMessage);
 +			req.setAttribute("ErrorMessage", errorMessage);
 +		}
 +
 +		if (null != exceptionThrown) {
 +			if (null == errorMessage)
 +				errorMessage = exceptionThrown.getMessage();
 +			Logger.error(errorMessage, exceptionThrown);
 +			req.setAttribute("ExceptionThrown", exceptionThrown);
 +		}
 +
 +		if (Logger.isDebugEnabled()) {
 +			req.setAttribute("LogLevel", "debug");
 +		}
 +
 +		if (!(exceptionThrown instanceof MOAIDException)) {
 +			Logger.error("Receive an internal error: Message=" + exceptionThrown.getMessage(), exceptionThrown);
 +			
 +		}
 +		
 +		IExceptionStore store = DBExceptionStoreImpl.getStore();
 +		String id = store.storeException(exceptionThrown);
 +
 +		if (id != null && MiscUtil.isNotEmpty(pendingRequestID)) {
 +		
 +			String redirectURL = null;
 +
 +			redirectURL = ServletUtils.getBaseUrl(req);
 +			redirectURL += "/dispatcher?" + ERROR_CODE_PARAM + "=" + id 
 +					+ "&" + DispatcherServlet.PARAM_TARGET_PENDINGREQUESTID + "=" + pendingRequestID;
 +		
 +			resp.setContentType("text/html");
 +			resp.setStatus(302);
 +	
 +			resp.addHeader("Location", redirectURL);		
 +			Logger.debug("REDIRECT TO: " + redirectURL);	
 +		
 +			return;
 +			
 +		} else {
 +			
 +			//Exception can not be stored in database
 +			handleErrorNoRedirect(errorMessage, exceptionThrown, req, resp);
 +		}
 +	}
 +
 +	/**
 +	 * Handles a <code>WrongParametersException</code>.
 +	 * 
 +	 * @param req
 +	 *            servlet request
 +	 * @param resp
 +	 *            servlet response
 +	 */
 +	protected void handleWrongParameters(WrongParametersException ex,
 +			HttpServletRequest req, HttpServletResponse resp) {
 +		Logger.error(ex.toString());
 +		req.setAttribute("WrongParameters", ex.getMessage());
 +
 +		// forward this to errorpage-auth.jsp where the HTML error page is
 +		// generated
 +		ServletContext context = req.getServletContext();
 +		RequestDispatcher dispatcher = context
 +				.getRequestDispatcher("/errorpage-auth.jsp");
 +		try {
 +			setNoCachingHeaders(resp);
 +			dispatcher.forward(req, resp);
 +		} catch (ServletException e) {
 +			Logger.error(e);
 +		} catch (IOException e) {
 +			Logger.error(e);
 +		}
 +	}
 +
 +	/**
 +	 * Logs all servlet parameters for debugging purposes.
 +	 */
 +	protected void logParameters(HttpServletRequest req) {
 +		for (Enumeration params = req.getParameterNames(); params
 +				.hasMoreElements();) {
 +			String parname = (String) params.nextElement();
 +			Logger.debug("Parameter " + parname + req.getParameter(parname));
 +		}
 +	}
 +
 +	/**
 +	 * Parses the request input stream for parameters, assuming parameters are
 +	 * encoded UTF-8 (no standard exists how browsers should encode them).
 +	 * 
 +	 * @param req
 +	 *            servlet request
 +	 * 
 +	 * @return mapping parameter name -> value
 +	 * 
 +	 * @throws IOException
 +	 *             if parsing request parameters fails.
 +	 * 
 +	 * @throws FileUploadException
 +	 *             if parsing request parameters fails.
 +	 */
 +	protected Map<String, String> getParameters(HttpServletRequest req) throws IOException,
 +			FileUploadException {
 +
 +		Map<String, String> parameters = new HashMap<String, String>();
 +
 +		if (ServletFileUpload.isMultipartContent(req)) {
 +			// request is encoded as mulitpart/form-data
 +			FileItemFactory factory = new DiskFileItemFactory();
 +			ServletFileUpload upload = null;
 +			upload = new ServletFileUpload(factory);
 +			List items = null;
 +			items = upload.parseRequest(req);
 +			for (int i = 0; i < items.size(); i++) {
 +				FileItem item = (FileItem) items.get(i);
 +				if (item.isFormField()) {
 +					// Process only form fields - no file upload items
 +					String logString = item.getString("UTF-8");
 +
 +					// TODO use RegExp
 +					String startS = "<pr:Identification><pr:Value>";
 +					String endS = "</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type>";
 +					String logWithMaskedBaseid = logString;
 +					int start = logString.indexOf(startS);
 +					if (start > -1) {
 +						int end = logString.indexOf(endS);
 +						if (end > -1) {
 +							logWithMaskedBaseid = logString.substring(0, start);
 +							logWithMaskedBaseid += startS;
 +							logWithMaskedBaseid += "xxxxxxxxxxxxxxxxxxxxxxxx";
 +							logWithMaskedBaseid += logString.substring(end,
 +									logString.length());
 +						}
 +					}
 +					parameters
 +							.put(item.getFieldName(), item.getString("UTF-8"));
 +					Logger.debug("Processed multipart/form-data request parameter: \nName: "
 +							+ item.getFieldName()
 +							+ "\nValue: "
 +							+ logWithMaskedBaseid);
 +				}
 +			}
 +		}
 +
 +		else {
 +			// request is encoded as application/x-www-urlencoded
 +			// [tknall]: we must not consume request body input stream once servlet-api request parameters have been accessed
 +			
 +			/*
 +			InputStream in = req.getInputStream();
 +
 +			String paramName;
 +			String paramValueURLEncoded;
 +			do {
 +				paramName = new String(readBytesUpTo(in, '='));
 +				if (paramName.length() > 0) {
 +					paramValueURLEncoded = readBytesUpTo(in, '&');
 +					String paramValue = URLDecoder.decode(paramValueURLEncoded,
 +							"UTF-8");
 +					parameters.put(paramName, paramValue);
 +				}
 +			} while (paramName.length() > 0);
 +			in.close();
 +			*/
 +			
 +			Iterator<Entry<String, String[]>> requestParamIt = req.getParameterMap().entrySet().iterator();
 +			while (requestParamIt.hasNext()) {
 +				Entry<String, String[]> entry = requestParamIt.next();
 +				String key = entry.getKey();
 +				String[] values = entry.getValue();
 +				// take the last value from the value array since the legacy code above also does it this way
 +				parameters.put(key, ArrayUtils.isEmpty(values) ? null : values[values.length-1]); 
 +			}
 +			
 +		}
 +
 +		return parameters;
 +	}
 +
 +	/**
 +	 * Reads bytes up to a delimiter, consuming the delimiter.
 +	 * 
 +	 * @param in
 +	 *            input stream
 +	 * @param delimiter
 +	 *            delimiter character
 +	 * @return String constructed from the read bytes
 +	 * @throws IOException
 +	 */
 +	protected String readBytesUpTo(InputStream in, char delimiter)
 +			throws IOException {
 +		ByteArrayOutputStream bout = new ByteArrayOutputStream();
 +		boolean done = false;
 +		int b;
 +		while (!done && (b = in.read()) >= 0) {
 +			if (b == delimiter)
 +				done = true;
 +			else
 +				bout.write(b);
 +		}
 +		return bout.toString();
 +	}
 +
 +	/**
 +	 * Sets response headers that prevent caching (code taken from {@link AuthServlet}).
 +	 * 
 +	 * @param resp
 +	 *            The HttpServletResponse.
 +	 */
 +	public void setNoCachingHeaders(HttpServletResponse resp) {
 +		resp.setHeader(HEADER_EXPIRES, HEADER_VALUE_EXPIRES);
 +		resp.setHeader(HEADER_PRAGMA, HEADER_VALUE_PRAGMA);
 +		resp.setHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL);
 +		resp.addHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL_IE);
 +	}
 +
 +	/**
 +	 * Adds a parameter to a URL.
 +	 * 
 +	 * @param url
 +	 *            the URL
 +	 * @param paramname
 +	 *            parameter name
 +	 * @param paramvalue
 +	 *            parameter value
 +	 * @return the URL with parameter added
 +	 */
 +	protected static String addURLParameter(String url, String paramname,
 +			String paramvalue) {
 +		String param = paramname + "=" + paramvalue;
 +		if (url.indexOf("?") < 0)
 +			return url + "?" + param;
 +		else
 +			return url + "&" + param;
 +	}
 +
 +	/**
 +	 * Checks if HTTP requests are allowed
 +	 * 
 +	 * @param authURL
 +	 *            requestURL
 +	 * @throws AuthenticationException
 +	 *             if HTTP requests are not allowed
 +	 * @throws ConfigurationException
 +	 */
 +	protected void checkIfHTTPisAllowed(String authURL)
 +			throws AuthenticationException, ConfigurationException {
 +		// check if HTTP Connection may be allowed (through
 +		// FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY)
 +		
 +		//Removed from MOA-ID 2.0 config
 +//		String boolStr = AuthConfigurationProvider
 +//				.getInstance()
 +//				.getGenericConfigurationParameter(
 +//						AuthConfigurationProvider.FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY);
 +		if ((!authURL.startsWith("https:"))
 +				//&& (false == BoolUtils.valueOf(boolStr))
 +				)
 +			throw new AuthenticationException("auth.07", new Object[] { authURL
 +					+ "*" });
 +
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AuthModule.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AuthModule.java new file mode 100644 index 000000000..a31f3ceb0 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AuthModule.java @@ -0,0 +1,41 @@ +package at.gv.egovernment.moa.id.auth.modules; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.model.ProcessDefinition; + +/** + * Provides metadata of a certain module. Uses for module discovery and process selection. + */ +public interface AuthModule { + +	/** +	 * Returns the priority of the module. The priority defines the order of the respective module within the chain of +	 * discovered modules. Higher priorized modules are asked before lower priorized modules for a process that they can +	 * handle. +	 * <p/> +	 * Internal default modules are priorized neutral ({@code 0}. Use a higher priority ({@code 1...Integer.MAX_VALUE}) +	 * in order to have your module(s) priorized or a lower priority ({@code Integer.MIN_VALUE...-1}) in order to put +	 * your modules behind default modules. +	 *  +	 * @return the priority of the module. +	 */ +	int getPriority(); + +	/** +	 * Checks if the module has a process, which is able to perform an authentication with the given +	 * {@link ExecutionContext}. +	 *  +	 * @param context +	 *            an ExecutionContext for a process. +	 * @return the process-ID of a process which is able to work with the given ExecutionContext, or {@code null}. +	 */ +	String selectProcess(ExecutionContext context); + +	/** +	 * Returns the an Array of {@link ProcessDefinition}s of the processes included in this module. +	 *  +	 * @return an array of resource uris of the processes included in this module. +	 */ +	String[] getProcessDefinitions(); + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthModuleImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthModuleImpl.java new file mode 100644 index 000000000..8ae4a9999 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthModuleImpl.java @@ -0,0 +1,28 @@ +package at.gv.egovernment.moa.id.auth.modules.internal; + +import org.apache.commons.lang3.StringUtils; + +import at.gv.egovernment.moa.id.auth.modules.AuthModule; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; + +/** + * Module descriptor + */ +public class DefaultAuthModuleImpl implements AuthModule { + +	@Override +	public int getPriority() { +		return 0; +	} + +	@Override +	public String selectProcess(ExecutionContext context) { +		return StringUtils.isBlank((String) context.get("ccc")) ? "DefaultAuthentication" : null; +	} + +	@Override +	public String[] getProcessDefinitions() { +		return new String[] { "classpath:at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthentication.process.xml" }; +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CertificateReadRequestTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CertificateReadRequestTask.java new file mode 100644 index 000000000..bc73a9f2f --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CertificateReadRequestTask.java @@ -0,0 +1,101 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.lang.StringEscapeUtils;
 +import org.apache.commons.lang3.BooleanUtils;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
 +import at.gv.egovernment.moa.id.auth.builder.InfoboxReadRequestBuilderCertificate;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.id.util.ServletUtils;
 +import at.gv.egovernment.moa.logging.Logger;
 +
 +/**
 + * Creates {@code InfoBoxReadRequest} in order to read the subject's certificates.<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Creates {@code InfoBoxReadRequest} in order to read the subject's certificates.</li>
 + * <li>Responds with {@code InfoBoxReadRequest} (for CCE), {@code DataURL} is {@code /VerifyCertificate}</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Responds with {@code InfoBoxReadRequest} (for CCE), {@code DataURL} is {@code /VerifyCertificate}</li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class CertificateReadRequestTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws Exception {
 +
 +		// TODO[branch]: Foreign citizen or mandate mode; respond with IRR for certificates, dataURL = "/VerifyCertificate"
 +		Logger.info("Send InfoboxReadRequest to BKU to get signer certificate.");
 +
 +		setNoCachingHeaders(resp);
 +
 +		String pendingRequestID = null;
 +		
 +		try {
 +		
 +			String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
 +			
 +			// check parameter
 +			if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
 +				throw new WrongParametersException("CertificateReadRequestTask", PARAM_SESSIONID, "auth.12");
 +			}
 +
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
 +
 +			AuthenticationSession session = AuthenticationServer.getSession(sessionID);
 +
 +			boolean useMandate = session.getUseMandate();
 +			boolean identityLinkAvailable = BooleanUtils.isTrue((Boolean) executionContext.get("identityLinkAvailable"));
 +			
 +			if (!identityLinkAvailable && useMandate) {
 +				Logger.error("Online-Mandate Mode for foreign citizencs not supported.");
 +				throw new AuthenticationException("auth.13", null);
 +			}
 +
 +			// change MOASessionID
 +			AuthenticationSessionStoreage.changeSessionID(session);
 +			
 +			// create the InfoboxReadRequest to get the certificate
 +			String infoboxReadRequest = new InfoboxReadRequestBuilderCertificate().build(true);
 +
 +			// build dataurl (to the VerifyCertificateSerlvet)
 +			String dataurl = new DataURLBuilder().buildDataURL(session.getAuthURL(), REQ_VERIFY_CERTIFICATE,
 +					session.getSessionID());
 +
 +			ServletUtils.writeCreateXMLSignatureRequest(resp, infoboxReadRequest,
 +					AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);
 +		
 +		} catch (MOAIDException ex) {
 +			handleError(null, ex, req, resp, pendingRequestID);
 +		} finally {
 +			ConfigurationDBUtils.closeSession();
 +		}		
 +
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateIdentityLinkFormTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateIdentityLinkFormTask.java new file mode 100644 index 000000000..4cd1ea94e --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateIdentityLinkFormTask.java @@ -0,0 +1,119 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +
 +import java.io.PrintWriter;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.lang.StringEscapeUtils;
 +import org.apache.commons.lang3.ObjectUtils;
 +
 +import at.gv.egovernment.moa.id.auth.builder.StartAuthenticationBuilder;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.auth.servlet.GenerateIFrameTemplateServlet;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.util.MiscUtil;
 +import at.gv.egovernment.moa.util.StringUtils;
 +
 +/**
 + * Creates a http form including an embedded {@code InfoBoxReadRequest} for reading the identity link.<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Removes ExecutionContext property {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}.</li>
 + * <li>Creates the http form mentioned above.</li>
 + * <li>Returns the http form via HttpServletResponse.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID} <strong>or</strong></li>
 + * <li>ExecutionContext property {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID} (in case of legacy authentication without CCE selection, where the moa session is not provided by request parameter).</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>The identity link form via HttpServletResponse.</li>
 + * </ul>
 + * Possible branches:
 + * <ul>
 + * <li>In case of STORK authentication
 + * <ul>
 + * <li>Creates STORK auth SAML request.</li>
 + * <li>Creates and returns a form for submitting the SAML request to the CPEPS (post binding).</li>
 + * <li>Returns the form via HttpServletResponse.</li>
 + * </ul>
 + * </li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GenerateIFrameTemplateServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class CreateIdentityLinkFormTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws Exception {
 +
 +		String pendingRequestID = null;
 +		String moasessionid = StringEscapeUtils.escapeHtml(ObjectUtils.defaultIfNull(req.getParameter(PARAM_SESSIONID), (String) executionContext.get(PARAM_SESSIONID)));
 +		AuthenticationSession moasession = null;
 +		try {
 +			
 +			if (MiscUtil.isEmpty(moasessionid)) {
 +				Logger.warn("MOASessionID is empty.");
 +				throw new MOAIDException("auth.18", new Object[] {});
 +			}
 +			
 +			try {
 +			
 +				pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(moasessionid);
 +				moasession = AuthenticationSessionStoreage.getSession(moasessionid);
 +				AuthenticationSessionStoreage.changeSessionID(moasession);
 +				executionContext.remove(PARAM_SESSIONID);
 +			
 +			} catch (MOADatabaseException e) {
 +				Logger.info("MOASession with SessionID=" + moasessionid + " is not found in Database");
 +				throw new MOAIDException("init.04", new Object[] { moasessionid });
 +
 +			} catch (Throwable e) {
 +				Logger.info("No HTTP Session found!");
 +				throw new MOAIDException("auth.18", new Object[] {});
 +			}
 +
 +			StartAuthenticationBuilder startauth = StartAuthenticationBuilder.getInstance();
 +			String getIdentityLinkForm = startauth.build(moasession, req, resp);
 +
 +			if (!StringUtils.isEmpty(getIdentityLinkForm)) {
 +				resp.setContentType("text/html;charset=UTF-8");
 +				PrintWriter out = new PrintWriter(resp.getOutputStream());
 +				out.print(getIdentityLinkForm);
 +				out.flush();
 +				Logger.debug("Finished GET " + GenerateIFrameTemplateServlet.class);
 +			}
 +			
 +		} catch (WrongParametersException ex) {
 +			handleWrongParameters(ex, req, resp);
 +		}
 +
 +		catch (MOAIDException ex) {
 +			handleError(null, ex, req, resp, pendingRequestID);
 +
 +		} catch (Exception e) {
 +			Logger.error("CreateIdentityLinkFormTask has an interal Error.", e);
 +
 +		}
 +
 +		finally {
 +			ConfigurationDBUtils.closeSession();
 +		}
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetForeignIDTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetForeignIDTask.java new file mode 100644 index 000000000..4771628a3 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetForeignIDTask.java @@ -0,0 +1,182 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +
 +import java.io.ByteArrayInputStream;
 +import java.io.IOException;
 +import java.security.cert.CertificateException;
 +import java.util.Map;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +import javax.xml.transform.TransformerException;
 +
 +import org.apache.commons.fileupload.FileUploadException;
 +import org.apache.commons.lang.StringEscapeUtils;
 +import org.w3c.dom.Element;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.data.CreateXMLSignatureResponse;
 +import at.gv.egovernment.moa.id.auth.data.IdentityLink;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.ParseException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.auth.parser.CreateXMLSignatureResponseParser;
 +import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
 +import at.gv.egovernment.moa.id.client.SZRGWClientException;
 +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
 +import at.gv.egovernment.moa.id.moduls.ModulUtils;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.util.DOMUtils;
 +import at.gv.util.xsd.srzgw.CreateIdentityLinkResponse;
 +
 +/**
 + * Evaluates the {@code CreateXMLSignatureResponse}, extracts signature and certificate and asks the SZR Gateway for an identity link.<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Parses the CreateXMLSignatureResponse retrieved from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
 + * <li>Extracts signature and signer certificate.</li>
 + * <li>Send request to SZR Gateway in order to get an identity link.</li>
 + * <li>Updates moa session (sets identity link, QAA level 4, authentication data and foreigner flag).</li>
 + * <li>Redirects back to {@code /dispatcher} in order to finalize authentication.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE} containing a {@code CreateXMLSignatureResponse}.</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Identity link, QAA level 4 and foreigner flag put into moa session.</li>
 + * <li>Redirect to {@code /dispatcher}.</li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GetForeignIDServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class GetForeignIDTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws Exception {
 +
 +		Logger.debug("POST GetForeignIDServlet");
 +
 +		setNoCachingHeaders(resp);
 +
 +		Map<String, String> parameters;
 +
 +		try {
 +			parameters = getParameters(req);
 +		} catch (FileUploadException e) {
 +			Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
 +			throw new IOException(e.getMessage());
 +		}
 +		
 +		String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
 +		String pendingRequestID = null;
 +		String redirectURL = null;
 +		AuthenticationSession session = null;
 +		try {
 +			// check parameter
 +			if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
 +				throw new WrongParametersException("GetForeignID", PARAM_SESSIONID, "auth.12");
 +			}
 +			String xmlCreateXMLSignatureResponse = (String) parameters.get(PARAM_XMLRESPONSE);
 +			if (!ParamValidatorUtils.isValidXMLDocument(xmlCreateXMLSignatureResponse)) {
 +				throw new WrongParametersException("GetForeignID", PARAM_XMLRESPONSE, "auth.12");
 +			}
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
 +			session = AuthenticationServer.getSession(sessionID);
 +
 +			// change MOASessionID
 +			sessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +
 +			Logger.debug(xmlCreateXMLSignatureResponse);
 +
 +			CreateXMLSignatureResponse csresp = new CreateXMLSignatureResponseParser(xmlCreateXMLSignatureResponse)
 +					.parseResponseDsig();
 +
 +			try {
 +				String serializedAssertion = DOMUtils.serializeNode(csresp.getDsigSignature());
 +				session.setAuthBlock(serializedAssertion);
 +
 +			} catch (TransformerException e) {
 +				throw new ParseException("parser.04", new Object[] { REQ_VERIFY_AUTH_BLOCK, PARAM_XMLRESPONSE });
 +
 +			} catch (IOException e) {
 +				throw new ParseException("parser.04", new Object[] { REQ_VERIFY_AUTH_BLOCK, PARAM_XMLRESPONSE });
 +
 +			}
 +
 +			Element signature = csresp.getDsigSignature();
 +
 +			try {
 +				session.setSignerCertificate(AuthenticationServer.getCertificateFromXML(signature));
 +			} catch (CertificateException e) {
 +				Logger.error("Could not extract certificate from CreateXMLSignatureResponse");
 +				throw new MOAIDException("auth.14", null);
 +			}
 +
 +			// make SZR request to the identity link
 +			CreateIdentityLinkResponse response = AuthenticationServer.getInstance().getIdentityLink(signature);
 +
 +			if (null != response.getErrorResponse()) {
 +				// TODO fix exception parameter
 +				throw new SZRGWClientException("service.08", (String) response.getErrorResponse().getErrorCode(),
 +						(String) response.getErrorResponse().getInfo());
 +			} else {
 +				IdentityLinkAssertionParser ilParser = new IdentityLinkAssertionParser(new ByteArrayInputStream(
 +						response.getIdentityLink()));
 +				IdentityLink identitylink = ilParser.parseIdentityLink();
 +				session.setIdentityLink(identitylink);
 +
 +				// set QAA Level four in case of card authentifcation
 +				session.setQAALevel(PVPConstants.STORK_QAA_1_4);
 +
 +				AuthenticationServer.getInstance().getForeignAuthenticationData(session);
 +
 +				// session is implicit stored in changeSessionID!!!!
 +				String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +
 +				Logger.info("Changed MOASession " + sessionID + " to Session " + newMOASessionID);
 +				Logger.info("Daten angelegt zu MOASession " + newMOASessionID);
 +
 +				redirectURL = new DataURLBuilder().buildDataURL(session.getAuthURL(),
 +						ModulUtils.buildAuthURL(session.getModul(), session.getAction(), pendingRequestID),
 +						newMOASessionID);
 +				redirectURL = resp.encodeRedirectURL(redirectURL);
 +
 +				// TODO[branch]: Final step back to /dispatcher
 +
 +				try {
 +					AuthenticationSessionStoreage.storeSession(session);
 +				} catch (MOADatabaseException e) {
 +					throw new MOAIDException("Session store error", null);
 +				}
 +
 +				resp.setContentType("text/html");
 +				resp.setStatus(302);
 +				resp.addHeader("Location", redirectURL);
 +				Logger.debug("REDIRECT TO: " + redirectURL);
 +			}
 +
 +		} catch (MOAIDException ex) {
 +			handleError(null, ex, req, resp, pendingRequestID);
 +
 +		} catch (Exception e) {
 +			Logger.error("GetForeignIDServlet has an interal Error.", e);
 +
 +		}
 +
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetMISSessionIDTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetMISSessionIDTask.java new file mode 100644 index 000000000..f08f96782 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetMISSessionIDTask.java @@ -0,0 +1,181 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +import iaik.pki.PKIException;
 +
 +import java.security.GeneralSecurityException;
 +import java.util.List;
 +
 +import javax.net.ssl.SSLSocketFactory;
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +import javax.xml.parsers.ParserConfigurationException;
 +
 +import org.apache.commons.lang.StringEscapeUtils;
 +import org.xml.sax.SAXException;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.config.ConnectionParameter;
 +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
 +import at.gv.egovernment.moa.id.moduls.ModulUtils;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.id.util.SSLUtils;
 +import at.gv.egovernment.moa.id.util.client.mis.simple.MISMandate;
 +import at.gv.egovernment.moa.id.util.client.mis.simple.MISSimpleClient;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.util.DOMUtils;
 +
 +/**
 + * Retrieves a mandate from the online mandate issuing service.<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Retrieves the mandate referenced within the moa session from the online (external) mandate issuing service.</li>
 + * <li>Verifies the mandate.</li>
 + * <li>Puts mandate into moa session.</li>
 + * <li>Redirects back to {@code /dispatcher} in order to finalize the authentication.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Mandate put into moa session.</li>
 + * <li>Redirect to {@code /dispatcher}.</li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GetMISSessionIDServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class GetMISSessionIDTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws Exception {
 +		
 +		Logger.debug("POST GetMISSessionIDServlet");
 +
 +		String sessionID = req.getParameter(PARAM_SESSIONID);
 +
 +		// escape parameter strings
 +		sessionID = StringEscapeUtils.escapeHtml(sessionID);
 +
 +		AuthenticationSession session = null;
 +		String pendingRequestID = null;
 +		try {
 +			// check parameter
 +			if (!ParamValidatorUtils.isValidSessionID(sessionID))
 +				throw new WrongParametersException("VerifyCertificate",
 +						PARAM_SESSIONID, "auth.12");
 +
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
 +			
 +			session = AuthenticationServer.getSession(sessionID);
 +
 +			//change MOASessionID
 +		    sessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +			
 +			String misSessionID = session.getMISSessionID();
 +
 +			AuthConfigurationProvider authConf = AuthConfigurationProvider
 +					.getInstance();
 +			ConnectionParameter connectionParameters = authConf
 +					.getOnlineMandatesConnectionParameter();
 +			SSLSocketFactory sslFactory = SSLUtils.getSSLSocketFactory(
 +					AuthConfigurationProvider.getInstance(),
 +					connectionParameters);
 +
 +			List<MISMandate> list = MISSimpleClient.sendGetMandatesRequest(
 +					connectionParameters.getUrl(), misSessionID, sslFactory);
 +
 +			if (list == null || list.size() == 0) {
 +				Logger.error("Keine Vollmacht gefunden.");
 +				throw new AuthenticationException("auth.15", null);
 +			}
 +
 +			// for now: list contains only one element
 +			MISMandate mandate = (MISMandate) list.get(0);
 +
 +			// TODO[tlenz]: UTF-8 ?
 +			String sMandate = new String(mandate.getMandate());
 +			if (sMandate == null || sMandate.compareToIgnoreCase("") == 0) {
 +				Logger.error("Mandate is empty.");
 +				throw new AuthenticationException("auth.15",
 +						new Object[] { GET_MIS_SESSIONID });
 +			}
 +						
 +			//check if it is a parsable XML
 +			byte[] byteMandate = mandate.getMandate();
 +			// TODO[tlenz]: UTF-8 ?
 +			String stringMandate = new String(byteMandate);
 +			DOMUtils.parseDocument(stringMandate, false,
 +					null, null).getDocumentElement();
 +			
 +			// extract RepresentationType
 +			AuthenticationServer.getInstance().verifyMandate(session, mandate);
 +			
 +			session.setMISMandate(mandate);
 +			session.setAuthenticatedUsed(false);
 +			session.setAuthenticated(true);
 +			
 +	    	//set QAA Level four in case of card authentifcation
 +	    	session.setQAALevel(PVPConstants.STORK_QAA_1_4);
 +			
 +			String oldsessionID = session.getSessionID();
 +			
 +			//Session is implicite stored in changeSessionID!!!
 +			String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +			
 +			Logger.info("Changed MOASession " + oldsessionID + " to Session " + newMOASessionID);
 +			Logger.info("Daten angelegt zu MOASession " + newMOASessionID);
 +						
 +			String redirectURL = new DataURLBuilder().buildDataURL(
 +					session.getAuthURL(),
 +					ModulUtils.buildAuthURL(session.getModul(),
 +							session.getAction(), pendingRequestID), newMOASessionID);
 +			redirectURL = resp.encodeRedirectURL(redirectURL);
 +			
 +			// TODO[branch]: Final step back to /dispatcher
 +			
 +			resp.setContentType("text/html");
 +			resp.setStatus(302);
 +			resp.addHeader("Location", redirectURL);
 +			Logger.debug("REDIRECT TO: " + redirectURL);
 +
 +		} catch (MOAIDException ex) {
 +			handleError(null, ex, req, resp, pendingRequestID);
 +			
 +		} catch (GeneralSecurityException ex) {
 +			handleError(null, ex, req, resp, pendingRequestID);
 +			
 +		} catch (PKIException e) {
 +			handleError(null, e, req, resp, pendingRequestID);
 +			
 +		} catch (SAXException e) {
 +			handleError(null, e, req, resp, pendingRequestID);
 +			
 +		} catch (ParserConfigurationException e) {
 +			handleError(null, e, req, resp, pendingRequestID);
 +			
 +	    } catch (Exception e) {
 +	    	Logger.error("MISMandateValidation has an interal Error.", e);
 +	       
 +	    }
 +	    finally {
 +	    	ConfigurationDBUtils.closeSession();
 +	    }
 +		
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/PrepareAuthBlockSignatureTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/PrepareAuthBlockSignatureTask.java new file mode 100644 index 000000000..dcea3a1dd --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/PrepareAuthBlockSignatureTask.java @@ -0,0 +1,102 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.lang.StringEscapeUtils;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
 +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.id.util.ServletUtils;
 +import at.gv.egovernment.moa.logging.Logger;
 +
 +/**
 + * Creates {@code CreateXMLSignatureRequest} for auth block signature.<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Creates {@code CreateXMLSignatureRequest} for auth block signature.</li>
 + * <li>Responds with {@code CreateXMLSignatureRequest} (for CCE), {@code DataURL} is {@code /VerifyAuthBlock}</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Responds with {@code CreateXMLSignatureRequest} (for CCE), {@code DataURL} is {@code /VerifyAuthBlock}</li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class PrepareAuthBlockSignatureTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws Exception {
 +		// note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet
 +
 +		Logger.debug("Process IdentityLink");
 +
 +		setNoCachingHeaders(resp);
 +		
 +		String pendingRequestID = null;
 +
 +		try {
 +			
 +			String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
 +			
 +			// check parameter
 +			if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
 +				throw new WrongParametersException("VerifyIdentityLink", PARAM_SESSIONID, "auth.12");
 +			}
 +
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
 +
 +			AuthenticationSession session = AuthenticationServer.getSession(sessionID);
 +
 +			// change MOASessionID
 +			sessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +				
 +			Logger.info("Normal");
 +
 +			// TODO[branch]: Default behaviour; respond with CXSR for authblock signature, dataURL "/VerifyAuthBlock"
 +
 +			OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
 +					session.getPublicOAURLPrefix());
 +			AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance();
 +
 +			String createXMLSignatureRequest = AuthenticationServer.getInstance()
 +					.getCreateXMLSignatureRequestAuthBlockOrRedirect(session, authConf, oaParam);
 +
 +			AuthenticationSessionStoreage.storeSession(session);
 +			
 +			ServletUtils.writeCreateXMLSignatureRequestOrRedirect(resp, session,
 +					createXMLSignatureRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT,
 +					"VerifyIdentityLink");
 +
 +		} catch (MOAIDException ex) {
 +			handleError(null, ex, req, resp, pendingRequestID);
 +
 +		} catch (Exception e) {
 +			Logger.error("IdentityLinkValidation has an interal Error.", e);
 +		}
 +
 +		finally {
 +			ConfigurationDBUtils.closeSession();
 +		}
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java new file mode 100644 index 000000000..1e1a4df89 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java @@ -0,0 +1,246 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +import iaik.pki.PKIException;
 +
 +import java.io.IOException;
 +import java.security.GeneralSecurityException;
 +import java.util.List;
 +import java.util.Map;
 +
 +import javax.net.ssl.SSLSocketFactory;
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +import javax.xml.transform.TransformerException;
 +
 +import org.apache.commons.fileupload.FileUploadException;
 +import org.apache.commons.lang.StringEscapeUtils;
 +import org.w3c.dom.Element;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.MISSimpleClientException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
 +import at.gv.egovernment.moa.id.config.ConnectionParameter;
 +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
 +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
 +import at.gv.egovernment.moa.id.moduls.ModulUtils;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.id.util.SSLUtils;
 +import at.gv.egovernment.moa.id.util.client.mis.simple.MISSessionId;
 +import at.gv.egovernment.moa.id.util.client.mis.simple.MISSimpleClient;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.util.DOMUtils;
 +
 +/**
 + * Verifies the signed authentication block (provided as {@code CreateXMLSignatureResponse}).<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Takes the {@code CreateXMLSignatureResponse} from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
 + * <li>Verifies the {@code CreateXMLSignatureResponse}.</li>
 + * <li>Updates moa session.</li>
 + * <li>Redirects back to {@code /dispatcher} in order to finalize the authentication.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE} containing a {@code CreateXMLSignatureResponse}.</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Authentication data put into moa session.</li>
 + * <li>Redirect to {@code /dispatcher}.</li>
 + * </ul>
 + * Possible branches:
 + * <ul>
 + * <li>In case of mandate mode
 + * <ul>
 + * <li>Creates a mandate session at the external mandate issuing service.</li>
 + * <li>Redirects the user's browser to the online mandate issuing service GUI.</li>
 + * </ul>
 + * </li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyAuthenticationBlockServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class VerifyAuthenticationBlockTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws Exception {
 +
 +		// note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyAuthenticationBlockServlet
 +		
 +		Logger.debug("POST VerifyAuthenticationBlock");
 +		
 +		String pendingRequestID = null;		
 +		
 +	    Map<String, String> parameters;
 +	    try 
 +	    {
 +	      parameters = getParameters(req);
 +	    } catch (FileUploadException e) 
 +	    {
 +	      Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
 +	      throw new IOException(e.getMessage());
 +	      
 +	    }
 +			String sessionID = req.getParameter(PARAM_SESSIONID);
 +			String createXMLSignatureResponse = (String)parameters.get(PARAM_XMLRESPONSE);
 +
 +			// escape parameter strings
 +			sessionID = StringEscapeUtils.escapeHtml(sessionID);
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
 +		   		
 +			String redirectURL = null;
 +			try {
 +	         // check parameter
 +	         if (!ParamValidatorUtils.isValidSessionID(sessionID))
 +	            throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID, "auth.12");
 +	         if (!ParamValidatorUtils.isValidXMLDocument(createXMLSignatureResponse))
 +	            throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_XMLRESPONSE, "auth.12");
 +
 +				AuthenticationSession session = AuthenticationServer.getSession(sessionID);
 +
 +				//change MOASessionID
 +			    sessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +				
 +				String authenticatedMOASessionId = AuthenticationServer.getInstance().verifyAuthenticationBlock(session, createXMLSignatureResponse);
 +				
 +				if (authenticatedMOASessionId == null) { 
 +					//mandate Mode
 +				
 +					  AuthConfigurationProvider authConf= AuthConfigurationProvider.getInstance();
 +						ConnectionParameter connectionParameters = authConf.getOnlineMandatesConnectionParameter();	
 +						SSLSocketFactory sslFactory = SSLUtils.getSSLSocketFactory(AuthConfigurationProvider.getInstance(), connectionParameters);
 +						
 +						// get identitity link as byte[]
 +						Element elem = session.getIdentityLink().getSamlAssertion();
 +						String s = DOMUtils.serializeNode(elem);
 +						
 +						//System.out.println("IDL: " + s);
 +						
 +						byte[] idl = s.getBytes("UTF-8");
 +						
 +						// redirect url
 +						// build redirect(to the GetMISSessionIdSerlvet)
 +						
 +						//change MOASessionID before MIS request
 +						String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +						
 +				        redirectURL =
 +				              new DataURLBuilder().buildDataURL(
 +				                session.getAuthURL(),
 +				                GET_MIS_SESSIONID,
 +				                newMOASessionID);
 +						
 +				        String oaURL = session.getOAURLRequested();
 +				        OAAuthParameter oaParam = authConf.getOnlineApplicationParameter(oaURL);
 +				        List<String> profiles = oaParam.getMandateProfiles();
 +
 +				        if (profiles == null) {
 +				      	  Logger.error("No Mandate/Profile for OA configured.");
 +				      	  throw new AuthenticationException("config.21", new Object[] { GET_MIS_SESSIONID});
 +				        }
 +				        
 +				        String oaFriendlyName = oaParam.getFriendlyName();
 +				        String mandateReferenceValue = session.getMandateReferenceValue();
 +				        byte[] cert = session.getEncodedSignerCertificate();
 +				        byte[] authBlock = session.getAuthBlock().getBytes("UTF-8");
 +				        
 +				        //TODO: check in case of SSO!!!
 +				        String targetType = null;  
 +				        if(oaParam.getBusinessService()) {
 +				        	String id = oaParam.getIdentityLinkDomainIdentifier();
 +				        	if (id.startsWith(AuthenticationSession.REGISTERANDORDNR_PREFIX_))
 +				        		targetType = id;
 +				        	else
 +				        		targetType = AuthenticationSession.REGISTERANDORDNR_PREFIX_+session.getDomainIdentifier();
 +				        	
 +				        } else {
 +				        	targetType = AuthenticationSession.TARGET_PREFIX_ + oaParam.getTarget();
 +				        }
 +				        
 +				        MISSessionId misSessionID = MISSimpleClient.sendSessionIdRequest(
 +				        		connectionParameters.getUrl(), 
 +				        		idl, 
 +				        		cert, 
 +				        		oaFriendlyName, 
 +				        		redirectURL, 
 +				        		mandateReferenceValue, 
 +				        		profiles, 
 +				        		targetType,
 +				        		authBlock,
 +				        		sslFactory);
 +				        
 +				        if (misSessionID == null) {
 +				      	  Logger.error("Fehler bei Anfrage an Vollmachten Service. MIS Session ID ist null.");
 +				      	  throw new MISSimpleClientException("Fehler bei Anfrage an Vollmachten Service.");
 +				        }
 +				        
 +				        String redirectMISGUI = misSessionID.getRedirectURL();
 +				        session.setMISSessionID(misSessionID.getSessiondId());
 +					
 +						try {
 +							AuthenticationSessionStoreage.storeSession(session);
 +						} catch (MOADatabaseException e) {
 +							throw new MOAIDException("Session store error", null);
 +						}
 +				        
 +						// TODO[branch]: Mandate; redirect to MIS website; website redirects back to "/GetMISSessionID"
 +						
 +				        resp.setStatus(302);
 +				    	  resp.addHeader("Location", redirectMISGUI);
 +				    	  Logger.debug("REDIRECT TO: " + redirectURL);
 +				}
 +				else {
 +					// TODO[branch]: Final step back to /dispatcher
 +					redirectURL = new DataURLBuilder().buildDataURL(session.getAuthURL(), 
 +							ModulUtils.buildAuthURL(session.getModul(), session.getAction(), pendingRequestID), authenticatedMOASessionId);
 +							
 +					resp.setContentType("text/html");
 +					resp.setStatus(302);
 +				
 +					resp.addHeader("Location", redirectURL);		
 +					Logger.debug("REDIRECT TO: " + redirectURL);				
 +					
 +				}
 +				
 +			}
 +	    
 +			catch (MOAIDException ex) {
 +				handleError(null, ex, req, resp, pendingRequestID);
 +				
 +			} catch (GeneralSecurityException e) {
 +				handleError(null, e, req, resp, pendingRequestID);
 +				
 +			} catch (PKIException e) {
 +				handleError(null, e, req, resp, pendingRequestID);
 +				
 +			} catch (TransformerException e) {
 +				handleError(null, e, req, resp, pendingRequestID);
 +				
 +		    } catch (Exception e) {
 +		    	Logger.error("AuthBlockValidation has an interal Error.", e);
 +		    }
 +		       
 +			
 +		    finally {
 +		    	ConfigurationDBUtils.closeSession();
 +		    }		
 +		
 +		
 +		
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyCertificateTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyCertificateTask.java new file mode 100644 index 000000000..32ea7fe3a --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyCertificateTask.java @@ -0,0 +1,164 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +import iaik.x509.X509Certificate;
 +
 +import java.io.IOException;
 +import java.util.Map;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.fileupload.FileUploadException;
 +import org.apache.commons.lang.StringEscapeUtils;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.id.util.ServletUtils;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.spss.util.CertificateUtils;
 +
 +/**
 + * Parses the certificate from {@code InfoBoxReadResponse} (via POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}), creates the auth block to be signed and returns a {@code CreateXMLSignatureRequest} for auth block signature.<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Retrieves the certificate via {@code InfoBoxReadResponse} from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
 + * <li>Verifies the certificate.</li>
 + * <li>Creates the auth block to be signed using information from the certificate (Organwalter, foreign citizen.</li>
 + * <li>Puts it in a {@code CreateXMLSignatureRequest}.</li>
 + * <li>Updates moa session.</li>
 + * <li>Responds with {@code CreateXMLSignatureRequest}.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_SESSIONID} containing a {@code InfoBoxReadResponse}.</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>{@code CreateXMLSignatureRequest} send as HttpServletResponse (for CCE).</li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyCertificateServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class VerifyCertificateTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws Exception {
 +
 +		// note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyCertificateServlet
 +
 +		Logger.debug("POST VerifyCertificateServlet");
 +		
 +		String pendingRequestID = null;
 +		
 +		Map<String, String> parameters;
 +	    try 
 +	    {
 +	      parameters = getParameters(req);
 +	    } catch (FileUploadException e) 
 +	    {
 +	      Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
 +	      throw new IOException(e.getMessage());
 +	     	}
 +	    String sessionID = req.getParameter(PARAM_SESSIONID);
 +	    
 +	    // escape parameter strings
 +		sessionID = StringEscapeUtils.escapeHtml(sessionID);
 +		
 +		pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
 +		
 +	    AuthenticationSession session = null;
 +	    try {
 +	       // check parameter
 +	       if (!ParamValidatorUtils.isValidSessionID(sessionID))
 +	          throw new WrongParametersException("VerifyCertificate", PARAM_SESSIONID, "auth.12");
 +	       
 +	    	session = AuthenticationServer.getSession(sessionID);
 +	    	
 +	        //change MOASessionID
 +	        sessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +	    	
 +    		X509Certificate cert = AuthenticationServer.getInstance().getCertificate(sessionID, parameters);
 +    		if (cert == null) {
 +    			Logger.error("Certificate could not be read.");
 +    			throw new AuthenticationException("auth.14", null);    		
 +    		}
 +    		
 +	    	boolean useMandate = session.getUseMandate();
 +	    	
 +	    	if (useMandate) {
 +
 +	    		// verify certificate for OrganWalter
 +	    		String createXMLSignatureRequestOrRedirect = AuthenticationServer.getInstance().verifyCertificate(session, cert);
 +	    		
 +		    	try {
 +					AuthenticationSessionStoreage.storeSession(session);
 +				} catch (MOADatabaseException e) {
 +					throw new MOAIDException("session store error", null);
 +				}
 +	    		
 +		    	// TODO[branch]: Mandate; respond with CXSR for authblock signature, dataURL "/VerifyAuthBlock"
 +		    	ServletUtils.writeCreateXMLSignatureRequestOrRedirect(resp, session, createXMLSignatureRequestOrRedirect, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyCertificate");
 +	    		
 +	    	}
 +	    	else {
 +	    			
 +		    	
 +	    		String countrycode = CertificateUtils.getIssuerCountry(cert);
 +	    		if (countrycode != null) {
 +	    			if (countrycode.compareToIgnoreCase("AT") == 0) {
 +	    				Logger.error("Certificate issuer country code is \"AT\". Login not support in foreign identities mode.");
 +	    				throw new AuthenticationException("auth.22", null);
 +	    			}
 +	    		}
 +	    		
 +	    		// Foreign Identities Modus	
 +		    	String createXMLSignatureRequest = AuthenticationServer.getInstance().createXMLSignatureRequestForeignID(session, cert);
 +		      // build dataurl (to the GetForeignIDSerlvet)
 +		    	String dataurl =
 +	             new DataURLBuilder().buildDataURL(
 +	               session.getAuthURL(),
 +	               REQ_GET_FOREIGN_ID,
 +	               session.getSessionID());
 +	       
 +		    	try {
 +					AuthenticationSessionStoreage.storeSession(session);
 +				} catch (MOADatabaseException e) {
 +					throw new MOAIDException("session store error", null);
 +				}
 +		    	
 +	    		// TODO[branch]: Foreign citizen; respond with CXSR for authblock signature, dataURL "/GetForeignID"
 +		    	ServletUtils.writeCreateXMLSignatureRequest(resp, createXMLSignatureRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "GetForeignID", dataurl);
 +		    	
 +		    	Logger.debug("Send CreateXMLSignatureRequest to BKU");
 +	    	}	    		    	 
 +	    }
 +	    catch (MOAIDException ex) {
 +	      handleError(null, ex, req, resp, pendingRequestID);
 +	      
 +	    } catch (Exception e) {
 +	    	Logger.error("CertificateValidation has an interal Error.", e);
 +	    }
 +	       
 +	    
 +	    finally {
 +	    	ConfigurationDBUtils.closeSession();
 +	    }
 +
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyIdentityLinkTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyIdentityLinkTask.java new file mode 100644 index 000000000..bf10b3681 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyIdentityLinkTask.java @@ -0,0 +1,102 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +
 +import java.io.IOException;
 +import java.util.Map;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.lang.StringEscapeUtils;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.ParseException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.logging.Logger;
 +
 +/**
 + * Verifies the identity link.<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Parses the identity link retrieved as {@code InfoBoxReadResponse} from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
 + * <li>Verifies the identity link.</li>
 + * <li>Updates moa session.</li>
 + * <li>Puts boolean flag {@code identityLinkAvailable} into {@code ExecutionContext}.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE} containing a {@code InfoBoxReadResponse}.</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Identity link put into moa session.</li>
 + * <li>Boolean flag {@code identityLinkAvailable} into {@code ExecutionContext}.</li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class VerifyIdentityLinkTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws Exception {
 +
 +		// note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet
 +
 +		Logger.debug("POST VerifyIdentityLink");
 +
 +		setNoCachingHeaders(resp);
 +		
 +		Map<String, String> parameters;
 +		String pendingRequestID = null;
 +
 +		try {
 +			parameters = getParameters(req);
 +		} catch (Exception e) {
 +			Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
 +			throw new IOException(e.getMessage());
 +		}
 +		
 +		try {
 +			
 +			String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
 +			// check parameter
 +			if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
 +				throw new WrongParametersException("VerifyIdentityLink", PARAM_SESSIONID, "auth.12");
 +			}
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
 +
 +			AuthenticationSession session = AuthenticationServer.getSession(sessionID);
 +
 +			boolean identityLinkAvailable = AuthenticationServer.getInstance().verifyIdentityLink(session, parameters) != null;
 +			AuthenticationSessionStoreage.storeSession(session);
 +
 +			executionContext.put("identityLinkAvailable", identityLinkAvailable);
 +
 +		} catch (ParseException ex) {
 +			handleError(null, ex, req, resp, pendingRequestID);
 +
 +		} catch (MOAIDException ex) {
 +			handleError(null, ex, req, resp, pendingRequestID);
 +
 +		} catch (Exception e) {
 +			Logger.error("IdentityLinkValidation has an interal Error.", e);
 +		}
 +
 +		finally {
 +			ConfigurationDBUtils.closeSession();
 +		}
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/registration/ModuleRegistration.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/registration/ModuleRegistration.java new file mode 100644 index 000000000..fa1878e74 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/registration/ModuleRegistration.java @@ -0,0 +1,149 @@ +package at.gv.egovernment.moa.id.auth.modules.registration; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; + +import javax.annotation.PostConstruct; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.core.io.Resource; + +import at.gv.egovernment.moa.id.auth.modules.AuthModule; +import at.gv.egovernment.moa.id.process.ProcessDefinitionParserException; +import at.gv.egovernment.moa.id.process.ProcessEngine; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; + +/** + * This class handles registering modules. The modules are detected either with + * the ServiceLoader mechanism or via Spring. All detected modules are ranked + * according to their priority. + */ +public class ModuleRegistration { + +	private static ModuleRegistration instance = new ModuleRegistration(); + +	private List<AuthModule> priorizedModules = new ArrayList<>(); + +	@Autowired +	private ApplicationContext ctx; + +	@Autowired +	private ProcessEngine processEngine; + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	public static ModuleRegistration getInstance() { +		return instance; +	} + +	private ModuleRegistration() { +	} + +	@PostConstruct +	private void init() { +		// load modules via the ServiceLoader +		initServiceLoaderModules(); + +		// load modules via Spring +		initSpringModules(); + +		// order modules according to their priority +		sortModules(); +	} +	 +	/** +	 * Discovers modules which use the ServiceLoader mechanism. +	 */ +	private void initServiceLoaderModules() { +		log.info("Looking for auth modules."); +		ServiceLoader<AuthModule> loader = ServiceLoader.load(AuthModule.class); +		Iterator<AuthModule> modules = loader.iterator(); +		while (modules.hasNext()) { +			AuthModule module = modules.next(); +			log.info("Detected module {}", module.getClass().getName()); +			registerModuleProcessDefinitions(module); +			priorizedModules.add(module); +		} +	} + +	/** +	 * Discovers modules which use Spring. +	 */ +	private void initSpringModules() { +		log.debug("Discovering Spring modules."); +		Map<String, AuthModule> modules = ctx.getBeansOfType(AuthModule.class); +		for (AuthModule module : modules.values()) { +			registerModuleProcessDefinitions(module); +			priorizedModules.add(module); +		} +	} + +	/** +	 * Registers the resource uris for the module. +	 *  +	 * @param module +	 *            the module. +	 */ +	private void registerModuleProcessDefinitions(AuthModule module) { +		for (String uri : module.getProcessDefinitions()) { +			Resource resource = ctx.getResource(uri); +			if (resource.isReadable()) { +				log.info("Registering process definition '{}'.", uri); +				try (InputStream processDefinitionInputStream = resource.getInputStream()) { +					processEngine.registerProcessDefinition(processDefinitionInputStream); +				} catch (IOException e) { +					log.error("Process definition '{}' could NOT be read.", uri, e); +				} catch (ProcessDefinitionParserException e) { +					log.error("Error while parsing process definition '{}'", uri, e); +				} +			} else { +				log.error("Process definition '{}' cannot be read.", uri); +			} +		} +	} + +	/** +	 * Order the modules in descending order according to their priority. +	 */ +	private void sortModules() { +		Collections.sort(priorizedModules, new Comparator<AuthModule>() { +			@Override +			public int compare(AuthModule thisAuthModule, AuthModule otherAuthModule) { +				int thisOrder = thisAuthModule.getPriority(); +				int otherOrder = otherAuthModule.getPriority(); +				return (thisOrder < otherOrder ? 1 : (thisOrder == otherOrder ? 0 : -1)); +			} +		}); +	} + +	/** +	 * Returns the process id of the first process, in the highest ranked +	 * module, which is able to work with the given execution context. +	 *  +	 * @param context +	 *            the {@link ExecutionContext}. +	 * @return the process id or {@code null} +	 */ +	public String selectProcess(ExecutionContext context) { +		for (AuthModule module : priorizedModules) { +			String id = module.selectProcess(context); +			if (StringUtils.isNotEmpty(id)) { +				log.debug("Process with id '{}' selected, for context '{}'.", id, context); +				return id; +			} +		} +		log.info("No process is able to handle context '{}'.", context); +		return null; +	} +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java index e5b2c598c..331a7653a 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java @@ -66,6 +66,11 @@ import org.apache.commons.fileupload.FileItemFactory;  import org.apache.commons.fileupload.FileUploadException;  import org.apache.commons.fileupload.disk.DiskFileItemFactory;  import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.NoUniqueBeanDefinitionException; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils;  import at.gv.egovernment.moa.id.advancedlogging.StatisticLogger;  import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; @@ -74,6 +79,7 @@ import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;  import at.gv.egovernment.moa.id.config.ConfigurationException;  import at.gv.egovernment.moa.id.entrypoints.DispatcherServlet; +import at.gv.egovernment.moa.id.process.ProcessEngine;  import at.gv.egovernment.moa.id.storage.DBExceptionStoreImpl;  import at.gv.egovernment.moa.id.storage.IExceptionStore;  import at.gv.egovernment.moa.id.util.ServletUtils; @@ -97,6 +103,11 @@ public class AuthServlet extends HttpServlet implements MOAIDAuthConstants {  	protected static final String ERROR_CODE_PARAM = "errorid"; +	/** +	 * The process engine. +	 */ +	private ProcessEngine processEngine; +	  	@Override  	protected void doGet(HttpServletRequest req, HttpServletResponse resp)  			throws ServletException, IOException { @@ -454,4 +465,31 @@ public class AuthServlet extends HttpServlet implements MOAIDAuthConstants {  	} + +	/** +	 * Returns the underlying process engine instance. +	 *  +	 * @return The process engine (never {@code null}). +	 * @throws NoSuchBeanDefinitionException +	 *             if no {@link ProcessEngine} bean was found. +	 * @throws NoUniqueBeanDefinitionException +	 *             if more than one {@link ProcessEngine} bean was found. +	 * @throws BeansException +	 *             if a problem getting the {@link ProcessEngine} bean occurred. +	 * @throws IllegalStateException +	 *             if the Spring WebApplicationContext was not found, which means that the servlet is used outside a +	 *             Spring web environment. +	 */ +	public synchronized ProcessEngine getProcessEngine() { +		if (processEngine == null) { +			WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); +			if (ctx == null) { +				throw new IllegalStateException( +						"Unable to find Spring WebApplicationContext. Servlet needs to be executed within a Spring web environment."); +			} +			processEngine = ctx.getBean(ProcessEngine.class); +		} +		return processEngine; +	} +	  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java index 99a7dce89..ad4776a45 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java @@ -23,55 +23,42 @@  package at.gv.egovernment.moa.id.auth.servlet;  import java.io.IOException; -import java.io.PrintWriter;  import java.util.List; -import javax.servlet.ServletConfig;  import javax.servlet.ServletException;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;  import org.apache.commons.lang.StringEscapeUtils; -import at.gv.egovernment.moa.id.auth.MOAIDAuthInitializer; -import at.gv.egovernment.moa.id.auth.builder.StartAuthenticationBuilder;  import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;  import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; +import at.gv.egovernment.moa.id.auth.modules.registration.ModuleRegistration;  import at.gv.egovernment.moa.id.auth.parser.StartAuthentificationParameterParser;  import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;  import at.gv.egovernment.moa.id.commons.db.dao.config.TemplateType;  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;  import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +  import at.gv.egovernment.moa.id.moduls.IRequest;  import at.gv.egovernment.moa.id.moduls.RequestStorage;  import at.gv.egovernment.moa.id.protocols.saml1.SAML1Protocol; + +import at.gv.egovernment.moa.id.process.ExecutionContextImpl; +import at.gv.egovernment.moa.id.process.ProcessInstance; +import at.gv.egovernment.moa.id.process.api.ExecutionContext;  import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; -import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;  import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.FileUtils;  import at.gv.egovernment.moa.util.MiscUtil; -import at.gv.egovernment.moa.util.StringUtils;  public class GenerateIFrameTemplateServlet extends AuthServlet {  	private static final long serialVersionUID = 1L; -	public void init(ServletConfig servletConfig) throws ServletException { -//		    try { -//		      super.init(servletConfig); -//		      MOAIDAuthInitializer.initialize(); -//		      Logger.debug("default platform file.encoding: " + System.getProperty("file.encoding")); -//		      Logger.info(MOAIDMessageProvider.getInstance().getMessage("init.00", null)); -//		    } -//		    catch (Exception ex) { -//		      Logger.fatal(MOAIDMessageProvider.getInstance().getMessage("init.02", null), ex); -//		      throw new ServletException(ex); -//		    } -	} -	    	protected void doGet(HttpServletRequest req, HttpServletResponse resp)  			throws ServletException, IOException {  		Logger.info("Receive " + GenerateIFrameTemplateServlet.class + " Request"); @@ -98,7 +85,7 @@ public class GenerateIFrameTemplateServlet extends AuthServlet {  	    	    moasession = AuthenticationSessionStoreage.getSession(moasessionid); -	    	    AuthenticationSessionStoreage.changeSessionID(moasession); +//	    	    AuthenticationSessionStoreage.changeSessionID(moasession);  			} catch (MOADatabaseException e) {  				Logger.info("MOASession with SessionID="+ moasessionid + " is not found in Database"); @@ -168,28 +155,37 @@ public class GenerateIFrameTemplateServlet extends AuthServlet {  		    											   moasession.getAction(),  		    											   req);  			} -			 -		    StartAuthenticationBuilder startauth = StartAuthenticationBuilder.getInstance();			 -		    String getIdentityLinkForm = startauth.build(moasession, req, resp); -			 -			//store MOASession + +			ExecutionContext ec = new ExecutionContextImpl(); +			// set execution context +			ec.put("ccc", moasession.getCcc()); +			ec.put("useMandate", moasession.getUseMandate()); +			ec.put("bkuURL", moasession.getBkuURL()); + +			// select and create process instance +			String processDefinitionId = ModuleRegistration.getInstance().selectProcess(ec); +			String processInstanceId = getProcessEngine().createProcessInstance(processDefinitionId, ec); + +			if (processDefinitionId == null) { +				Logger.warn("No suitable process found for SessionID " + moasession.getSessionID()); +				throw new MOAIDException("process.02", new Object[] { moasession.getSessionID() }); +			} + +			// keep process instance id in moa session +			moasession.setProcessInstanceId(processInstanceId); + +			// make sure moa session has been persisted before running the process  			try {  				AuthenticationSessionStoreage.storeSession(moasession); -				  			} catch (MOADatabaseException e) {  				Logger.error("Database Error! MOASession is not stored!"); -				throw new MOAIDException("init.04", new Object[] { -						moasession.getSessionID()}); +				throw new MOAIDException("init.04", new Object[] { moasession.getSessionID() });  			} -		     -		    if (!StringUtils.isEmpty(getIdentityLinkForm)) { -		    	resp.setContentType("text/html;charset=UTF-8"); -		    	PrintWriter out = new PrintWriter(resp.getOutputStream()); -		    	out.print(getIdentityLinkForm); -		    	out.flush(); -		    	Logger.debug("Finished GET "+GenerateIFrameTemplateServlet.class); -		    } -	    }  + +			// start process +			getProcessEngine().start(processInstanceId); + +		}  	    catch (WrongParametersException ex) {  	    	handleWrongParameters(ex, req, resp);  	    } @@ -206,4 +202,13 @@ public class GenerateIFrameTemplateServlet extends AuthServlet {  	    	ConfigurationDBUtils.closeSession();  	    }  	} + +	 +	 +	 +	 +	 +	 +	 +  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetForeignIDServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetForeignIDServlet.java index bbc704f22..41c2a9c6a 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetForeignIDServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetForeignIDServlet.java @@ -69,6 +69,7 @@ import at.gv.egovernment.moa.id.auth.data.IdentityLink;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
  import at.gv.egovernment.moa.id.auth.exception.ParseException;
  import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.internal.tasks.GetForeignIDTask;
  import at.gv.egovernment.moa.id.auth.parser.CreateXMLSignatureResponseParser;
  import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
  import at.gv.egovernment.moa.id.client.SZRGWClientException; @@ -85,6 +86,7 @@ import at.gv.util.xsd.srzgw.CreateIdentityLinkResponse;   * Servlet requested for getting the foreign eID
   * provided by the security layer implementation.
   * Utilizes the {@link AuthenticationServer}.
 + * @deprecated Use {@link GetForeignIDTask} instead.
   *
   */
  public class GetForeignIDServlet extends AuthServlet {
 @@ -134,6 +136,8 @@ public class GetForeignIDServlet extends AuthServlet {  		Logger.debug("POST GetForeignIDServlet");
 +		Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");
 +		
  		resp.setHeader(MOAIDAuthConstants.HEADER_EXPIRES,MOAIDAuthConstants.HEADER_VALUE_EXPIRES);
  		resp.setHeader(MOAIDAuthConstants.HEADER_PRAGMA,MOAIDAuthConstants.HEADER_VALUE_PRAGMA);
  		resp.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL,MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL);
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetMISSessionIDServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetMISSessionIDServlet.java index 9e2e845b5..043b660c1 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetMISSessionIDServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetMISSessionIDServlet.java @@ -67,6 +67,7 @@ import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;  import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; +import at.gv.egovernment.moa.id.auth.modules.internal.tasks.GetMISSessionIDTask;  import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;  import at.gv.egovernment.moa.id.config.ConnectionParameter;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; @@ -83,7 +84,7 @@ import at.gv.egovernment.moa.util.DOMUtils;  /**   * Servlet requested for getting the foreign eID provided by the security layer   * implementation. Utilizes the {@link AuthenticationServer}. - *  + * @deprecated Use {@link GetMISSessionIDTask} instead.   */  public class GetMISSessionIDServlet extends AuthServlet { @@ -136,6 +137,8 @@ public class GetMISSessionIDServlet extends AuthServlet {  		Logger.debug("POST GetMISSessionIDServlet"); +		Logger.warn(getClass().getName() + " is deprecated and should not be used any more."); +		  		resp.setHeader(MOAIDAuthConstants.HEADER_EXPIRES,  				MOAIDAuthConstants.HEADER_VALUE_EXPIRES);  		resp.setHeader(MOAIDAuthConstants.HEADER_PRAGMA, @@ -197,6 +200,7 @@ public class GetMISSessionIDServlet extends AuthServlet {  			// for now: list contains only one element  			MISMandate mandate = (MISMandate) list.get(0); +			// TODO[tlenz]: UTF-8 ?  			String sMandate = new String(mandate.getMandate());  			if (sMandate == null || sMandate.compareToIgnoreCase("") == 0) {  				Logger.error("Mandate is empty."); @@ -206,6 +210,7 @@ public class GetMISSessionIDServlet extends AuthServlet {  			//check if it is a parsable XML  			byte[] byteMandate = mandate.getMandate(); +			// TODO[tlenz]: UTF-8 ?  			String stringMandate = new String(byteMandate);  			DOMUtils.parseDocument(stringMandate, false,  					null, null).getDocumentElement(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/MonitoringServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/MonitoringServlet.java deleted file mode 100644 index e04f97e6e..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/MonitoringServlet.java +++ /dev/null @@ -1,126 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - *  - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - *  - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - *  - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - ******************************************************************************/ -package at.gv.egovernment.moa.id.auth.servlet; - -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.List; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; -import at.gv.egovernment.moa.id.monitoring.TestManager; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; - -public class MonitoringServlet extends AuthServlet { - -	private static final long serialVersionUID = 1L; -	private static final String REQUEST_ATTR_MODULE = "module"; -	 -	 -	  protected void doGet(HttpServletRequest req, HttpServletResponse resp) -			    throws ServletException, IOException { -		   -		  try { -			AuthConfigurationProvider config = AuthConfigurationProvider.getInstance(); -			 -			if (config.isMonitoringActive()) { -				Logger.debug("Monitoring Servlet received request"); - -				TestManager tests = TestManager.getInstance(); -				 -				String modulename = req.getParameter(REQUEST_ATTR_MODULE); -				if (MiscUtil.isEmpty(modulename)) { -				 -					List<String> error = tests.executeTests(); -					if (error != null && error.size() > 0) { -						createErrorMessage(req, resp, error); -						 -					} else { -						resp.setStatus(HttpServletResponse.SC_OK); -						resp.setContentType("text/html;charset=UTF-8"); -						resp.getWriter().write(getHtml(config.getMonitoringMessageSuccess())); -						Logger.info("Monitoring Servlet finished without errors"); -					} -					 -				} else { -					if (tests.existsModule(modulename)) { -						List<String> errors = tests.executeTest(modulename); -						if (errors != null && errors.size() > 0) { -							createErrorMessage(req, resp, errors); -							 -						} else { -							resp.setStatus(HttpServletResponse.SC_OK); -							resp.setContentType("text/html;charset=UTF-8"); -							resp.getWriter().write(getHtml(config.getMonitoringMessageSuccess())); -							Logger.info("Monitoring Servlet finished without errors"); -						} -						 -					} else { -						Logger.warn("NO Testmodule exists with modulename " + modulename); -						resp.setStatus(HttpServletResponse.SC_NOT_FOUND); -						resp.setContentType("text/html;charset=UTF-8"); -						PrintWriter out; -						try { -							out = new PrintWriter(resp.getOutputStream()); -							out.write("NO Testmodule exists with modulename " + modulename); -							out.flush(); -							     -						} catch (IOException e) { -							Logger.warn("Internal Monitoring Servlet Error. ", e); -						}  -					} -					 -				}	 -			} -			   -		} catch (ConfigurationException e) { -			createErrorMessage(req, resp, Arrays.asList(e.getMessage())); -		} -	  } -	   -	  private void createErrorMessage(HttpServletRequest req, HttpServletResponse resp, List<String> errorMessage) { -		  Logger.warn("Monitoring Servlet found some Error: " + errorMessage); -		  resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); -		  resp.setContentType("text/html;charset=UTF-8"); -		  PrintWriter out; -		  try { -			  out = new PrintWriter(resp.getOutputStream()); -			  for (String error : errorMessage) -				  out.write(error + "<br>"); -			  out.flush(); -			   -		  } catch (IOException e) { -			  Logger.warn("Internal Monitoring Servlet Error. ", e); -		  }  -	  } -	   -	private String getHtml(String text) { -		return "<html><head><title>Reponse</title></head><body>" + text +"</body></html>"; -	} -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorServlet.java index 8aef6af2d..7357818c8 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorServlet.java @@ -104,6 +104,7 @@ import javax.xml.ws.BindingProvider;  /**
   * Endpoint for receiving STORK response messages
 + * @deprecated Use {@link at.gv.egovernment.moa.id.auth.modules.stork.tasks.PepsConnectorTask} instead.
   */
  public class PEPSConnectorServlet extends AuthServlet {
 @@ -155,6 +156,8 @@ public class PEPSConnectorServlet extends AuthServlet {  		try {
 +			Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");
 +
  			Logger.info("PEPSConnector Servlet invoked, expecting C-PEPS message.");
  			Logger.debug("This ACS endpoint is: " + HTTPUtils.getBaseURL(request));
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorWithLocalSigningServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorWithLocalSigningServlet.java index 3bc79f8bd..337a9ed31 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorWithLocalSigningServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorWithLocalSigningServlet.java @@ -109,6 +109,7 @@ import eu.stork.peps.exceptions.STORKSAMLEngineException;  /**   * Endpoint for receiving STORK response messages + * @deprecated Use {@link at.gv.egovernment.moa.id.auth.modules.stork.tasks.PepsConnectorHandleResponseWithoutSignatureTask} instead.   */  public class PEPSConnectorWithLocalSigningServlet extends AuthServlet {  	private static final long serialVersionUID = 1L; @@ -131,6 +132,8 @@ public class PEPSConnectorWithLocalSigningServlet extends AuthServlet {  	 */  	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException   	{ +		Logger.warn(getClass().getName() + " is deprecated and should not be used any more."); +  		String moaSessionID1 = request.getParameter("moaSessionID");	  		String signResponse = request.getParameter("signresponse");	  		Logger.info("moaSessionID1:"+moaSessionID1); @@ -473,6 +476,7 @@ public class PEPSConnectorWithLocalSigningServlet extends AuthServlet {  						Logger.info("Found AttributeProviderPlugin attribute:"+ap.getAttributes());  						if(ap.getAttributes().equalsIgnoreCase("signedDoc"))  						{ +							// FIXME[tlenz]: A servlet's class field is not thread safe.  							oasisDssWebFormURL = ap.getUrl();  							found = true;  							Logger.info("Loaded signedDoc attribute provider url from config:"+oasisDssWebFormURL); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java new file mode 100644 index 000000000..a99b7aeef --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java @@ -0,0 +1,83 @@ +package at.gv.egovernment.moa.id.auth.servlet;
 +
 +import java.io.IOException;
 +
 +import javax.servlet.ServletException;
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.lang.StringEscapeUtils;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +
 +/**
 + * Servlet that resumes a suspended process (in case of asynchronous tasks).
 + * 
 + * @author tknall
 + * 
 + */
 +public class ProcessEngineSignalServlet extends AuthServlet {
 +
 +	private static final long serialVersionUID = 1L;
 +
 +	/**
 +	 * Sets response headers that prevent caching (code taken from {@link AuthServlet}).
 +	 * 
 +	 * @param resp
 +	 *            The HttpServletResponse.
 +	 */
 +	private void setNoCachingHeaders(HttpServletResponse resp) {
 +		resp.setHeader(HEADER_EXPIRES, HEADER_VALUE_EXPIRES);
 +		resp.setHeader(HEADER_PRAGMA, HEADER_VALUE_PRAGMA);
 +		resp.setHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL);
 +		resp.addHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL_IE);
 +	}
 +
 +	/**
 +	 * Processes a GET request, delegating the call to {@link #doPost(HttpServletRequest, HttpServletResponse)}.
 +	 */
 +	@Override
 +	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 +		this.doPost(req, resp);
 +	}
 +
 +	/**
 +	 * Resumes the current process instance that has been suspended due to an asynchronous task. The process instance is
 +	 * retrieved from the MOA session referred to by the request parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}.
 +	 */
 +	@Override
 +	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 +		String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
 +
 +		setNoCachingHeaders(resp);
 +		try {
 +
 +			// check parameter
 +			if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
 +				throw new WrongParametersException("ProcessEngineSignal", PARAM_SESSIONID, "auth.12");
 +			}
 +
 +			// retrieve moa session
 +			AuthenticationSession session = AuthenticationServer.getSession(sessionID);
 +
 +			// process instance is mandatory
 +			if (session.getProcessInstanceId() == null) {
 +				throw new IllegalStateException("MOA session does not provide process instance id.");
 +			}
 +
 +			// wake up next task
 +			getProcessEngine().signal(session.getProcessInstanceId());
 +
 +		} catch (Exception ex) {
 +			handleError(null, ex, req, resp, null);
 +		} finally {
 +			MOASessionDBUtils.closeSession();
 +		}
 +
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java index e7fa9cbd7..a8fe71485 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java @@ -71,6 +71,7 @@ import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;  import at.gv.egovernment.moa.id.auth.exception.MISSimpleClientException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; +import at.gv.egovernment.moa.id.auth.modules.internal.tasks.VerifyAuthenticationBlockTask;  import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;  import at.gv.egovernment.moa.id.config.ConnectionParameter; @@ -92,6 +93,7 @@ import at.gv.egovernment.moa.util.DOMUtils;   *    * @author Paul Ivancsics   * @version $Id$ + * @deprecated Use {@link VerifyAuthenticationBlockTask} instead.   */  public class VerifyAuthenticationBlockServlet extends AuthServlet { @@ -153,6 +155,8 @@ public class VerifyAuthenticationBlockServlet extends AuthServlet {  		Logger.debug("POST VerifyAuthenticationBlock"); +		Logger.warn(getClass().getName() + " is deprecated and should not be used any more."); +  		resp.setHeader(MOAIDAuthConstants.HEADER_EXPIRES,MOAIDAuthConstants.HEADER_VALUE_EXPIRES);  		resp.setHeader(MOAIDAuthConstants.HEADER_PRAGMA,MOAIDAuthConstants.HEADER_VALUE_PRAGMA);  		resp.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL,MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyCertificateServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyCertificateServlet.java index a3397f561..2aa717a65 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyCertificateServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyCertificateServlet.java @@ -65,6 +65,7 @@ import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;  import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
  import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.internal.tasks.VerifyCertificateTask;
  import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
  import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 @@ -77,6 +78,7 @@ import at.gv.egovernment.moa.spss.util.CertificateUtils;   * Servlet requested for getting the foreign eID
   * provided by the security layer implementation.
   * Utilizes the {@link AuthenticationServer}.
 + * @deprecated Use {@link VerifyCertificateTask} instead.
   *
   */
  public class VerifyCertificateServlet extends AuthServlet {
 @@ -126,6 +128,8 @@ public class VerifyCertificateServlet extends AuthServlet {  		Logger.debug("POST VerifyCertificateServlet");
 +		Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");
 +
  		resp.setHeader(MOAIDAuthConstants.HEADER_EXPIRES,MOAIDAuthConstants.HEADER_VALUE_EXPIRES);
  		resp.setHeader(MOAIDAuthConstants.HEADER_PRAGMA,MOAIDAuthConstants.HEADER_VALUE_PRAGMA);
  		resp.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL,MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL);
 @@ -180,7 +184,8 @@ public class VerifyCertificateServlet extends AuthServlet {  					throw new MOAIDException("session store error", null);
  				}
 -	    		ServletUtils.writeCreateXMLSignatureRequestOrRedirect(resp, session, createXMLSignatureRequestOrRedirect, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyCertificate");
 +		    	ServletUtils.writeCreateXMLSignatureRequestOrRedirect(resp, session, createXMLSignatureRequestOrRedirect, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyCertificate");
 +	    		
  	    	}
  	    	else {
 @@ -208,8 +213,7 @@ public class VerifyCertificateServlet extends AuthServlet {  					throw new MOAIDException("session store error", null);
  				}
 -		    	ServletUtils.writeCreateXMLSignatureRequest(resp, session, createXMLSignatureRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "GetForeignID", dataurl);
 -		    	
 +		    	ServletUtils.writeCreateXMLSignatureRequest(resp, createXMLSignatureRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "GetForeignID", dataurl);
  		    	Logger.debug("Send CreateXMLSignatureRequest to BKU");
  	    	}	    		    	 
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java index 3b503f07b..b8e57ed43 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java @@ -53,7 +53,6 @@ import javax.servlet.ServletException;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; -import org.apache.commons.fileupload.FileUploadException;  import org.apache.commons.lang.StringEscapeUtils;  import at.gv.egovernment.moa.id.auth.AuthenticationServer; @@ -65,8 +64,8 @@ import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.auth.exception.ParseException;  import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; +import at.gv.egovernment.moa.id.auth.modules.internal.tasks.VerifyIdentityLinkTask;  import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils; -import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils;  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;  import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; @@ -82,6 +81,7 @@ import at.gv.egovernment.moa.logging.Logger;   *   * @author Paul Ivancsics   * @version $Id$ + * @deprecated Use {@link VerifyIdentityLinkTask} instead.   */  public class VerifyIdentityLinkServlet extends AuthServlet { @@ -135,6 +135,8 @@ public class VerifyIdentityLinkServlet extends AuthServlet {      throws ServletException, IOException {  		Logger.debug("POST VerifyIdentityLink"); +	 +	Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");      Map<String, String> parameters;      String pendingRequestID = null; @@ -201,7 +203,7 @@ public class VerifyIdentityLinkServlet extends AuthServlet {                    session.getSessionID()); -          ServletUtils.writeCreateXMLSignatureRequest(resp, session, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl); +          ServletUtils.writeCreateXMLSignatureRequest(resp, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);      	    } @@ -231,7 +233,7 @@ public class VerifyIdentityLinkServlet extends AuthServlet {       		  //ServletUtils.writeCreateXMLSignatureRequestURLEncoded(resp, session, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);       		  Logger.debug("ContentType set to: text/xml;charset=UTF-8 (ServletUtils)"); -     		  ServletUtils.writeCreateXMLSignatureRequest(resp, session, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl); +     		  ServletUtils.writeCreateXMLSignatureRequest(resp, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);      		}	      		else { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java index b02c0946c..593b72658 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java @@ -40,7 +40,7 @@ public class AuthConfigLoader implements Runnable {  			try {  				Thread.sleep(INTERVAL * 1000); -				Logger.info("check for new config."); +				Logger.trace("check for new config.");  				MOAIDConfiguration moaidconfig = ConfigurationDBRead.getMOAIDConfiguration();  				if (moaidconfig != null) {									 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java index 80364a2ab..c746c0888 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java @@ -111,10 +111,10 @@ import at.gv.egovernment.moa.id.config.auth.data.ProtocolAllowed;  import at.gv.egovernment.moa.id.config.legacy.BuildFromLegacyConfig;  import at.gv.egovernment.moa.id.config.stork.STORKConfig;  import at.gv.egovernment.moa.id.data.IssuerAndSerial; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStore;  import at.gv.egovernment.moa.id.protocols.pvp2x.config.MOADefaultBootstrap;  import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.MiscUtil; -import at.gv.util.config.EgovUtilConfiguration;  import at.gv.util.config.EgovUtilPropertiesConfiguration;  /** @@ -345,6 +345,7 @@ public class AuthConfigurationProvider extends ConfigurationProvider {  				config.addAnnotatedClass(OldSSOSessionIDStore.class);  				config.addAnnotatedClass(ExceptionStore.class);  				config.addAnnotatedClass(InterfederationSessionStore.class); +				config.addAnnotatedClass(ProcessInstanceStore.class);  				config.addProperties(moaSessionProp);  				MOASessionDBUtils.initHibernate(config, moaSessionProp); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java index 03cb6c1c4..e3b7524ae 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java @@ -23,7 +23,6 @@  package at.gv.egovernment.moa.id.entrypoints;  import java.io.IOException; -  import java.util.Iterator;  import javax.servlet.ServletConfig; @@ -97,10 +96,13 @@ public class DispatcherServlet extends AuthServlet{  		boolean useSSOOA = false;  		String protocolRequestID = null; -		  		try {  			Logger.info("REQUEST: " + req.getRequestURI());  			Logger.info("QUERY  : " + req.getQueryString()); +			 + +// *** start of error handling *** +			  			String errorid = req.getParameter(ERROR_CODE_PARAM);  			if (errorid != null) { @@ -117,7 +119,7 @@ public class DispatcherServlet extends AuthServlet{  					pendingRequestID = (String) idObject;   				} -				if (throwable != null) {					 +				if (throwable != null) {  						IRequest errorRequest = null;  						if (pendingRequestID != null) { @@ -173,6 +175,11 @@ public class DispatcherServlet extends AuthServlet{  				return;  			} +// *** end of error handling *** + +			 +// *** start of protocol specific stuff *** +  			Object moduleObject = req.getParameter(PARAM_TARGET_MODULE);  			String module = null;  			if (moduleObject != null && (moduleObject instanceof String)) { @@ -272,7 +279,7 @@ public class DispatcherServlet extends AuthServlet{  							//create interfederated MOASession  							String sessionID =   									AuthenticationSessionStoreage.createInterfederatedSession(protocolRequest, true, ssoId); -							req.getParameterMap().put(PARAM_SESSIONID, sessionID); +							req.getParameterMap().put(PARAM_SESSIONID, new String[]{ sessionID });  							Logger.info("PreProcessing of SSO interfederation response complete. "); @@ -357,7 +364,11 @@ public class DispatcherServlet extends AuthServlet{  					}  				} -								 +						 +// *** end of protocol specific stuff *** +				 +// *** start handling authentication *** +				  				AuthenticationManager authmanager = AuthenticationManager.getInstance();									  				String moasessionID = null; @@ -473,7 +484,11 @@ public class DispatcherServlet extends AuthServlet{  					//build authenticationdata from session information and OA configuration  					authData = AuthenticationDataBuilder.buildAuthenticationData(protocolRequest, moasession);					  				} -										 + +// *** end handling authentication *** + +// *** start finalizing authentication (SSO, final redirects, statistic logging etc) *** +				  				SLOInformationInterface assertionID = moduleAction.processRequest(protocolRequest, req, resp, authData);  				RequestStorage.removePendingRequest(protocolRequestID); @@ -506,6 +521,8 @@ public class DispatcherServlet extends AuthServlet{  				} +// *** end finalizing authentication *** +  			} catch (Throwable e) {  				Logger.warn("An authentication error occured: ", e);;  				// Try handle module specific, if not possible rethrow diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java index 333bd35f1..49f3df25c 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java @@ -59,17 +59,17 @@ import org.opensaml.ws.message.encoder.MessageEncodingException;  import org.opensaml.ws.soap.common.SOAPException;  import org.opensaml.xml.XMLObject;  import org.opensaml.xml.security.SecurityException; +import org.springframework.beans.factory.annotation.Autowired;  import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;  import at.gv.egovernment.moa.id.auth.builder.LoginFormBuilder;  import at.gv.egovernment.moa.id.auth.builder.SendAssertionFormBuilder; -import at.gv.egovernment.moa.id.auth.builder.StartAuthenticationBuilder;  import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;  import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;  import at.gv.egovernment.moa.id.auth.exception.BuildException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.registration.ModuleRegistration;  import at.gv.egovernment.moa.id.auth.parser.StartAuthentificationParameterParser; -import at.gv.egovernment.moa.id.auth.servlet.AuthServlet;  import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore;  import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore;  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; @@ -78,6 +78,11 @@ import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;  import at.gv.egovernment.moa.id.data.SLOInformationContainer;  import at.gv.egovernment.moa.id.data.SLOInformationImpl;  import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; + +import at.gv.egovernment.moa.id.process.ExecutionContextImpl; +import at.gv.egovernment.moa.id.process.ProcessEngine; +import at.gv.egovernment.moa.id.process.ProcessExecutionException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext;  import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding; @@ -97,25 +102,24 @@ import at.gv.egovernment.moa.id.util.ParamValidatorUtils;  import at.gv.egovernment.moa.id.util.Random;  import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.MiscUtil; -import at.gv.egovernment.moa.util.StringUtils; -public class AuthenticationManager extends AuthServlet { +public class AuthenticationManager implements MOAIDAuthConstants { -	private static AuthenticationManager instance = null; -	 -	private static final long serialVersionUID = 1L; +	private static final AuthenticationManager INSTANCE = new AuthenticationManager();  	public static final String MOA_SESSION = "MoaAuthenticationSession";  	public static final String MOA_AUTHENTICATED = "MoaAuthenticated";  	public static final int SLOTIMEOUT = 30 * 1000; //30 sec +	@Autowired +	private ProcessEngine processEngine; +	 +	private AuthenticationManager() { +	} +	  	public static AuthenticationManager getInstance() { -		if (instance == null) { -			instance = new AuthenticationManager(); -		} -		 -		return instance; +		return INSTANCE;  	}  	/** @@ -323,7 +327,7 @@ public class AuthenticationManager extends AuthServlet {  		try {  			authSession = AuthenticationSessionStoreage  					.getSession(moaSessionID); -		 +  			if(authSession == null) {  				Logger.info("NO MOA Authentication data for ID " + moaSessionID);  				return; @@ -548,7 +552,10 @@ public class AuthenticationManager extends AuthServlet {  			throws ServletException, IOException, MOAIDException {  		Logger.debug("Starting authentication on this IDP ..."); -		setNoCachingHeadersInHttpRespone(request, response); +		response.setHeader(MOAIDAuthConstants.HEADER_EXPIRES, MOAIDAuthConstants.HEADER_VALUE_EXPIRES); +		response.setHeader(MOAIDAuthConstants.HEADER_PRAGMA, MOAIDAuthConstants.HEADER_VALUE_PRAGMA); +		response.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL); +		response.addHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL_IE);  		List<String> legacyallowed_prot = AuthConfigurationProvider.getInstance().getLegacyAllowedProtocols(); @@ -569,79 +576,95 @@ public class AuthenticationManager extends AuthServlet {  			throw new MOAIDException("init.04", new Object[] {});  		} -		 -		if (legacyallowed && legacyparamavail) { -			 -			//parse request parameter into MOASession			 -			StartAuthentificationParameterParser.parse(request, response, moasession, target); -							 -		    Logger.info("Start Authentication Module: " + moasession.getModul()  -		    		+ " Action: " + moasession.getAction()); -					     -		    StartAuthenticationBuilder startauth = StartAuthenticationBuilder.getInstance(); -			 -		    String getIdentityLinkForm = startauth.build(moasession, request, response); -			 -			//store MOASession -			try { -				AuthenticationSessionStoreage.storeSession(moasession, target.getRequestID());				 -			} catch (MOADatabaseException e) { -				Logger.error("Database Error! MOASession is not stored!"); -				throw new MOAIDException("init.04", new Object[] { -						moasession.getSessionID()}); -			} -		     -		    if (!StringUtils.isEmpty(getIdentityLinkForm)) { -		    	response.setContentType("text/html;charset=UTF-8"); -		    	PrintWriter out = new PrintWriter(response.getOutputStream()); -		    	out.print(getIdentityLinkForm); -		    	out.flush(); -		    	Logger.debug("Finished GET StartAuthentication"); -		    } -			 -		} else { -			//load Parameters from OnlineApplicationConfiguration -			OAAuthParameter oaParam = AuthConfigurationProvider.getInstance() -					.getOnlineApplicationParameter(target.getOAURL()); +		try { -			if (oaParam == null) { -				throw new AuthenticationException("auth.00", new Object[] { target.getOAURL() }); -			} -							 -			else { +			if (legacyallowed && legacyparamavail) { -				//check if an MOASession exists and if not create an new MOASession -				//moasession = getORCreateMOASession(request); +				//parse request parameter into MOASession			 +				StartAuthentificationParameterParser.parse(request, response, moasession, target); +								 +			    Logger.info("Start Authentication Module: " + moasession.getModul()  +			    		+ " Action: " + moasession.getAction()); +	 +				// create execution context +				ExecutionContext executionContext = new ExecutionContextImpl(); +				executionContext.put("ccc", moasession.getCcc()); +				executionContext.put("useMandate", moasession.getUseMandate()); +				executionContext.put("bkuURL", moasession.getBkuURL()); +				executionContext.put(PARAM_SESSIONID, moasession.getSessionID()); -				//set OnlineApplication configuration in Session -				moasession.setOAURLRequested(target.getOAURL()); -				moasession.setAction(target.requestedAction()); -				moasession.setModul(target.requestedModule()); -			} -						 -			//Build authentication form -			 -			 -			String publicURLPreFix = AuthConfigurationProvider.getInstance().getPublicURLPrefix(); -			String loginForm = LoginFormBuilder.buildLoginForm(target.requestedModule(),  -					target.requestedAction(), oaParam, publicURLPreFix, moasession.getSessionID()); -			 -			//store MOASession -			try { -				AuthenticationSessionStoreage.storeSession(moasession, target.getRequestID());				 -			} catch (MOADatabaseException e) { -				Logger.error("Database Error! MOASession is not stored!"); -				throw new MOAIDException("init.04", new Object[] { -						moasession.getSessionID()}); +				// create process instance +				String processDefinitionId = ModuleRegistration.getInstance().selectProcess(executionContext); + +				if (processDefinitionId == null) { +					Logger.warn("No suitable process found for SessionID " + moasession.getSessionID() ); +					throw new MOAIDException("process.02",new Object[] { +							moasession.getSessionID()}); +				} + +				String processInstanceId = processEngine.createProcessInstance(processDefinitionId, executionContext); + +				// keep process instance id in moa session +				moasession.setProcessInstanceId(processInstanceId); + +				// make sure moa session has been persisted before running the process +				try { +					AuthenticationSessionStoreage.storeSession(moasession); +				} catch (MOADatabaseException e) { +					Logger.error("Database Error! MOASession is not stored!"); +					throw new MOAIDException("init.04", new Object[] { +							moasession.getSessionID()}); +				} + +		    	// start process +				processEngine.start(processInstanceId); +			     +			} else { +				//load Parameters from OnlineApplicationConfiguration +				OAAuthParameter oaParam = AuthConfigurationProvider.getInstance() +						.getOnlineApplicationParameter(target.getOAURL()); +				 +				if (oaParam == null) { +					throw new AuthenticationException("auth.00", new Object[] { target.getOAURL() }); +				} +								 +				else { +					 +					//check if an MOASession exists and if not create an new MOASession +					//moasession = getORCreateMOASession(request); +	 +					//set OnlineApplication configuration in Session +					moasession.setOAURLRequested(target.getOAURL()); +					moasession.setAction(target.requestedAction()); +					moasession.setModul(target.requestedModule()); +				} +							 +				//Build authentication form +				 +				 +				String publicURLPreFix = AuthConfigurationProvider.getInstance().getPublicURLPrefix(); +				String loginForm = LoginFormBuilder.buildLoginForm(target.requestedModule(),  +						target.requestedAction(), oaParam, publicURLPreFix, moasession.getSessionID()); +				 +				//store MOASession +				try { +					AuthenticationSessionStoreage.storeSession(moasession, target.getRequestID());				 +				} catch (MOADatabaseException e) { +					Logger.error("Database Error! MOASession is not stored!"); +					throw new MOAIDException("init.04", new Object[] { +							moasession.getSessionID()}); +				} +				 +				//set MOAIDSession +				//request.getSession().setAttribute(MOA_SESSION, moasession.getSessionID()); +				 +				response.setContentType("text/html;charset=UTF-8"); +				PrintWriter out = new PrintWriter(response.getOutputStream());  +				out.print(loginForm); +				out.flush();   			} -			 -			//set MOAIDSession -			//request.getSession().setAttribute(MOA_SESSION, moasession.getSessionID()); -			 -			response.setContentType("text/html;charset=UTF-8"); -			PrintWriter out = new PrintWriter(response.getOutputStream());  -			out.print(loginForm); -			out.flush();  +		} catch (ProcessExecutionException e) { +			throw new MOAIDException("process.01", new Object[] { moasession.getProcessInstanceId(), moasession }, e);  		}  	}  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/DatabaseTestModule.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/DatabaseTestModule.java deleted file mode 100644 index a08ef5f0c..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/DatabaseTestModule.java +++ /dev/null @@ -1,142 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -package at.gv.egovernment.moa.id.monitoring; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.hibernate.Query; -import org.hibernate.Session; - -import at.gv.egovernment.moa.id.commons.db.ConfigurationDBRead; -import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils; -import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; -import at.gv.egovernment.moa.id.commons.db.StatisticLogDBUtils; -import at.gv.egovernment.moa.id.commons.db.dao.config.MOAIDConfiguration; -import at.gv.egovernment.moa.id.commons.db.dao.session.AssertionStore; -import at.gv.egovernment.moa.id.commons.db.dao.statistic.StatisticLog; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; - -public class DatabaseTestModule implements TestModuleInterface{ - -	public List<String> performTests() throws Exception { -		Logger.trace("Start MOA-ID Database Test."); -		 -		List<String> errors = new ArrayList<String>(); -		 -		AuthConfigurationProvider config = AuthConfigurationProvider.getInstance(); -		 -		String error = testMOAConfigurationDatabase(); -		if (MiscUtil.isNotEmpty(error)) -			errors.add(error); -		 -		error = testMOASessionDatabase(); -		if (MiscUtil.isNotEmpty(error)) -			errors.add(error); -		 -		if (config.isAdvancedLoggingActive()) { -			error = testMOAAdvancedLoggingDatabase(); -			if (MiscUtil.isNotEmpty(error)) -				errors.add(error); -		} -		 -		return errors; -	} - -	 -	private String testMOASessionDatabase() throws Exception{ -		Logger.trace("Start Test: MOASessionDatabase"); -		 -		Date expioredate = new Date(new Date().getTime() - 120); -  -		try { -			List<AssertionStore> results; -			Session session = MOASessionDBUtils.getCurrentSession(); -			 -			synchronized (session) {			 -				session.beginTransaction(); -				Query query = session.getNamedQuery("getAssertionWithTimeOut"); -				query.setTimestamp("timeout", expioredate);		 -				results = query.list(); -				session.getTransaction().commit(); -			} -			 -			Logger.trace("Finish Test: MOASessionDatabase"); -			return null; -			 -		} catch (Throwable e) { -			Logger.warn("Failed Test: MOASessionDatabase", e); -			return "MOASessionDatabase: " + e.getMessage(); -		} -	} -	 -	private String testMOAConfigurationDatabase() throws Exception{ -		 -		MOAIDConfiguration moaidconfig = ConfigurationDBRead.getMOAIDConfiguration();	 -		ConfigurationDBUtils.closeSession(); -		 -		if (moaidconfig == null) -			return ("MOA-ID 2.x configuration can not be loaded from Database."); -		 -		return null; -	} -	 -	private String testMOAAdvancedLoggingDatabase() { -		 -		Date expioredate = new Date(new Date().getTime() - 120); -		try { -			Session session = StatisticLogDBUtils.getCurrentSession(); -		 -			List<StatisticLog> results; -		 -			synchronized (session) {			 -				session.beginTransaction(); -				Query query = session.getNamedQuery("getAllEntriesNotBeforeTimeStamp"); -				query.setTimestamp("timeout", expioredate);		 -				results = query.list(); -				session.getTransaction().commit(); -			} -		 -			Logger.trace("Finish Test: AdvancedLoggingDataBase"); -			return null; -			 -		} catch (Throwable e) { -			Logger.warn("Failed Test: AdvancedLoggingDataBase", e); -			return "AdvancedLoggingDataBase: " + e.getMessage(); -		} -	} - - -	public String getName() { -		return "DatabaseTest"; -	} - - -	public void initializeTest(long delayParam, String url) throws Exception { -		// TODO Auto-generated method stub -		 -	} -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/IdentityLinkTestModule.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/IdentityLinkTestModule.java deleted file mode 100644 index b5220914c..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/IdentityLinkTestModule.java +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -package at.gv.egovernment.moa.id.monitoring; - -import java.io.InputStream; -import java.net.URL; -import java.util.List; - -import org.w3c.dom.Element; - -import at.gv.egovernment.moa.id.auth.builder.VerifyXMLSignatureRequestBuilder; -import at.gv.egovernment.moa.id.auth.data.IdentityLink; -import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse; -import at.gv.egovernment.moa.id.auth.exception.ValidateException; -import at.gv.egovernment.moa.id.auth.invoke.SignatureVerificationInvoker; -import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser; -import at.gv.egovernment.moa.id.auth.parser.VerifyXMLSignatureResponseParser; -import at.gv.egovernment.moa.id.auth.validator.IdentityLinkValidator; -import at.gv.egovernment.moa.id.auth.validator.VerifyXMLSignatureResponseValidator; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; -import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; -import at.gv.egovernment.moa.id.config.auth.data.DynamicOAAuthParameters; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; - -public class IdentityLinkTestModule implements TestModuleInterface { - -	private static IdentityLink identityLink = null; -	 -	public void initializeTest(long delayParam, String url) throws Exception{ -		 -		if (MiscUtil.isNotEmpty(url)) { -			 -		  	URL keystoreURL = new URL(url);					 -			InputStream idlstream = keystoreURL.openStream(); -			identityLink = new IdentityLinkAssertionParser(idlstream).parseIdentityLink(); -		} -		 -	} -	 -	public List<String> performTests()  throws Exception{ -		Logger.trace("Start MOA-ID IdentityLink Test"); -		 -		AuthConfigurationProvider config = AuthConfigurationProvider.getInstance(); -		 -		IdentityLinkValidator.getInstance().validate(identityLink); -		// builds a <VerifyXMLSignatureRequest> for a call of MOA-SP -		Element domVerifyXMLSignatureRequest = new VerifyXMLSignatureRequestBuilder() -				.build(identityLink, config -						.getMoaSpIdentityLinkTrustProfileID()); - -		// invokes the call -		Element domVerifyXMLSignatureResponse = new SignatureVerificationInvoker() -				.verifyXMLSignature(domVerifyXMLSignatureRequest); -		// parses the <VerifyXMLSignatureResponse> -		try { -			VerifyXMLSignatureResponse verifyXMLSignatureResponse = new VerifyXMLSignatureResponseParser( -					domVerifyXMLSignatureResponse).parseData(); -		 -			DynamicOAAuthParameters oaParam = new DynamicOAAuthParameters(); -			oaParam.setBusinessService(true); -			 -			VerifyXMLSignatureResponseValidator.getInstance().validate( -					verifyXMLSignatureResponse, -					config.getIdentityLinkX509SubjectNames(), -					VerifyXMLSignatureResponseValidator.CHECK_IDENTITY_LINK, -					oaParam); -			 -		} catch (ValidateException e) { -			//check if default Monitoring IDL is used then error is ignored -			if ("validator.07".equals(e.getMessageId())  -					&& e.getMessage().contains("Das Zertifikat der Personenbindung ist")) -				return null; -			 -			else -				throw e; -			 -		} -		 -		Logger.trace("Finished MOA-ID IdentityLink Test without errors"); -		 -		return null; -	} - -	public String getName() { -		return "IdentityLinkTest"; -	} - -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestManager.java deleted file mode 100644 index 84581abe8..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestManager.java +++ /dev/null @@ -1,111 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -package at.gv.egovernment.moa.id.monitoring; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.FileUtils; - -public class TestManager { - -	private static TestManager instance; -	 -	private Map<String, TestModuleInterface> tests = new HashMap<String, TestModuleInterface>(); -	 -	public static TestManager getInstance() throws ConfigurationException { -		if (instance == null) -			instance = new TestManager(); -		 -		return instance; -	} -	 -	private TestManager() throws ConfigurationException { -		 -		AuthConfigurationProvider config = AuthConfigurationProvider.getInstance(); -		 -		//add Database test -		DatabaseTestModule test1 = new DatabaseTestModule(); -		tests.put(test1.getName(), test1); -		 -		//add IdentityLink verification test -		IdentityLinkTestModule test2 = new IdentityLinkTestModule(); -		String idlurl = FileUtils.makeAbsoluteURL(config.getMonitoringTestIdentityLinkURL(), config.getRootConfigFileDir()); -		try { -			test2.initializeTest(0, idlurl); -			tests.put(test2.getName(), test2);; -			 -		} catch (Exception e) { -			Logger.warn("MOA-ID IdentityLink Test can not performed without IdentityLink. Insert IdentityLink file to MOA-ID configuration", e); -		} -	} -	 -	public List<String> executeTests() { -		Logger.debug("Start MOA-ID-Auth testing"); - -		 -		List<String> errors; -		 -		for (TestModuleInterface test : tests.values()) { -			try { -				errors = test.performTests(); -				if (errors != null && errors.size() > 0) -					return errors; -				 -			} catch (Exception e) { -				Logger.warn("General Testing Eception during Test " + test.getClass() + ": ", e); -				return Arrays.asList(e.getMessage()); -			} -		} -		 -		return null;	 -	} -	 -	public List<String> executeTest(String testname) { -		 -		TestModuleInterface test = tests.get(testname); -		 -		if (test != null) { -			try { -				return test.performTests(); -				 -			} catch (Exception e) { -				Logger.warn("General Testing Eception during Test " + test.getName() + ": ", e); -				return Arrays.asList(e.getMessage()); -			} -			 -		} else { -			Logger.info("TestModule with Name " + testname + " is not implemented"); -			return null; -		} -	} -	 -	public boolean existsModule(String modulename) { -		return tests.containsKey(modulename); -	} -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestModuleInterface.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestModuleInterface.java deleted file mode 100644 index 4e26b1ce8..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestModuleInterface.java +++ /dev/null @@ -1,34 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - *******************************************************************************/ -package at.gv.egovernment.moa.id.monitoring; - -import java.util.List; - -public interface TestModuleInterface { - -	public List<String> performTests() throws Exception; -	 -	public void initializeTest(long delayParam, String url) throws Exception;  -	 -	public String getName(); -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExecutionContextImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExecutionContextImpl.java new file mode 100644 index 000000000..080990f71 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExecutionContextImpl.java @@ -0,0 +1,79 @@ +package at.gv.egovernment.moa.id.process; + +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; + +/** + * ExecutionContext implementation, related to a certain process instance. + *  + * @author tknall + *  + */ +public class ExecutionContextImpl implements ExecutionContext { + +	private static final long serialVersionUID = 1L; + +	private Map<String, Serializable> ctxData = Collections.synchronizedMap(new HashMap<String, Serializable>()); + +	private String processInstanceId; + +	/** +	 * Creates a new instance. +	 */ +	public ExecutionContextImpl() { +	} + +	/** +	 * Creates a new instance and associated it with a certain process instance. +	 */ +	public ExecutionContextImpl(String processInstanceId) { +		this.processInstanceId = processInstanceId; +	} + +	@Override +	public void setProcessInstanceId(String processInstanceId) { +		this.processInstanceId = processInstanceId; +	} + +	@Override +	public String getProcessInstanceId() { +		return processInstanceId; +	} + +	@Override +	public Serializable get(String key) { +		return ctxData.get(key); +	} + +	@Override +	public Serializable remove(String key) { +		return ctxData.remove(key); +	} + +	@Override +	public void put(String key, Serializable object) { +		ctxData.put(key, object); +	} + +	@Override +	public Set<String> keySet() { +		return Collections.unmodifiableSet(ctxData.keySet()); +	} + +	@Override +	public String toString() { +		StringBuilder builder = new StringBuilder(); +		builder.append("ExecutionContextImpl ["); +		builder.append("id=").append(processInstanceId); +		builder.append(", variables="); +		builder.append(ctxData.keySet()); +		builder.append("]"); +		return builder.toString(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExpressionEvaluationContextImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExpressionEvaluationContextImpl.java new file mode 100644 index 000000000..f0d1c861d --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExpressionEvaluationContextImpl.java @@ -0,0 +1,44 @@ +package at.gv.egovernment.moa.id.process; + +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext; + +/** + * Context implementation used for expression evaluation only. + *  + * @author tknall + *  + */ +public class ExpressionEvaluationContextImpl implements ExpressionEvaluationContext { + +	private static final long serialVersionUID = 1L; + +	private Map<String, Serializable> ctxData; + +	/** +	 * Creates a new instance and initializes it with data from a given process instance. +	 *  +	 * @param processInstance +	 *            The process instance. +	 */ +	ExpressionEvaluationContextImpl(ProcessInstance processInstance) { +		ExecutionContext executionContext = processInstance.getExecutionContext(); +		Set<String> keys = executionContext.keySet(); +		ctxData = Collections.synchronizedMap(new HashMap<String, Serializable>(keys.size())); +		for (String key : keys) { +			ctxData.put(key, executionContext.get(key)); +		} +	} + +	@Override +	public Map<String, Serializable> getCtx() { +		return Collections.unmodifiableMap(ctxData); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParser.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParser.java new file mode 100644 index 000000000..162ee624a --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParser.java @@ -0,0 +1,224 @@ +package at.gv.egovernment.moa.id.process; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import javax.xml.stream.util.EventReaderDelegate; +import javax.xml.transform.stax.StAXSource; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.SAXException; + +import at.gv.egovernment.moa.id.process.model.EndEvent; +import at.gv.egovernment.moa.id.process.model.ProcessDefinition; +import at.gv.egovernment.moa.id.process.model.ProcessNode; +import at.gv.egovernment.moa.id.process.model.StartEvent; +import at.gv.egovernment.moa.id.process.model.TaskInfo; +import at.gv.egovernment.moa.id.process.model.Transition; + +/** + * Parses an XML representation of a process definition as defined by the respective XML schema. + * <p/ + * The parser is thread-safe. + * @author tknall + * + */ +public class ProcessDefinitionParser { +	 +	private static final String NS = "http://reference.e-government.gv.at/namespace/moa/process/definition/v1"; +	 +	private static Logger log = LoggerFactory.getLogger(ProcessDefinitionParser.class); + +	private static class LazyProcessDefinitionSchemaHolder { +		private static final Schema PD_SCHEMA_INSTANCE; +		static { +			try (InputStream in = ProcessDefinitionParser.class.getResourceAsStream("ProcessDefinition.xsd")) { +				log.trace("Compiling process definition schema."); +				SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); +				// schema is thread-safe +				PD_SCHEMA_INSTANCE = factory.newSchema(new StreamSource(in)); +			} catch (Exception e) { +				throw new RuntimeException("Unable to compile process definition schema.", e); +			} +		} +	} + +	/** +	 * Parses an XML representation of a process definition. The representation is being validated in order to suffice +	 * the related XML schema. +	 *  +	 * @param processDefinitionInputStream +	 *            The process definition. +	 * @return A new process definition. +	 * @throws ProcessDefinitionParserException +	 *             Thrown in case of error parsing the process definition. +	 */ +	public ProcessDefinition parse(InputStream processDefinitionInputStream) throws ProcessDefinitionParserException { +		XMLEventReader reader = null; +		final ProcessDefinition pd = new ProcessDefinition(); +		log.debug("Parsing and validating process definition."); +		try { + +			// Standard implementation of XMLInputFactory seems not to be thread-safe +			XMLInputFactory inputFactory = XMLInputFactory.newInstance(); +			reader = inputFactory.createXMLEventReader(processDefinitionInputStream); + +			final List<StartElement> transitionElements = new ArrayList<>(); +			final List<StartEvent> startEvents = new ArrayList<>(); +			 +			reader = new EventReaderDelegate(reader) { + +				@Override +				public XMLEvent nextEvent() throws XMLStreamException { +					XMLEvent event = super.nextEvent(); + +					switch (event.getEventType()) { +					case XMLStreamConstants.START_ELEMENT: +						StartElement element = event.asStartElement(); +						QName qname = element.getName(); +						 +						if (NS.equals(qname.getNamespaceURI())) { +							log.trace("Found process description element '{}'.", qname.getLocalPart()); +							Attribute id = element.getAttributeByName(new QName("id")); +							 +							switch (qname.getLocalPart()) { +							case "ProcessDefinition": +								if (id != null) { +									pd.setId(id.getValue()); +								} +								break; +							case "StartEvent": +								StartEvent startEvent = new StartEvent(); +								if (id != null) { +									startEvent.setId(id.getValue()); +								} +								startEvents.add(startEvent); +								break; +							case "EndEvent": +								EndEvent endEvent = new EndEvent(); +								if (id != null) { +									endEvent.setId(id.getValue()); +									pd.getEndEvents().put(id.getValue(), endEvent); +								} +								break; +							case "Transition": +								transitionElements.add(element); +								break; +							case "Task": +								TaskInfo taskInfo = new TaskInfo(); +								if (id != null) { +									taskInfo.setId(id.getValue()); +									pd.getTaskInfos().put(id.getValue(), taskInfo); +								} +								Attribute async = element.getAttributeByName(new QName("async")); +								if (async != null) { +									taskInfo.setAsync(Boolean.valueOf(async.getValue())); +								} +								Attribute implementingClass = element.getAttributeByName(new QName("class")); +								if (implementingClass != null) { +									taskInfo.setTaskImplementingClass(implementingClass.getValue()); +								} +								break; +							} +							 +						} +						 +						break; +					} + +					return event; +				} + +			}; + +			// validator is not thread-safe +			Validator validator = LazyProcessDefinitionSchemaHolder.PD_SCHEMA_INSTANCE.newValidator(); +			validator.validate(new StAXSource(reader)); +			log.trace("Process definition successfully schema validated."); + +			// perform some basic checks +			log.trace("Building model and performing some plausibility checks."); +			if (startEvents.size() != 1) { +				throw new ProcessDefinitionParserException("A ProcessDefinition must contain exactly one single StartEvent."); +			} +			pd.setStartEvent(startEvents.get(0)); +			 +			// link transitions +			Iterator<StartElement> transitions = transitionElements.iterator(); +			while (transitions.hasNext()) { +				StartElement element = transitions.next(); +				Transition transition = new Transition(); +				Attribute id = element.getAttributeByName(new QName("id")); +				if (id != null) { +					transition.setId(id.getValue()); +				} +				Attribute conditionExpression = element.getAttributeByName(new QName("conditionExpression")); +				if (conditionExpression != null) { +					transition.setConditionExpression(conditionExpression.getValue()); +				} +				Attribute from = element.getAttributeByName(new QName("from")); +				if (from != null) { +					ProcessNode fromNode = pd.getProcessNode(from.getValue()); +					if (fromNode == null) { +						throw new ProcessDefinitionParserException("Transition's 'from'-attribute refers to a non-existing event or task '" + from.getValue() + '.'); +					} +					if (fromNode instanceof EndEvent) { +						throw new ProcessDefinitionParserException("Transition cannot start from end event."); +					} +					transition.setFrom(fromNode); +					fromNode.getOutgoingTransitions().add(transition); +				} +				Attribute to = element.getAttributeByName(new QName("to")); +				if (to != null) { +					ProcessNode toNode = pd.getProcessNode(to.getValue()); +					if (toNode == null) { +						throw new ProcessDefinitionParserException("Transition's 'to'-attribute refers to a non-existing event or task '" + to.getValue() + '.'); +					} +					transition.setTo(toNode); +					toNode.getIncomingTransitions().add(transition); +				} +				if (transition.getConditionExpression() == null && Objects.equals(transition.getFrom(), transition.getTo())) { +					throw new ProcessDefinitionParserException("Transition's 'from' equals its 'to'. Since no 'conditionExpression' has been set this will cause a loop."); +				} +			} +			log.debug("Process definition '{}' successfully parsed.", pd.getId()); +			return pd; + +		} catch (ProcessDefinitionParserException e) { +			throw e; +		} catch (XMLStreamException|IOException e) { +			throw new ProcessDefinitionParserException("Unable to read process definition from inputstream.", e); +		} catch (SAXException e) { +			throw new ProcessDefinitionParserException("Schema validation of process description failed.", e); +		} catch (Exception e) { +			throw new ProcessDefinitionParserException("Internal error creating process definition from inputstream.", e); +		} finally { +			if (reader != null) { +				try { +					reader.close(); +				} catch (XMLStreamException e) { +					// error freeing resources +				} +			} +		} +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParserException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParserException.java new file mode 100644 index 000000000..0c214750d --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParserException.java @@ -0,0 +1,35 @@ +package at.gv.egovernment.moa.id.process; + +/** + * Exception thrown in case of error parsing a process definition. + *  + * @author tknall + *  + */ +public class ProcessDefinitionParserException extends Exception { + +	private static final long serialVersionUID = 1L; + +	/** +	 * Creates a new parser exception providing a {@code message} describing the reason and the {@code cause}. +	 *  +	 * @param message +	 *            The message. +	 * @param cause +	 *            The cause. +	 */ +	public ProcessDefinitionParserException(String message, Throwable cause) { +		super(message, cause); +	} + +	/** +	 * Creates a new parser exception providing a {@code message} describing the reason. +	 *  +	 * @param message +	 *            The message. +	 */ +	public ProcessDefinitionParserException(String message) { +		super(message); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java new file mode 100644 index 000000000..5cf84abed --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java @@ -0,0 +1,98 @@ +package at.gv.egovernment.moa.id.process; + + +import java.io.InputStream; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.model.ProcessDefinition; + +/** + * Process engine providing means for starting and resuming processes. + *  + * @author tknall + */ +public interface ProcessEngine { + +	/** +	 * Registers a new process definition. Note that existing definitions with the same identifier will be replaced. +	 *  +	 * @param processDefinition +	 *            The process definition to be registered. +	 */ +	void registerProcessDefinition(ProcessDefinition processDefinition); + +	/** +	 * Registers a new process definition given as {@link InputStream}. Note that existing definitions with the same identifier will be replaced. +	 * +	 * @param processDefinitionInputStream The input stream to the definition to be registered. +	 * @throws ProcessDefinitionParserException Thrown in case of an error parsing the process definition. +	 * @return The process definition's identifier. +	 */ +	String registerProcessDefinition(InputStream processDefinitionInputStream) throws ProcessDefinitionParserException; + +	/** +	 * Creates a process instance according to the referenced process definition, persists it into the database and returns it identifier. +	 * <p/> +	 * Note that the method returns the identifier of a process instance which will be needed in order to start a process or to continue +	 * process execution after asynchronous task execution (refer to {@link #start(String)} and +	 * {@link #signal(String)} for further information). +	 *  +	 * @param processDefinitionId +	 *            The identifier of the respective process definition. +	 * @param executionContext The execution context (may be {@code null}). +	 * @return The id of the newly created process instance (never {@code null}). +	 * @throws ProcessExecutionException +	 *             Thrown in case of error, e.g. when a {@code processDefinitionId} is referenced that does not exist. +	 */ +	String createProcessInstance(String processDefinitionId, ExecutionContext executionContext) throws ProcessExecutionException; + +	/** +	 * Creates a process instance according to the referenced process definition, persists it into the database and returns it identifier. +	 * <p/> +	 * Note that the method returns the identifier of a process instance which will be needed in order to start a process or to continue +	 * process execution after asynchronous task execution (refer to {@link #start(String)} and +	 * {@link #signal(String)} for further information). +	 *  +	 * @param processDefinitionId +	 *            The identifier of the respective process definition. +	 * @return The id of the newly created process instance (never {@code null}). +	 * @throws ProcessExecutionException +	 *             Thrown in case of error, e.g. when a {@code processDefinitionId} is referenced that does not exist. +	 */ +	String createProcessInstance(String processDefinitionId) throws ProcessExecutionException; + +	/** +	 * Returns the process instance with a given {@code processInstanceId}. +	 *  +	 * @param processInstanceId +	 *            The process instance id. +	 * @return The process instance (never {@code null}). +	 * @throws IllegalArgumentException +	 *             In case the process instance does not/no longer exist. +	 * @throws RuntimeException +	 *             In case the process instance could not be retrieved from persistence. +	 */ +	ProcessInstance getProcessInstance(String processInstanceId); + +	/** +	 * Starts the process using the given {@code processInstanceId}. +	 *  +	 * @param processInstanceId +	 *            The process instance id. +	 * @throws ProcessExecutionException +	 *             Thrown in case of error. +	 */ +	void start(String processInstanceId) throws ProcessExecutionException; + + +	/** +	 * Resumes process execution after an asynchronous task has been executed. +	 *  +	 * @param processInstanceId +	 *            The process instance id. +	 * @throws ProcessExecutionException +	 *             Thrown in case of error. +	 */ +	void signal(String processInstanceId) throws ProcessExecutionException; + +}
\ No newline at end of file diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java new file mode 100644 index 000000000..0ffa22ec3 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java @@ -0,0 +1,355 @@ +package at.gv.egovernment.moa.id.process; + +import java.io.InputStream; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Predicate; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext; +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator; +import at.gv.egovernment.moa.id.process.api.Task; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStore; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAO; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAOImpl; +import at.gv.egovernment.moa.id.process.model.EndEvent; +import at.gv.egovernment.moa.id.process.model.ProcessDefinition; +import at.gv.egovernment.moa.id.process.model.ProcessNode; +import at.gv.egovernment.moa.id.process.model.StartEvent; +import at.gv.egovernment.moa.id.process.model.TaskInfo; +import at.gv.egovernment.moa.id.process.model.Transition; + +/** + * Process engine implementation allowing starting and continuing processes as well as providing means for cleanup actions. + */ +public class ProcessEngineImpl implements ProcessEngine { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	private ProcessDefinitionParser pdp = new ProcessDefinitionParser(); + +	ProcessInstanceStoreDAO piStoreDao = ProcessInstanceStoreDAOImpl.getInstance(); + +	private Map<String, ProcessDefinition> processDefinitions = new ConcurrentHashMap<String, ProcessDefinition>(); + +	private final static String MDC_CTX_PI_NAME = "processInstanceId"; +	private final static String MDC_CTX_TASK_NAME = "taskId"; + +	private ExpressionEvaluator transitionConditionExpressionEvaluator; + +	@Override +	public void registerProcessDefinition(ProcessDefinition processDefinition) { +		log.info("Registering process definition '{}'.", processDefinition.getId()); +		processDefinitions.put(processDefinition.getId(), processDefinition); +	} + +	@Override +	public String registerProcessDefinition(InputStream processDefinitionInputStream) throws ProcessDefinitionParserException{ +		ProcessDefinition pd = pdp.parse(processDefinitionInputStream); +		registerProcessDefinition(pd); +		return pd.getId(); +	} + +	/** +	 * Sets the process definitions. +	 * +	 * @param processDefinitions +	 *            The process definitions. +	 * @throws IllegalArgumentException +	 *             In case the process definitions contain definitions with the same identifier. +	 */ +	public void setProcessDefinitions(Iterable<ProcessDefinition> processDefinitions) { +		this.processDefinitions.clear(); +		for (ProcessDefinition pd : processDefinitions) { +			if (this.processDefinitions.containsKey(pd.getId())) { +				throw new IllegalArgumentException("Duplicate process definition identifier '" + pd.getId() + "'."); +			} +			registerProcessDefinition(pd); +		} +	} + +	/** +	 * Sets an expression evaluator that should be used to process transition condition expressions. +	 * @param transitionConditionExpressionEvaluator The expression evaluator. +	 */ +	public void setTransitionConditionExpressionEvaluator( +			ExpressionEvaluator transitionConditionExpressionEvaluator) { +		this.transitionConditionExpressionEvaluator = transitionConditionExpressionEvaluator; +	} + + +	@Override +	public String createProcessInstance(String processDefinitionId, ExecutionContext executionContext) throws ProcessExecutionException { +		// look for respective process definition +		ProcessDefinition pd = processDefinitions.get(processDefinitionId); +		if (pd == null) { +			throw new ProcessExecutionException("Unable to find process definition for process '" + processDefinitionId + "'."); +		} +		// create and keep process instance +		ProcessInstance pi = new ProcessInstance(pd, executionContext); +		log.info("Creating process instance from process definition '{}': {}", processDefinitionId, pi.getId()); + +		try { +			saveOrUpdateProcessInstance(pi); +		} catch (MOADatabaseException e) { +			throw new ProcessExecutionException("Unable to persist process instance.", e); +		} + +		return pi.getId(); +	} + +	@Override +	public String createProcessInstance(String processDefinitionId) throws ProcessExecutionException { +		return createProcessInstance(processDefinitionId, null); +	} + +	@Override +	public void start(String processInstanceId) throws ProcessExecutionException { + +		try { +			ProcessInstance pi = loadProcessInstance(processInstanceId); + +			MDC.put(MDC_CTX_PI_NAME, pi.getId()); + +			if (!ProcessInstanceState.NOT_STARTED.equals(pi.getState())) { +				throw new ProcessExecutionException("Process instance '" + pi.getId() + "' has already been started (current state is " + pi.getState() + ")."); +			} +			log.info("Starting process instance '{}'.", pi.getId()); +			// execute process +			pi.setState(ProcessInstanceState.STARTED); +			execute(pi); + +			saveOrUpdateProcessInstance(pi); +		} catch (MOADatabaseException e) { +			throw new ProcessExecutionException("Unable to load/save process instance.", e); + +		} finally { +			MDC.remove(MDC_CTX_PI_NAME); +		} +	} +	 +	@Override +	public void signal(String processInstanceId) throws ProcessExecutionException { + +		try { +			ProcessInstance pi = loadProcessInstance(processInstanceId); + +			MDC.put(MDC_CTX_PI_NAME, pi.getId()); + +			if (!ProcessInstanceState.SUSPENDED.equals(pi.getState())) { +				throw new ProcessExecutionException("Process instance '" + pi.getId() + "' has not been suspended (current state is " + pi.getState() + ")."); +			} + +			log.info("Waking up process instance '{}'.", pi.getId()); +			pi.setState(ProcessInstanceState.STARTED); +			execute(pi); + +			saveOrUpdateProcessInstance(pi); +		} catch (MOADatabaseException e) { +			throw new ProcessExecutionException("Unable to load/save process instance.", e); + +		} finally { +			MDC.remove(MDC_CTX_PI_NAME); +		} +	} +	 + +	/** +	 * Instantiates a task implementation given by a {@link TaskInfo}. +	 * @param ti The task info. +	 * @return A Task implementation or {@code null} if the task info does not reference any task implementing classes. +	 * @throws ProcessExecutionException Thrown in case of error (when the referenced class does not implement {@link Task} for instance). +	 */ +	private Task createTaskInstance(TaskInfo ti) throws ProcessExecutionException { +		String clazz = StringUtils.trimToNull(ti.getTaskImplementingClass()); +		Task task = null; +		 +		if (clazz != null) { +			log.debug("Instantiating task implementing class '{}'.", clazz); +			Class<?> instanceClass = null; +			try { +				instanceClass = Class.forName(clazz, true, Thread.currentThread().getContextClassLoader()); +			} catch (Exception e) { +				throw new ProcessExecutionException("Unable to get class '" + clazz + "' associated with task '" + ti.getId() + "' .", e); +			} +			if (!Task.class.isAssignableFrom(instanceClass)) { +				throw new ProcessExecutionException("Class '" + clazz + "' associated with task '" + ti.getId() + "' is not assignable to " + Task.class.getName() + "."); +			} +			try { +				task = (Task) instanceClass.newInstance(); +			} catch (Exception e) { +				throw new ProcessExecutionException("Unable to instantiate class '" + clazz + "' associated with task '" + ti.getId() + "' .", e); +			} +		} + +		return task; +	} + +	/** +	 * Starts/executes a given process instance. +	 * @param pi The process instance. +	 * @throws ProcessExecutionException Thrown in case of error. +	 */ +	private void execute(final ProcessInstance pi) throws ProcessExecutionException { +		if (ProcessInstanceState.ENDED.equals(pi.getState())) { +			throw new ProcessExecutionException("Process for instance '" + pi.getId() + "' has already been ended."); +		} +		ProcessDefinition pd = pi.getProcessDefinition(); +		ProcessNode processNode = pd.getProcessNode(pi.getNextId()); +		log.debug("Processing node '{}'.", processNode.getId()); +		 +		// distinguish process node types StartEvent, TaskInfo and EndEvent +		 +		if (processNode instanceof TaskInfo) { +			// TaskInfo types need to be executed +			TaskInfo ti = (TaskInfo) processNode; +			MDC.put(MDC_CTX_TASK_NAME, ti.getId()); +			try { +				log.info("Processing task '{}'.", ti.getId()); +				Task task = createTaskInstance(ti); +				if (task != null) { +					try { +						log.info("Executing task implementation for task '{}'.", ti.getId()); +						log.debug("Execution context before task execution: {}", pi.getExecutionContext().keySet()); +						task.execute(pi.getExecutionContext()); +						log.info("Returned from execution of task '{}'.", ti.getId()); +						log.debug("Execution context after task execution: {}", pi.getExecutionContext().keySet()); +					} catch (Throwable t) { +						throw new ProcessExecutionException("Error executing task '" + ti.getId() + "'.", t); +					} +				} else { +					log.debug("No task implementing class set."); +				} +			} finally { +				MDC.remove(MDC_CTX_TASK_NAME); +			} +			 +		} else if (processNode instanceof EndEvent) { +			log.info("Finishing process instance '{}'.", pi.getId()); + +			try { +				piStoreDao.remove(pi.getId()); +			} catch (MOADatabaseException e) { +				throw new ProcessExecutionException("Unable to remove process instance.", e); +			} +			pi.setState(ProcessInstanceState.ENDED); +			log.debug("Final process context: {}", pi.getExecutionContext().keySet()); +			return; +		} +		 +		final ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContextImpl(pi); +		 +		// traverse pointer +		Transition t = CollectionUtils.find(processNode.getOutgoingTransitions(), new Predicate<Transition>() { +			@Override +			public boolean evaluate(Transition transition) { +				if (transitionConditionExpressionEvaluator != null && transition.getConditionExpression() != null) { +					log.trace("Evaluating transition expression '{}'.", transition.getConditionExpression()); +					return transitionConditionExpressionEvaluator.evaluate(expressionContext, transition.getConditionExpression()); +				} +				return true; +			} +		}); +		if (t == null) { +			throw new ProcessExecutionException("No valid transition starting from process node '" + processNode.getId()+ "'."); +		} +		log.trace("Found suitable transition: {}", t); +		// update pointer +		log.trace("Shifting process token from '{}' to '{}'.", pi.getNextId(), t.getTo().getId()); +		pi.setNextId(t.getTo().getId()); +		 +		// inspect current task +		if (t.getTo() instanceof TaskInfo && (((TaskInfo) t.getTo()).isAsync())) { +			// immediately return in case of asynchonous task +			log.info("Suspending process instance '{}' for asynchronous task '{}'.", pi.getId(), t.getTo().getId()); +			pi.setState(ProcessInstanceState.SUSPENDED); +			return; +		} +		 +		// continue execution in case of StartEvent or Task +		if (processNode instanceof StartEvent || processNode instanceof TaskInfo) { +			execute(pi); +		} +	} + +	@Override +	public ProcessInstance getProcessInstance(String processInstanceId) { + +		ProcessInstance processInstance; +		try { +			processInstance = loadProcessInstance(processInstanceId); + +		} catch (MOADatabaseException e) { +			throw new RuntimeException("The process instance '" + processInstanceId + "' could not be retrieved.", e); +		} + +		if (processInstance == null) { +			throw new IllegalArgumentException("The process instance '" + processInstanceId + "' does not/no longer exist."); +		} + +		return processInstance; +	} + +	/** +	 * Persists a {@link ProcessInstance} to the database. +	 * @param processInstance The object to persist. +	 * @throws MOADatabaseException Thrown if an error occurs while accessing the database. +	 */ +	private void saveOrUpdateProcessInstance(ProcessInstance processInstance) throws MOADatabaseException { +		ProcessInstanceStore store = new ProcessInstanceStore(); + +		ExecutionContext ctx = processInstance.getExecutionContext(); + +		Map<String, Serializable> ctxData = new HashMap<String, Serializable>(); +		for (String key : ctx.keySet()) { +			ctxData.put(key, ctx.get(key)); +		} +		store.setExecutionContextData(ctxData); + +		store.setNextTaskId(processInstance.getNextId()); +		store.setProcessDefinitionId(processInstance.getProcessDefinition().getId()); + +		store.setProcessInstanceId(processInstance.getId()); +		store.setProcessState(processInstance.getState()); + +		piStoreDao.saveOrUpdate(store); +	} + +	/** +	 * Load a {@link ProcessInstance} with a certain id from the database. +	 * @param processInstanceId The process instance id +	 * @return The process instance corresponding to the id or {@code null} if no such object is found. +	 * @throws MOADatabaseException Thrown if an error occurs while accessing the database. +	 */ +	private ProcessInstance loadProcessInstance(String processInstanceId) throws MOADatabaseException { + +		ProcessInstanceStore piStore = piStoreDao.load(processInstanceId); + +		if (piStore == null) { +			return null; +		} + +		ExecutionContext executionContext = new ExecutionContextImpl(piStore.getProcessInstanceId()); + +		Map<String, Serializable> executionContextData = piStore.getExecutionContextData(); +		for (String key : executionContextData.keySet()) { +			executionContext.put(key, executionContextData.get(key)); +		} + +		ProcessInstance pi = new ProcessInstance(processDefinitions.get(piStore.getProcessDefinitionId()), executionContext); +		pi.setNextId(piStore.getNextTaskId()); +		pi.setState(piStore.getProcessState()); + +		return pi; +	} +	 +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessExecutionException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessExecutionException.java new file mode 100644 index 000000000..821bbe6dc --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessExecutionException.java @@ -0,0 +1,36 @@ +package at.gv.egovernment.moa.id.process; + +/** + * Indicates a problem when executing a process. + *  + * @author tknall + *  + */ +public class ProcessExecutionException extends Exception { + +	private static final long serialVersionUID = 1L; + +	/** +	 * Creates a new process execution exception providing a {@code message} describing the reason and the respective +	 * {@code cause}. +	 *  +	 * @param message +	 *            The message. +	 * @param cause +	 *            The cause. +	 */ +	public ProcessExecutionException(String message, Throwable cause) { +		super(message, cause); +	} + +	/** +	 * Creates a new process execution exception providing a {@code message} describing the reason. +	 *  +	 * @param message +	 *            The message. +	 */ +	public ProcessExecutionException(String message) { +		super(message); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstance.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstance.java new file mode 100644 index 000000000..a6cf3b57f --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstance.java @@ -0,0 +1,164 @@ +package at.gv.egovernment.moa.id.process; + +import java.io.Serializable; +import java.util.Date; + +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.time.DurationFormatUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.model.ProcessDefinition; +import at.gv.egovernment.moa.id.process.support.SecureRandomHolder; + +/** + * Represents a process being executed. The process instance provides information about the process and its state. + *  + * @author tknall + *  + */ +public class ProcessInstance implements Serializable { + +	private static final long serialVersionUID = 1L; +	private static final int RND_ID_LENGTH = 22; + +	private ProcessDefinition processDefinition; +	private String nextId; +	private Date lru; +	private ExecutionContext executionContext; +	private ProcessInstanceState state = ProcessInstanceState.NOT_STARTED; + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	/** +	 * Creates a new process instance, based on a given process definition and a +	 * given execution context. If the given execution context is {@code null} a new execution context will be created.<p/> +	 * The process instance id of the execution context will be newly generated if it is {@code null} in the execution context. +	 *  +	 * @param processDefinition +	 *            The process definition. +	 * @param executionContext +	 *            The execution context (may be {@code null}). If {@code null} a new execution context will be created internally. +	 */ +	ProcessInstance(ProcessDefinition processDefinition, ExecutionContext executionContext) { +		this.processDefinition = processDefinition; +		nextId = processDefinition.getStartEvent().getId(); +		if (executionContext == null) { +			executionContext = new ExecutionContextImpl(); +		} +		if (executionContext.getProcessInstanceId() == null) { +			String pdIdLocalPart = RandomStringUtils.random(RND_ID_LENGTH, 0, 0, true, true, null, +					SecureRandomHolder.getInstance()); +			executionContext.setProcessInstanceId(this.processDefinition.getId() + "-" + pdIdLocalPart); +		} else { +			log.debug("Using process instance id from execution context."); +		} +		log.debug("Creating process instance with id '{}'.", executionContext.getProcessInstanceId()); +		this.executionContext = executionContext; +		touch(); +	} + +	/** +	 * Returns the underlying process definition. +	 *  +	 * @return The underlying process definition. +	 */ +	ProcessDefinition getProcessDefinition() { +		touch(); +		return processDefinition; +	} + +	/** +	 * Returns the id of the process node to be executed next. +	 *  +	 * @return The process node pointer indicating the process node to be executed next. +	 */ +	public String getNextId() { +		touch(); +		return nextId; +	} + +	/** +	 * Sets the internal pointer to the process node to be executed next. +	 *  +	 * @param nextId +	 *            The process node id to be executed next. +	 */ +	void setNextId(String nextId) { +		touch(); +		this.nextId = nextId; +	} + +	/** +	 * Returns the current state of the process instance. +	 *  +	 * @return The current state. +	 */ +	public ProcessInstanceState getState() { +		touch(); +		return state; +	} + +	/** +	 * Sets the current state of the process instance. +	 *  +	 * @param state +	 *            The current state. +	 */ +	void setState(ProcessInstanceState state) { +		touch(); +		this.state = state; +	} + +	public String getId() { +		touch(); +		return executionContext.getProcessInstanceId(); +	} + +	/** +	 * Updates the last recently used date of the process instance. +	 */ +	private void touch() { +		lru = new Date(); +	} + +	/** +	 * Returns the date the process instance has been accessed last. +	 *  +	 * @return The last recently used date. +	 */ +	Date getLru() { +		return lru; +	} + +	/** +	 * Returns the associated execution context. +	 * @return The execution context (never {@code null}). +	 */ +	public ExecutionContext getExecutionContext() { +		touch(); +		return executionContext; +	} + +	@Override +	public String toString() { +		StringBuilder builder = new StringBuilder(); +		builder.append("ProcessInstance ["); +		builder.append("id=").append(executionContext.getProcessInstanceId()); +		builder.append(", idle since=").append( +				DurationFormatUtils.formatDurationWords(new Date().getTime() - this.lru.getTime(), true, true)); +		if (processDefinition != null) { +			builder.append(", processDefinition.id="); +			builder.append(processDefinition.getId()); +		} +		if (nextId != null) { +			builder.append(", nextId="); +			builder.append(nextId); +		} +		builder.append(", executionContext=").append(executionContext); +		builder.append("]"); +		return builder.toString(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstanceState.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstanceState.java new file mode 100644 index 000000000..2765283a0 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstanceState.java @@ -0,0 +1,30 @@ +package at.gv.egovernment.moa.id.process; + +/** + * Represents a certain process instance state. + * @author tknall + * + */ +public enum ProcessInstanceState { +	 +	/** +	 * Indicates that the process with this process instance has not yet been started. +	 */ +	NOT_STARTED, +	 +	/** +	 * Indicates that the process is currently running. +	 */ +	STARTED, +	 +	/** +	 * Indicates that the process has been suspended until being waken up by someonce calling {@code signal}. +	 */ +	SUSPENDED, +	 +	/** +	 * Indicates that the process has been completed. +	 */ +	ENDED + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExecutionContext.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExecutionContext.java new file mode 100644 index 000000000..4a9dfc336 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExecutionContext.java @@ -0,0 +1,63 @@ +package at.gv.egovernment.moa.id.process.api; + +import java.io.Serializable; +import java.util.Set; + +/** + * Encapsulates data needed for or provided by task execution. + *  + * @author tknall + *  + */ +public interface ExecutionContext extends Serializable { + +	/** +	 * Returns the identifier of underlying process instance. +	 *  +	 * @return The identifier of the process instance. +	 */ +	String getProcessInstanceId(); + +	/** +	 * Sets the identifier of underlying process instance. +	 *  +	 * @param processInstanceId +	 *            The identifier of the process instance. +	 */ +	void setProcessInstanceId(String processInstanceId); + +	/** +	 * Stores a serializable object using {@code key}. +	 *  +	 * @param key +	 *            The key under that the {@code object} should be stored. +	 * @param object The object to be stored. +	 */ +	void put(String key, Serializable object); + +	/** +	 * Returns an serializable object stored within this process context using {@code key}. +	 *  +	 * @param key +	 *            The key that has been used to store the serializable object (may be {@code null}). +	 * @return The object or {@code null} in case the key does not relate to a stored object or the stored object itself +	 *         was {@code null}. +	 */ +	Serializable get(String key); +	 +	/** +	 * Removes the object stored using {@code key}. +	 * @param key +	 *            The key that has been used to store the serializable object (may be {@code null}). +	 * @return The object that has been removed or {@code null} there was no object stored using {@code key}. +	 */ +	Serializable remove(String key); + +	/** +	 * Returns an unmodifiable set containing the stored keys. +	 *  +	 * @return The keyset (never {@code null}). +	 */ +	Set<String> keySet(); + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluationContext.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluationContext.java new file mode 100644 index 000000000..94854dcad --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluationContext.java @@ -0,0 +1,23 @@ +package at.gv.egovernment.moa.id.process.api; + +import java.io.Serializable; +import java.util.Map; + +import at.gv.egovernment.moa.id.process.model.Transition; + +/** + * Context used for evaluation of condition expressions set for {@linkplain Transition Transitions}. + *  + * @author tknall + *  + */ +public interface ExpressionEvaluationContext extends Serializable { + +	/** +	 * Returns the context data map used for expression evaluation. +	 *  +	 * @return An unmodifiable map (never {@code null}). +	 */ +	Map<String, Serializable> getCtx(); + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluator.java new file mode 100644 index 000000000..fe0743201 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluator.java @@ -0,0 +1,25 @@ +package at.gv.egovernment.moa.id.process.api; + +/** + * Evaluates a given {@code expression} returning a boolean value. + *  + * @author tknall + */ +public interface ExpressionEvaluator { + +	/** +	 * Evaluates a given {@code expression} returning a boolean value. +	 *  +	 * @param expressionContext +	 *            The context which can be used for evaluation of the expression. +	 * @param expression +	 *            The expression resulting in a boolean (must not be {@code null}). +	 * @return A boolean value. +	 * @throws IllegalArgumentException +	 *             In case of an invalid {@code expression}. +	 * @throws NullPointerException +	 *             In case of a {@code null} expression. +	 */ +	boolean evaluate(ExpressionEvaluationContext expressionContext, String expression); + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/Task.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/Task.java new file mode 100644 index 000000000..6401b1d5d --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/Task.java @@ -0,0 +1,21 @@ +package at.gv.egovernment.moa.id.process.api; + + +/** + * Represents a single task to be performed upon process execution. + *  + * @author tknall + *  + */ +public interface Task { + +	/** +	 * Executes this task. +	 *  +	 * @param executionContext +	 *            Provides execution related information. +	 * @throws Exception An exception upon task execution. +	 */ +	void execute(ExecutionContext executionContext) throws Exception; + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStore.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStore.java new file mode 100644 index 000000000..d690c37bf --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStore.java @@ -0,0 +1,89 @@ +package at.gv.egovernment.moa.id.process.dao; + +import java.io.Serializable; +import java.util.Map; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.Id; +import javax.persistence.Lob; +import javax.persistence.Table; + +import org.hibernate.internal.util.SerializationHelper; + +import at.gv.egovernment.moa.id.process.ProcessInstanceState; + +@Entity +@Table(name = "processinstance") +public class ProcessInstanceStore { + +	/** +	 * A process instance identifier qualifies as natural primary key by satisfying these requirements +	 * ("unique, constant, required"): +	 * <ul> +	 * <li>unique value</li> +	 * <li>never changes (immutable)</li> +	 * <li>never {@code null}</li> +	 * </ul> +	 */ +	@Id +	private String processInstanceId; + +	@Column(name = "processDefinitionId", nullable = false) +	private String processDefinitionId; + +	@Column(name = "nextTaskId", nullable = false) +	private String nextTaskId; + +	@Column(name = "processState", nullable = false) +	@Enumerated(value = EnumType.STRING) +	private ProcessInstanceState processState; + +	@Column(name = "executionContextData", nullable = false) +	@Lob +	private byte[] executionContextData; + +	public String getProcessInstanceId() { +		return processInstanceId; +	} + +	public String getProcessDefinitionId() { +		return processDefinitionId; +	} + +	public String getNextTaskId() { +		return nextTaskId; +	} + +	public ProcessInstanceState getProcessState() { +		return processState; +	} + +	@SuppressWarnings("unchecked") +	public Map<String, Serializable> getExecutionContextData() { +		return  (Map<String, Serializable>) SerializationHelper.deserialize(executionContextData); +	} + +	public void setProcessInstanceId(String processInstanceId) { +		this.processInstanceId = processInstanceId; +	} + +	public void setProcessDefinitionId(String processDefinitionId) { +		this.processDefinitionId = processDefinitionId; +	} + +	public void setNextTaskId(String nextTaskId) { +		this.nextTaskId = nextTaskId; +	} + +	public void setProcessState(ProcessInstanceState processState) { +		this.processState = processState; +	} + +	public void setExecutionContextData(Map<String, Serializable> executionContextData) { +		this.executionContextData = SerializationHelper.serialize((Serializable) executionContextData); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAO.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAO.java new file mode 100644 index 000000000..57ce70c08 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAO.java @@ -0,0 +1,43 @@ +package at.gv.egovernment.moa.id.process.dao; + +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.process.ProcessInstance; + +public interface ProcessInstanceStoreDAO { + +	/** +	 * Stores a {@link ProcessInstance} defined by {@code pIStore} in the +	 * database. +	 *  +	 * @param pIStore +	 *            the {@link ProcessInstanceStore} to persist. +	 * @throws MOADatabaseException +	 *             is thrown if a problem occurs while accessing the database. +	 */ +	void saveOrUpdate(ProcessInstanceStore pIStore) throws MOADatabaseException; + +	/** +	 * Returns a {@link ProcessInstanceStore}, defined by +	 * {@code processInstanceID} from the database, or {@code null} if the +	 * object could not be found. +	 *  +	 * @param processInstanceId +	 *            the id of the {@code ProcessInstanceStore} to retrieve. +	 * @return a ProcessInstanceStore, or {@code null}. +	 * @throws MOADatabaseException +	 *             is thrown if a problem occurs while accessing the database. +	 */ +	ProcessInstanceStore load(String processInstanceId) throws MOADatabaseException; + +	/** +	 * Deletes the {@link ProcessInstance} corresponding with the +	 * {@code processInstanceId}. +	 *  +	 * @param processInstanceId +	 *            the id of the {@code ProcessInstance} to be deleted. +	 * @throws MOADatabaseException +	 *             is thrown if a problem occurs while accessing the database. +	 */ +	void remove(String processInstanceId) throws MOADatabaseException; + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java new file mode 100644 index 000000000..012dfe90b --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java @@ -0,0 +1,90 @@ +package at.gv.egovernment.moa.id.process.dao; + +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.criterion.Restrictions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; + +/** + * Database backed implementation of the {@link ProcessInstanceStoreDAO} + * interface. + */ +public class ProcessInstanceStoreDAOImpl implements ProcessInstanceStoreDAO { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	private static ProcessInstanceStoreDAO instance = new ProcessInstanceStoreDAOImpl(); + +	public static ProcessInstanceStoreDAO getInstance() { +		return instance; +	} + +	@Override +	public void saveOrUpdate(ProcessInstanceStore pIStore) throws MOADatabaseException { +		try { +			MOASessionDBUtils.saveOrUpdate(pIStore); +			log.debug("Store process instance with='{}' in the database.", pIStore.getProcessInstanceId()); +		} catch (MOADatabaseException e) { +			log.warn("ProcessInstanceStore could not be persisted to the database."); +			throw e; +		} +	} + +	@Override +	public ProcessInstanceStore load(String processInstanceId) throws MOADatabaseException { + +		log.debug("Retrieve the ProcessInstanceStore for id='{}' from the database.", processInstanceId); +		Session session = MOASessionDBUtils.getCurrentSession(); + +		ProcessInstanceStore result = null; +		Transaction tx = null; +		synchronized (session) { +			try { + +				tx = session.beginTransaction(); +				// select all where processInstanceId equals processInstanceId +				Criteria criteria = session.createCriteria(ProcessInstanceStore.class); +				criteria.add(Restrictions.eq("processInstanceId", processInstanceId)); +				result = (ProcessInstanceStore) criteria.uniqueResult(); +				tx.commit(); + +			} catch (Exception e) { +				log.error("There are multiple persisted processes with the same process instance id '{}'", +						processInstanceId); +				if (tx != null) { +					tx.rollback(); +				} +				throw e; +			} finally { +				MOASessionDBUtils.closeSession(); +			} +		} +		if (result != null) { +			log.debug("Found process instance store for instance '{}'.", processInstanceId); +		} else { +			log.debug("Unable to find process instance store for instance '{}'.", processInstanceId); +		} +		return result; +	} + +	@Override +	public void remove(String processInstanceId) throws MOADatabaseException { + +		log.debug("Delete the ProcessInstanceStore for id='{}' from the database.", processInstanceId); +		ProcessInstanceStore toBeDeleted = load(processInstanceId); +		if (toBeDeleted != null) { +			if (!MOASessionDBUtils.delete(toBeDeleted)) { +				log.warn("Could not delete the ProcessInstanceStore with process instance id '{}'", processInstanceId); +				throw new MOADatabaseException("Could not delete the ProcessInstanceStore with process instance id '" +						+ processInstanceId + "'."); +			} +		} else  +			log.trace("ProcessInstanceStore for id='{}' was not found and could therefore not be deleted.", processInstanceId); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/EndEvent.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/EndEvent.java new file mode 100644 index 000000000..49fb082ea --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/EndEvent.java @@ -0,0 +1,42 @@ +package at.gv.egovernment.moa.id.process.model; + +import java.io.Serializable; + +import org.apache.commons.collections4.CollectionUtils; + +/** + * Represents an end event. Process execution terminates when an end event is reached. + *  + * @author tknall + */ +public class EndEvent extends ProcessNode implements Serializable { + +	private static final long serialVersionUID = 1L; + +	@Override +	public String toString() { +		StringBuilder builder = new StringBuilder(); +		builder.append("EndEvent ["); +		if (getId() != null) { +			builder.append("id="); +			builder.append(getId()); +		} +		if (CollectionUtils.isNotEmpty(getIncomingTransitions())) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("incomingTransitions="); +			builder.append(getIncomingTransitions()); +		} +		if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("outgoingTransitions="); +			builder.append(getOutgoingTransitions()); +		} +		builder.append("]"); +		return builder.toString(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessDefinition.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessDefinition.java new file mode 100644 index 000000000..518409ecf --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessDefinition.java @@ -0,0 +1,158 @@ +package at.gv.egovernment.moa.id.process.model; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; + +import at.gv.egovernment.moa.id.process.ProcessDefinitionParser; + +/** + * Represents a single process definition containing + * <ul> + * <li>a {@link StartEvent},</li> + * <li>one or more {@linkplain TaskInfo Tasks},</li> + * <li>one or more {@linkplain EndEvent EndEvents} and</li> + * <li>some {@linkplain Transition Transitions} linking StartEvents, Tasks and EndEvents. + * </ul> + *  + * @author tknall + *  + */ +public class ProcessDefinition { + +	private String id; +	private StartEvent startEvent; +	private Map<String, TaskInfo> taskInfos = new LinkedHashMap<>(); +	private Map<String, EndEvent> endEvents = new LinkedHashMap<>(); + +	/** +	 * Returns the unique identifier of the process definition. +	 *  +	 * @return The unique identifier (never {@code null} if process definition comes from +	 *         {@link ProcessDefinitionParser}). +	 */ +	public String getId() { +		return id; +	} + +	/** +	 * Sets the unique identifier of the process definition. +	 *  +	 * @param id +	 *            The unique identifier. +	 */ +	public void setId(String id) { +		this.id = id; +	} + +	/** +	 * Returns the start event of the process definition. +	 *  +	 * @return The start event (never {@code null} if process definition comes from {@link ProcessDefinitionParser}). +	 */ +	public StartEvent getStartEvent() { +		return startEvent; +	} + +	/** +	 * Sets the start event of the process definition. +	 *  +	 * @param startEvent +	 *            The start event. +	 */ +	public void setStartEvent(StartEvent startEvent) { +		this.startEvent = startEvent; +	} + +	/** +	 * Returns a map containing the tasks of the process definition. +	 *  +	 * @return The tasks (map is never {@code null} if process definition comes from {@link ProcessDefinitionParser}). +	 */ +	public Map<String, TaskInfo> getTaskInfos() { +		return taskInfos; +	} + +	/** +	 * Sets the map containing the tasks. +	 *  +	 * @param taskInfos +	 *            The map containing the tasks. +	 */ +	public void setTaskInfos(Map<String, TaskInfo> taskInfos) { +		this.taskInfos = taskInfos; +	} + +	/** +	 * Returns a map containing the end events of the process description. +	 *  +	 * @return The map containing the end events (map is never {@code null} if process definition comes from +	 *         {@link ProcessDefinitionParser}). +	 */ +	public Map<String, EndEvent> getEndEvents() { +		return endEvents; +	} + +	/** +	 * Sets a map containing the end events of the process description. +	 *  +	 * @param endEvents +	 *            The map containing the end events. +	 */ +	public void setEndEvents(Map<String, EndEvent> endEvents) { +		this.endEvents = endEvents; +	} + +	/** +	 * Returns the process node associated with the given {@code id}. +	 *  +	 * @param id +	 *            The identifier of the process node. +	 * @return The process node (may be {code null} when no process node with the given {@code id} exists). +	 */ +	public ProcessNode getProcessNode(String id) { +		Objects.requireNonNull(id, "Identifier must not be null."); +		if (startEvent != null && id.equals(startEvent.getId())) { +			return startEvent; +		} +		TaskInfo task = taskInfos.get(id); +		if (task != null) { +			return task; +		} +		return endEvents.get(id); +	} + +	@Override +	public String toString() { +		StringBuilder builder = new StringBuilder(); +		if (id != null) { +			builder.append("id="); +			builder.append(id); +		} +		if (startEvent != null) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("startEvent="); +			builder.append(startEvent); +		} +		if (taskInfos != null && !taskInfos.isEmpty()) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("tasksInfos="); +			builder.append(taskInfos.values()); +		} +		if (endEvents != null && !endEvents.isEmpty()) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("endEvents="); +			builder.append(endEvents.values()); +		} +		builder.insert(0, "ProcessDefinition ["); +		builder.append("]"); +		return builder.toString(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessNode.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessNode.java new file mode 100644 index 000000000..42f2e3cc2 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessNode.java @@ -0,0 +1,69 @@ +package at.gv.egovernment.moa.id.process.model; + +import java.util.ArrayList; +import java.util.List; + +import at.gv.egovernment.moa.id.process.ProcessDefinitionParser; + +/** + * Represents a {@link StartEvent}, an {@link EndEvent} or a {@linkplain TaskInfo Task}. + * @author tknall + * + */ +public abstract class ProcessNode { + +	private String id; +	private List<Transition> outgoingTransitions = new ArrayList<>(); +	private List<Transition> incomingTransitions = new ArrayList<>(); + +	/** +	 * Returns the unique identifier of the process node. +	 *  +	 * @return The unique identifier (never {@code null} if process node comes from a process definition from +	 *         {@link ProcessDefinitionParser}). +	 */ +	public String getId() { +		return id; +	} + +	/** +	 * Sets the unique identifier of the process node. +	 * @param id The unique identifier. +	 */ +	public void setId(String id) { +		this.id = id; +	} + +	/** +	 * Returns a list of transitions pointing from this process node to another one. +	 * @return A list of transitions (never {@code null} if process node comes from a process definition from {@link ProcessDefinitionParser}). +	 */ +	public List<Transition> getOutgoingTransitions() { +		return outgoingTransitions; +	} + +	/** +	 * Sets the list of transitions pointing from this process node to another one. +	 * @param outgoingTransitions The list of transitions originating from this process node. +	 */ +	public void setOutgoingTransitions(List<Transition> outgoingTransitions) { +		this.outgoingTransitions = outgoingTransitions; +	} + +	/** +	 * Returns a list of transitions pointing from another process node to this one. +	 * @return A list of transitions (never {@code null} if process node comes from a process definition from {@link ProcessDefinitionParser}). +	 */ +	public List<Transition> getIncomingTransitions() { +		return incomingTransitions; +	} + +	/** +	 * Sets the list of transitions pointing from another process node to this one. +	 * @param incomingTransitions A list of transitions pointing to this process node. +	 */ +	public void setIncomingTransitions(List<Transition> incomingTransitions) { +		this.incomingTransitions = incomingTransitions; +	} +	 +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/StartEvent.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/StartEvent.java new file mode 100644 index 000000000..60175e09c --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/StartEvent.java @@ -0,0 +1,45 @@ +package at.gv.egovernment.moa.id.process.model; + +import java.io.Serializable; + +import org.apache.commons.collections4.CollectionUtils; + +/** + * Represents a start event. Each process description contains a single start event. Process execution starts with a + * start event. + *  + * @author tknall + *  + */ +public class StartEvent extends ProcessNode implements Serializable { + +	private static final long serialVersionUID = 1L; + +	@Override +	public String toString() { +		StringBuilder builder = new StringBuilder(); +		builder.append("StartEvent ["); +		if (getId() != null) { +			builder.append("id="); +			builder.append(getId()); +		} +		if (CollectionUtils.isNotEmpty(getIncomingTransitions())) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("incomingTransitions="); +			builder.append(getIncomingTransitions()); +		} +		if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("outgoingTransitions="); + +			builder.append(getOutgoingTransitions()); +		} +		builder.append("]"); +		return builder.toString(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/TaskInfo.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/TaskInfo.java new file mode 100644 index 000000000..78a9d6a0a --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/TaskInfo.java @@ -0,0 +1,94 @@ +package at.gv.egovernment.moa.id.process.model; + +import java.io.Serializable; + +import org.apache.commons.collections4.CollectionUtils; + +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * Represents information about a single task to be performed upon process execution. + * @author tknall + * + */ +public class TaskInfo extends ProcessNode implements Serializable { + +	private static final long serialVersionUID = 1L; +	private static final boolean DEFAULT_ASYNC = false; +	 +	private String taskImplementingClass; +	private boolean async = DEFAULT_ASYNC; +	 +	/** +	 * Determines if the task is marked asynchronous ({@code true}) or synchronous ({@code false}). +	 * @return A flag indicating if the task should be executed asynchronously or synchronously. (Default: {@code false}) +	 */ +	public boolean isAsync() { +		return async; +	} + +	/** +	 * Marks a task to executed asynchronously ({@code true}) or synchronously ({@code false}). +	 * @param async The flag. +	 */ +	public void setAsync(boolean async) { +		this.async = async; +	} + +	/** +	 * Returns the class that implements the actual task (must implement {@link Task}). +	 * @return The task implementing class. +	 */ +	public String getTaskImplementingClass() { +		return taskImplementingClass; +	} + +	/** +	 * Sets the class that implements the actual task (must implement {@link Task}). +	 * @param taskImplementingClass The task implementing class. +	 */ +	public void setTaskImplementingClass(String taskImplementingClass) { +		this.taskImplementingClass = taskImplementingClass; +	} + +	@Override +	public String toString() { +		StringBuilder builder = new StringBuilder(); +		if (getId() != null) { +			builder.append("id="); +			builder.append(getId()); +		} +		if (async != DEFAULT_ASYNC) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("async="); +			builder.append(async); +		} +		if (taskImplementingClass != null) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("taskImplementingClass="); +			builder.append(taskImplementingClass); +		} +		if (CollectionUtils.isNotEmpty(getIncomingTransitions())) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("incomingTransitions="); +			builder.append(getIncomingTransitions()); +		} +		if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("outgoingTransitions="); +			builder.append(getOutgoingTransitions()); +		} +		builder.insert(0, "TaskInfo ["); +		builder.append("]"); +		return builder.toString(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/Transition.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/Transition.java new file mode 100644 index 000000000..bc3005534 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/Transition.java @@ -0,0 +1,136 @@ +package at.gv.egovernment.moa.id.process.model; + +import java.io.Serializable; + +import at.gv.egovernment.moa.id.process.ProcessDefinitionParser; + +/** + * Represents a single transition from a {@link StartEvent} or {@linkplain TaskInfo Task} to another + * {@linkplain TaskInfo Task} or {@link EndEvent}. + *  + * @author tknall + *  + */ +public class Transition implements Serializable { + +	private static final long serialVersionUID = 1L; + +	private String id; +	private String conditionExpression; +	private ProcessNode from; +	private ProcessNode to; + +	/** +	 * Returns the process node (effectively a {@link StartEvent} or {@linkplain TaskInfo Task}) the transition is +	 * pointing from. +	 *  +	 * @return The transition's source process node (never {@code null} if transition comes from a process definition +	 *         from {@link ProcessDefinitionParser}). +	 */ +	public ProcessNode getFrom() { +		return from; +	} + +	/** +	 * Sets the process node the transition is pointing from. +	 *  +	 * @param from +	 *            The transition's source process node. +	 */ +	public void setFrom(ProcessNode from) { +		this.from = from; +	} + +	/** +	 * Returns the process node (effectively a {@linkplain TaskInfo Task} or {@link EndEvent}) the transition is +	 * pointing to. +	 *  +	 * @return The transition's destination process node (never {@code null} if transition comes from a process +	 *         definition from {@link ProcessDefinitionParser}). +	 */ +	public ProcessNode getTo() { +		return to; +	} + +	/** +	 * Sets the process node the transition is pointing to. +	 *  +	 * @param to +	 *            The transition's destination process node. +	 */ +	public void setTo(ProcessNode to) { +		this.to = to; +	} + +	/** +	 * Returns the unique identifier of the transition. +	 *  +	 * @return The unique identifier (may be {@code null}). +	 */ +	public String getId() { +		return id; +	} + +	/** +	 * Sets the unique identifier of the transition. +	 *  +	 * @param id +	 *            The unique identifier. +	 */ +	public void setId(String id) { +		this.id = id; +	} + +	/** +	 * Returns the condition expression for this transition. +	 *  +	 * @return The condition expression (may be {@code null}). +	 */ +	public String getConditionExpression() { +		return conditionExpression; +	} + +	/** +	 * Sets the condition expression for this transition. +	 *  +	 * @param conditionExpression +	 *            The condition expression. +	 */ +	public void setConditionExpression(String conditionExpression) { +		this.conditionExpression = conditionExpression; +	} + +	@Override +	public String toString() { +		StringBuilder builder = new StringBuilder(); +		if (id != null) { +			builder.append("id="); +			builder.append(id); +		} +		if (from != null) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("from.id="); +			builder.append(from.getId()); +		} +		if (to != null) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("to.id="); +			builder.append(to.getId()); +		} +		if (conditionExpression != null) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("conditionExpression="); +			builder.append(conditionExpression); +		} +		builder.insert(0, "Transition ["); +		builder.append("]"); +		return builder.toString(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/spring/SpringExpressionEvaluator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/spring/SpringExpressionEvaluator.java new file mode 100644 index 000000000..5b30c7172 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/spring/SpringExpressionEvaluator.java @@ -0,0 +1,61 @@ +package at.gv.egovernment.moa.id.process.spring; + +import java.util.Objects; + +import javax.annotation.PostConstruct; + +import org.apache.commons.lang3.BooleanUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.expression.BeanFactoryResolver; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; + +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext; +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator; +import at.gv.egovernment.moa.id.process.model.Transition; + +/** + * Expression evaluator for processing {@link Transition} conditions allowing to reference Spring beans from the + * application context. + *  + * @author tknall + *  + */ +public class SpringExpressionEvaluator implements ExpressionEvaluator { + +	private Logger log = LoggerFactory.getLogger(getClass()); +	private ExpressionParser parser = new SpelExpressionParser(); +	private StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); + +	@Autowired(required = false) +	private ApplicationContext ctx; + +	@PostConstruct +	private void init() { +		if (ctx != null) { +			evaluationContext.setBeanResolver(new BeanFactoryResolver(ctx)); +		} +	} + +	@Override +	public boolean evaluate(ExpressionEvaluationContext expressionContext, String expression) { +		Objects.requireNonNull(expression, "Expression must not be null."); +		log.trace("Evaluating '{}'.", expression); + +		Expression expr = parser.parseExpression(expression); +		Boolean result = expr.getValue(evaluationContext, expressionContext, Boolean.class); +		if (result == null) { +			log.warn("Evaluation of '{}' results in null-value.", expression); +		} else { +			log.debug("Expression '{}' -> {}", expression, result); +		} + +		return BooleanUtils.isTrue(result); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/AbstractAuthSourceServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/AbstractAuthSourceServlet.java new file mode 100644 index 000000000..738b58834 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/AbstractAuthSourceServlet.java @@ -0,0 +1,116 @@ +package at.gv.egovernment.moa.id.process.springweb; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.NoUniqueBeanDefinitionException; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +import at.gv.egovernment.moa.id.process.ProcessEngine; +import at.gv.egovernment.moa.id.process.ProcessInstance; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; + +/** + * Abstract HttpServlet that provides means for retrieving the process engine (Spring Web required) as well as + * retrieving the underlying process instance and execution context evaluating a certain request parameter. + *  + * @author tknall + *  + */ +public abstract class AbstractAuthSourceServlet extends HttpServlet { + +	private static final long serialVersionUID = 1L; + +	private ProcessEngine processEngine; +	 +	/** +	 * Returns the name of the request parameter representing the respective instance id. +	 * <p/>Default is {@code processInstanceId}. +	 * @return The request parameter name. +	 */ +	public String getProcessInstanceIdParameterName() { +		return "processInstanceId"; +	} + +	/** +	 * Returns the underlying process engine instance. +	 *  +	 * @return The process engine (never {@code null}). +	 * @throws NoSuchBeanDefinitionException +	 *             if no {@link ProcessEngine} bean was found. +	 * @throws NoUniqueBeanDefinitionException +	 *             if more than one {@link ProcessEngine} bean was found. +	 * @throws BeansException +	 *             if a problem getting the {@link ProcessEngine} bean occurred. +	 * @throws IllegalStateException +	 *             if the Spring WebApplicationContext was not found, which means that the servlet is used outside a +	 *             Spring web environment. +	 */ +	public synchronized ProcessEngine getProcessEngine() { +		if (processEngine == null) { +			WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); +			if (ctx == null) { +				throw new IllegalStateException( +						"Unable to find Spring WebApplicationContext. Servlet needs to be executed within a Spring web environment."); +			} +			processEngine = ctx.getBean(ProcessEngine.class); +		} +		return processEngine; +	} + +	/** +	 * Retrieves the process instance referenced by the request parameter {@link #getProcessInstanceIdParameterName()}. +	 *  +	 * @param request +	 *            The HttpServletRequest. +	 * @return The process instance (never {@code null}). +	 * @throws NoSuchBeanDefinitionException +	 *             if no {@link ProcessEngine} bean was found. +	 * @throws NoUniqueBeanDefinitionException +	 *             if more than one {@link ProcessEngine} bean was found. +	 * @throws BeansException +	 *             if a problem getting the {@link ProcessEngine} bean occurred. +	 * @throws IllegalStateException +	 *             if the Spring WebApplicationContext was not found, which means that the servlet is used outside a +	 *             Spring web environment. +	 * @throws IllegalArgumentException +	 *             in case the process instance id referenced by the request parameter +	 *             {@link #getProcessInstanceIdParameterName()} does not exist. +	 */ +	public ProcessInstance getProcessInstance(HttpServletRequest request) { +		String processInstanceId = StringUtils.trimToNull(request.getParameter(getProcessInstanceIdParameterName())); +		if (processInstanceId == null) { +			throw new IllegalArgumentException("Missing request parameter '" + getProcessInstanceIdParameterName() + "'."); +		} +		return getProcessEngine().getProcessInstance(processInstanceId); +	} + +	/** +	 * Retrieves the execution context for the respective process instance referenced by the request parameter +	 * {@link #getProcessInstanceIdParameterName()}. +	 *  +	 * @param request +	 *            The HttpServletRequest. +	 * @return The execution context (never {@code null}). +	 * @throws NoSuchBeanDefinitionException +	 *             if no {@link ProcessEngine} bean was found. +	 * @throws NoUniqueBeanDefinitionException +	 *             if more than one {@link ProcessEngine} bean was found. +	 * @throws BeansException +	 *             if a problem getting the {@link ProcessEngine} bean occurred. +	 * @throws IllegalStateException +	 *             if the Spring WebApplicationContext was not found, which means that the servlet is used outside a +	 *             Spring web environment. +	 * @throws IllegalArgumentException +	 *             in case the process instance id referenced by the request parameter +	 *             {@link #getProcessInstanceIdParameterName()} does not exist. +	 */ +	public ExecutionContext getExecutionContext(HttpServletRequest request) { +		return getProcessInstance(request).getExecutionContext(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/MoaIdTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/MoaIdTask.java new file mode 100644 index 000000000..bae6391ec --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/MoaIdTask.java @@ -0,0 +1,73 @@ +package at.gv.egovernment.moa.id.process.springweb; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.filter.RequestContextFilter; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * Abstract task implementation providing {@link HttpServletRequest} and {@link HttpServletResponse}. + * <p/> + * Note that this abstract task requires the Spring (web) framework including a {@link RequestContextFilter} to be set + * within {@code web.xml}. + *  + * <pre> + * ... + * <filter> + *   <filter-name>requestContextFilter</filter-name> + *   <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class> + * </filter> + * <filter-mapping> + *   <filter-name>requestContextFilter</filter-name> + *   <url-pattern>/*</url-pattern> + * </filter-mapping> + * ... + * </pre> + *  + * @author tknall + *  + */ +public abstract class MoaIdTask implements Task { + +	/** +	 * Executes the task providing the underlying {@link ExecutionContext} {@code executionContext} as well as the +	 * respective {@link HttpServletRequest} and {@link HttpServletResponse}. +	 *  +	 * @param executionContext +	 *            The execution context (never {@code null}). +	 * @param request +	 *            The HttpServletRequest (never {@code null}). +	 * @param response +	 *            The HttpServletResponse (never {@code null}). +	 * @throws IllegalStateException +	 *             Thrown in case the task is nur being run within the required environment. Refer to javadoc for +	 *             further information. +	 * @throws Exception +	 *             Thrown in case of error executing the task. +	 */ +	public abstract void execute(ExecutionContext executionContext, HttpServletRequest request, +			HttpServletResponse response) throws Exception; + +	@Override +	public void execute(ExecutionContext executionContext) throws Exception { +		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); +		if (requestAttributes != null && requestAttributes instanceof ServletRequestAttributes) { +			HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); +			HttpServletResponse response = ((ServletRequestAttributes) requestAttributes).getResponse(); +			if (request == null || response == null) { +				throw new IllegalStateException( +						"Spring's RequestContextHolder did not provide HttpServletResponse. Did you forget to set the required org.springframework.web.filter.RequestContextFilter in your web.xml."); +			} +			execute(executionContext, request, response); +		} else { +			throw new IllegalStateException("Task needs to be executed within a Spring web environment."); +		} +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/SpringWebExpressionEvaluator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/SpringWebExpressionEvaluator.java new file mode 100644 index 000000000..499e86fa0 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/SpringWebExpressionEvaluator.java @@ -0,0 +1,138 @@ +package at.gv.egovernment.moa.id.process.springweb; + +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.expression.BeanFactoryResolver; +import org.springframework.expression.Expression; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; + +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext; +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator; +import at.gv.egovernment.moa.id.process.model.Transition; + +/** + * Expression evaluator for processing {@link Transition} conditions allowing to + * <ul> + * <li>reference Spring beans from the application context using {@code @myBeanName...},</li> + * <li>{@link ExecutionContext} properties using {@code ctx['property']},</li> + * <li>Multi valued {@link HttpServletRequest} parameters using {@code requestParameters['foo']} (keep in mind that this + * expression returns an array of String values) and</li> + * <li>Single valued {@link HttpServletRequest} parameters using {@code requestParameter['foo']}</li> + * </ul> + *  + * @author tknall + *  + */ +public class SpringWebExpressionEvaluator implements ExpressionEvaluator { + +	private Logger log = LoggerFactory.getLogger(getClass()); +	private ExpressionParser parser = new SpelExpressionParser(); +	private StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); + +	@Autowired(required = false) +	private ApplicationContext ctx; + +	@Autowired(required = false) +	private HttpServletRequest request; + +	@PostConstruct +	private void init() { +		if (ctx != null) { +			evaluationContext.setBeanResolver(new BeanFactoryResolver(ctx)); +		} +	} + +	/** +	 * Evaluation context that provides access to {@link HttpServletRequest} parameters using +	 * {@code requestParameter['foo']} for single value parameters or {@code requestParameters['foo']} for multi value +	 * parameters. Basic calls to {@code ctx} will be delegated. +	 *  +	 * @author tknall +	 *  +	 */ +	private class SpringWebExpressionEvaluationContext implements ExpressionEvaluationContext { + +		private static final long serialVersionUID = 1L; + +		/** +		 * Creates a new expression evaluation context, providing access to HttpServletRequest parameter(s). +		 *  +		 * @param delegate +		 *            The original {@link ExpressionEvaluationContext} to be delegated to for {@code ctx['foo']} +		 *            expressions. +		 */ +		public SpringWebExpressionEvaluationContext(ExpressionEvaluationContext delegate) { +			this.delegate = delegate; +		} + +		private ExpressionEvaluationContext delegate; + +		@Override +		public Map<String, Serializable> getCtx() { +			return delegate.getCtx(); +		} + +		@SuppressWarnings("unused") +		public Map<String, String> getRequestParameter() { +			if (request != null) { +				Map<String, String> singleValueMap = new HashMap<String, String>(); +				Iterator<Entry<String, String[]>> it = request.getParameterMap().entrySet().iterator(); +				while (it.hasNext()) { +					Entry<String, String[]> entry = it.next(); +					if (ArrayUtils.isNotEmpty(entry.getValue())) { +						singleValueMap.put(entry.getKey(), entry.getValue()[0]); +					} +				} +				return singleValueMap; +			} else { +				return Collections.<String, String> emptyMap(); +			} +		} + +		@SuppressWarnings("unused") +		public Map<String, String[]> getRequestParameters() { +			if (request != null) { +				return request.getParameterMap(); +			} else { +				return Collections.<String, String[]> emptyMap(); +			} +		} + +	} + +	@Override +	public boolean evaluate(ExpressionEvaluationContext expressionContext, String expression) { +		Objects.requireNonNull(expression, "Expression must not be null."); +		log.trace("Evaluating '{}'.", expression); + +		Expression expr = parser.parseExpression(expression); +		Boolean result = expr.getValue(evaluationContext, new SpringWebExpressionEvaluationContext(expressionContext), +				Boolean.class); +		if (result == null) { +			log.warn("Evaluation of '{}' results in null-value.", expression); +		} else { +			log.debug("Expression '{}' -> {}", expression, result); +		} + +		return BooleanUtils.isTrue(result); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/support/SecureRandomHolder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/support/SecureRandomHolder.java new file mode 100644 index 000000000..72677739a --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/support/SecureRandomHolder.java @@ -0,0 +1,35 @@ +package at.gv.egovernment.moa.id.process.support; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +/** + * Holder for a secure random instance following the initialization on demand holder design pattern. The secure random + * instance is a singleton that is initialized on first usage. + *  + * @author tknall + *  + */ +public class SecureRandomHolder { + +	private SecureRandomHolder() { +	} + +	private static final SecureRandom SRND_INSTANCE; +	static { +		try { +			SRND_INSTANCE = SecureRandom.getInstance("SHA1PRNG"); +		} catch (NoSuchAlgorithmException e) { +			throw new RuntimeException("Unable to instantiate SHA1PRNG.", e); +		} +	} + +	/** +	 * Returns a secure random generator instance. +	 * @return The secure random instance. +	 */ +	public static SecureRandom getInstance() { +		return SecureRandomHolder.SRND_INSTANCE; +	} + +}
\ No newline at end of file diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/loginFormFull.html b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/loginFormFull.html index 3eff06daf..5ae76ed96 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/loginFormFull.html +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/loginFormFull.html @@ -842,7 +842,7 @@ input {  				src="#CONTEXTPATH#/img/valid-html5-blue.png" alt="HTML5 ist valide!" />  			</a> <a href="http://jigsaw.w3.org/css-validator/"> <img  				style="border: 0; width: 88px; height: 31px" -				src="http://jigsaw.w3.org/css-validator/images/vcss-blue" +				src="https://jigsaw.w3.org/css-validator/images/vcss-blue"  				alt="CSS ist valide!" />  			</a>  		</div> diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java index a9f5ed60a..4288f48ad 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java @@ -48,6 +48,7 @@ import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;  import at.gv.egovernment.moa.id.data.EncryptedData;  import at.gv.egovernment.moa.id.data.SLOInformationInterface;  import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAOImpl;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionAttributeExtractorExeption;  import at.gv.egovernment.moa.id.protocols.pvp2x.utils.AssertionAttributeExtractor;  import at.gv.egovernment.moa.id.util.Random; @@ -912,19 +913,28 @@ public class AuthenticationSessionStoreage {  	} -	private static void cleanDelete(AuthenticatedSessionStore result) {		 +	private static void cleanDelete(AuthenticatedSessionStore result) { + +		try { +			AuthenticationSession session = getSession(result.getSessionid()); +			if (session.getProcessInstanceId() != null) { +				ProcessInstanceStoreDAOImpl.getInstance().remove(session.getProcessInstanceId()); +			} + +		} catch (MOADatabaseException e) { +			Logger.warn("Removing process associated with moa session " + result.getSessionid() + " FAILED.", e); +		} +  		try {  			result.setSession("blank".getBytes());  			MOASessionDBUtils.saveOrUpdate(result); -			 +  		} catch (MOADatabaseException e) {  			Logger.warn("Blank authenticated session with sessionID=" + result.getSessionid() + " FAILED.", e); -			 +  		} finally {  			if (!MOASessionDBUtils.delete(result)) -				Logger.error("Authenticated session with sessionID=" + result.getSessionid()  -							+ " not removed! (Error during Database communication)"); -			 +				Logger.error("Authenticated session with sessionID=" + result.getSessionid() + " not removed! (Error during Database communication)");  		}  	} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ServletUtils.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ServletUtils.java index 56e59a4aa..3dbc0ab7b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ServletUtils.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ServletUtils.java @@ -113,14 +113,13 @@ public class ServletUtils {     * depending on the requests starting text.
     * 
     * @param resp The httpServletResponse
 -   * @param session The current AuthenticationSession
     * @param createXMLSignatureRequestOrRedirect The request
     * @param servletGoal The servlet to which the redirect should happen
     * @param servletName The servlet name for debug purposes
     * @throws MOAIDException
     * @throws IOException
     */
 -  public static void writeCreateXMLSignatureRequest(HttpServletResponse resp, AuthenticationSession session, String createXMLSignatureRequestOrRedirect, String servletGoal, String servletName, String dataURL) 
 +  public static void writeCreateXMLSignatureRequest(HttpServletResponse resp, String createXMLSignatureRequestOrRedirect, String servletGoal, String servletName, String dataURL) 
    throws MOAIDException,
           IOException
    { 
 diff --git a/id/server/idserverlib/src/main/java/iaik/IAIKRuntimeException.java b/id/server/idserverlib/src/main/java/iaik/IAIKRuntimeException.java new file mode 100644 index 000000000..968d3491d --- /dev/null +++ b/id/server/idserverlib/src/main/java/iaik/IAIKRuntimeException.java @@ -0,0 +1,18 @@ +package iaik;
 +
 +/**
 + * Adapter class providing {@code iaik.RuntimeException} for libraries that have not been updated in order to consider
 + * the fact that the class {@code IAIKRuntimeException} has been moved.
 + * 
 + * @author tknall
 + * 
 + */
 +public class IAIKRuntimeException extends iaik.server.modules.IAIKRuntimeException {
 +
 +	private static final long serialVersionUID = 1L;
 +
 +	public IAIKRuntimeException(String reason, Throwable wrapped, String uniqueIdentifier) {
 +		super(reason, wrapped, uniqueIdentifier);
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.auth.modules.AuthModule b/id/server/idserverlib/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.auth.modules.AuthModule new file mode 100644 index 000000000..865096055 --- /dev/null +++ b/id/server/idserverlib/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.auth.modules.AuthModule @@ -0,0 +1,2 @@ +# The default moaid process +at.gv.egovernment.moa.id.auth.modules.internal.DefaultAuthModuleImpl diff --git a/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthentication.process.xml b/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthentication.process.xml new file mode 100644 index 000000000..3860ddef4 --- /dev/null +++ b/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthentication.process.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?>
 +<pd:ProcessDefinition id="DefaultAuthentication" xmlns:pd="http://reference.e-government.gv.at/namespace/moa/process/definition/v1">
 +
 +<!--
 +	- National authentication with Austrian Citizen Card and mobile signature with our without mandate.
 +	- Legacy authentication for foreign citizens using MOCCA supported signature cards.
 +-->
 +	<pd:Task id="createIdentityLinkForm"    class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.CreateIdentityLinkFormTask" />
 +	<pd:Task id="verifyIdentityLink"        class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.VerifyIdentityLinkTask"        async="true" />
 +	<pd:Task id="verifyAuthBlock"           class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.VerifyAuthenticationBlockTask" async="true" />
 +	<pd:Task id="verifyCertificate"         class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.VerifyCertificateTask"         async="true" />
 +	<pd:Task id="getMISSessionID"           class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.GetMISSessionIDTask"           async="true" />
 +	<pd:Task id="certificateReadRequest"    class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.CertificateReadRequestTask" />
 +	<pd:Task id="prepareAuthBlockSignature" class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.PrepareAuthBlockSignatureTask" />
 +	<pd:Task id="getForeignID"              class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.GetForeignIDTask"              async="true" />
 +
 +	<!-- Process is triggered either by GenerateIFrameTemplateServlet (upon bku selection) or by AuthenticationManager (upon legacy authentication start using legacy parameters. -->
 +	<pd:StartEvent id="start" />
 +	
 +	<pd:Transition from="start"                     to="createIdentityLinkForm" />
 +	
 +	<pd:Transition from="createIdentityLinkForm"    to="verifyIdentityLink" />
 +	
 +	<pd:Transition from="verifyIdentityLink"        to="certificateReadRequest" conditionExpression="!ctx['identityLinkAvailable'] || ctx['useMandate']" />
 +	<pd:Transition from="verifyIdentityLink"        to="prepareAuthBlockSignature" />
 +	
 +	<pd:Transition from="prepareAuthBlockSignature" to="verifyAuthBlock" />
 +	<!-- Note: verifyAuthBlock still creates a MIS session and redirects the user to the MIS gui. This should be separated from the auth block verification. -->
 +	
 +	<pd:Transition from="certificateReadRequest"    to="verifyCertificate" />
 +	<!-- Note: verifyCertificate still creates the auth block to be signed which should be separated from certificat verification. -->
 +	
 +	<pd:Transition from="verifyCertificate"         to="verifyAuthBlock" conditionExpression="ctx['useMandate']" />
 +	<pd:Transition from="verifyCertificate"         to="getForeignID" />
 +	
 +	<pd:Transition from="verifyAuthBlock"           to="getMISSessionID" conditionExpression="ctx['useMandate']" />
 +	<pd:Transition from="verifyAuthBlock"           to="end" />
 +	
 +	<pd:Transition from="getMISSessionID"           to="end" />
 +	<pd:Transition from="getForeignID"              to="end" />
 +	
 +	<pd:EndEvent id="end" />
 +
 +</pd:ProcessDefinition>
 diff --git a/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd b/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd new file mode 100644 index 000000000..d6ab7ae46 --- /dev/null +++ b/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" +	targetNamespace="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	elementFormDefault="qualified" version="1.0"> + +	<xsd:element name="ProcessDefinition"> +		<xsd:complexType> +			<xsd:sequence> +				<xsd:choice minOccurs="0" maxOccurs="unbounded"> +					<xsd:element name="StartEvent" type="tns:StartEventType" /> +					<xsd:element name="Task" type="tns:TaskType" /> +					<xsd:element name="Transition" type="tns:TransitionType" /> +					<xsd:element name="EndEvent" type="tns:EndEventType" /> +				</xsd:choice> +			</xsd:sequence> +			<xsd:attribute name="id" type="xsd:ID" use="required" /> +		</xsd:complexType> +	</xsd:element> + +	<xsd:complexType name="ProcessNodeType" abstract="true"> +		<xsd:attribute name="id" type="xsd:ID" use="required" /> +	</xsd:complexType> + +	<xsd:complexType name="StartEventType"> +		<xsd:complexContent> +			<xsd:extension base="tns:ProcessNodeType" /> +		</xsd:complexContent> +	</xsd:complexType> + +	<xsd:complexType name="TransitionType"> +		<xsd:attribute name="from" type="xsd:IDREF" use="required" /> +		<xsd:attribute name="to" type="xsd:IDREF" use="required" /> +		<xsd:attribute name="id" type="xsd:ID" /> +		<xsd:attribute name="conditionExpression" type="xsd:string" /> +	</xsd:complexType> + +	<xsd:complexType name="EndEventType"> +		<xsd:complexContent> +			<xsd:extension base="tns:ProcessNodeType" /> +		</xsd:complexContent> +	</xsd:complexType> + +	<xsd:complexType name="TaskType"> +		<xsd:complexContent> +			<xsd:extension base="tns:ProcessNodeType"> +				<xsd:attribute name="async" type="xsd:boolean" default="false"/> +				<xsd:attribute name="class" type="xsd:string" /> +			</xsd:extension> +		</xsd:complexContent> +	</xsd:complexType> + +</xsd:schema> diff --git a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties index 8fda4566c..ad01644a1 100644 --- a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties +++ b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties @@ -229,6 +229,9 @@ stork.18=STORK-SAML Engine konnte nicht initialisiert werden.  stork.19=Das erforderliche Attribut ist f\u00FCr naturliche Personen nicht vorhanden\: {0}
  stork.20=Fehler bei der Datenkonversion - eingegebens Datum fehlerhaft
  stork.21=Der angeforderte QAA-level {0} ist h\u00F6her als der QAA-level der Authentifizierung {1}
 +stork.22=Der STORK Authentifizierung erfordert die Auswahl des Herkunftslandes der Betroffenen.
 +stork.23=Die STORK Authentifizierung f\u00FCr "{0}" wird nicht unterst\u00FCtzt.
 +stork.24=Die STORK Authentifizierungsantwort enth\uFFFDlt leere Angaben zum Geschlecht.
  pvp2.00={0} ist kein gueltiger consumer service index
  pvp2.01=Fehler beim kodieren der PVP2 Antwort
 @@ -266,4 +269,7 @@ oauth20.09=Zertifikat fuer JSON Web-Token ist falsch konfiguriert. Fehler bei "{  slo.00=Sie konnten erfolgreich von allen Online-Applikation abgemeldet werden.
  slo.01=Sie konnten NICHT erfolgreich von allen Online-Applikationen abgemeldet werden\!<BR>Bitte schlie\u00DFen Sie aus sicherheitsgr\u00FCnden Ihren Browser.
 -slo.02=Es wurde keine aktive SSO Session gefunden oder Sie sind bei keiner Online-Applikation angemeldet.
\ No newline at end of file +slo.02=Es wurde keine aktive SSO Session gefunden oder Sie sind bei keiner Online-Applikation angemeldet.
 +
 +process.01=Fehler beim Ausf\u00FChren des Prozesses.
 +process.02=Fehler beim Erstellen eines geeigneten Prozesses f\u00FCr die SessionID {0}.
 diff --git a/id/server/idserverlib/src/main/resources/resources/templates/loginFormFull.html b/id/server/idserverlib/src/main/resources/resources/templates/loginFormFull.html index 7e2ddc491..e293d8456 100644 --- a/id/server/idserverlib/src/main/resources/resources/templates/loginFormFull.html +++ b/id/server/idserverlib/src/main/resources/resources/templates/loginFormFull.html @@ -837,7 +837,7 @@  				src="#CONTEXTPATH#/img/valid-html5-blue.png" alt="HTML5 ist valide!" />  			</a> <a href="http://jigsaw.w3.org/css-validator/"> <img  				style="border: 0; width: 88px; height: 31px" -				src="http://jigsaw.w3.org/css-validator/images/vcss-blue" +				src="https://jigsaw.w3.org/css-validator/images/vcss-blue"  				alt="CSS ist valide!" />  			</a>  		</div> diff --git a/id/server/idserverlib/src/main/resources/resources/templates/sendAssertionFormFull.html b/id/server/idserverlib/src/main/resources/resources/templates/sendAssertionFormFull.html index e75bef70c..033a574b9 100644 --- a/id/server/idserverlib/src/main/resources/resources/templates/sendAssertionFormFull.html +++ b/id/server/idserverlib/src/main/resources/resources/templates/sendAssertionFormFull.html @@ -545,7 +545,7 @@ button:hover,button:focus,button:active,.sendButton:hover,.sendButton:focus,.sen  				src="#CONTEXTPATH#/img/valid-html5-blue.png" alt="HTML5 ist valide!" />  			</a> <a href="http://jigsaw.w3.org/css-validator/"> <img  				style="border: 0; width: 88px; height: 31px" -				src="http://jigsaw.w3.org/css-validator/images/vcss-blue" +				src="https://jigsaw.w3.org/css-validator/images/vcss-blue"  				alt="CSS ist valide!" />  			</a>  		</div> diff --git a/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html b/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html index b241e85cf..8976b2bd6 100644 --- a/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html +++ b/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html @@ -436,7 +436,7 @@  				src="$contextpath/img/valid-html5-blue.png" alt="HTML5 ist valide!" />  			</a> <a href="http://jigsaw.w3.org/css-validator/"> <img  				style="border: 0; width: 88px; height: 31px" -				src="http://jigsaw.w3.org/css-validator/images/vcss-blue" +				src="https://jigsaw.w3.org/css-validator/images/vcss-blue"  				alt="CSS ist valide!" />  			</a>  		</div> diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/ExpressionContextAdapter.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/ExpressionContextAdapter.java new file mode 100644 index 000000000..c26236619 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/ExpressionContextAdapter.java @@ -0,0 +1,52 @@ +package at.gv.egovernment.moa.id.process.spring.test; + + +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext; + +/** + * Adapter class for {@link ExpressionEvaluationContext}. Intended to be used for testing purposes. + *  + * @author tknall + *  + */ +public class ExpressionContextAdapter implements ExpressionEvaluationContext { + +	private static final long serialVersionUID = 1L; + +	private Map<String, Serializable> ctxData = Collections.synchronizedMap(new HashMap<String, Serializable>()); + +	/** +	 * Returns a certain {@link Serializable} object associated with a certain {@code key}. +	 *  +	 * @param key +	 *            The key. +	 * @return The object or {@code null} if no object was found stored with that key or if a {@code null} value was +	 *         stored. +	 */ +	Serializable get(String key) { +		return ctxData.get(key); +	} + +	/** +	 * Stores a {@link Serializable} with a certain {@code key}. +	 *  +	 * @param key +	 *            The key. +	 * @param object +	 *            The object. +	 */ +	void put(String key, Serializable object) { +		ctxData.put(key, object); +	} + +	@Override +	public Map<String, Serializable> getCtx() { +		return Collections.unmodifiableMap(ctxData); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SimplePojo.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SimplePojo.java new file mode 100644 index 000000000..89f3c0383 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SimplePojo.java @@ -0,0 +1,41 @@ +package at.gv.egovernment.moa.id.process.spring.test; + +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator; + +/** + * A dummy pojo used to test {@link ExpressionEvaluator} with Spring EL referencing Spring beans. + *  + * @author tknall + *  + */ +public class SimplePojo { + +	private Boolean booleanValue; +	private String stringValue; +	private Integer integerValue; + +	public Boolean getBooleanValue() { +		return booleanValue; +	} + +	public void setBooleanValue(Boolean booleanValue) { +		this.booleanValue = booleanValue; +	} + +	public String getStringValue() { +		return stringValue; +	} + +	public void setStringValue(String stringValue) { +		this.stringValue = stringValue; +	} + +	public Integer getIntegerValue() { +		return integerValue; +	} + +	public void setIntegerValue(Integer integerValue) { +		this.integerValue = integerValue; +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionAwareProcessEngineTest.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionAwareProcessEngineTest.java new file mode 100644 index 000000000..5355f14d3 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionAwareProcessEngineTest.java @@ -0,0 +1,116 @@ +package at.gv.egovernment.moa.id.process.spring.test; + +import static at.gv.egovernment.moa.id.process.ProcessInstanceState.*; +import static org.junit.Assert.*; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.hibernate.cfg.Configuration; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils; +import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; +import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.process.ProcessDefinitionParserException; +import at.gv.egovernment.moa.id.process.ProcessEngine; +import at.gv.egovernment.moa.id.process.ProcessEngineImpl; +import at.gv.egovernment.moa.id.process.ProcessExecutionException; +import at.gv.egovernment.moa.id.process.ProcessInstance; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStore; +import at.gv.egovernment.moa.id.process.spring.SpringExpressionEvaluator; + +/** + * Tests the process engine using processes based on Spring EL referencing the process context and further Spring beans. + *  + * @author tknall + *  + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class SpringExpressionAwareProcessEngineTest { + +	 +	private static ProcessEngine pe; + +	@BeforeClass +	public static void init() throws IOException, ProcessDefinitionParserException { + +		pe = new ProcessEngineImpl(); +		((ProcessEngineImpl) pe).setTransitionConditionExpressionEvaluator(new SpringExpressionEvaluator()); +		try (InputStream in = SpringExpressionAwareProcessEngineTest.class.getResourceAsStream("SampleProcessDefinitionWithExpression1.xml")) { +			((ProcessEngineImpl) pe).registerProcessDefinition(in); +		} +		try (InputStream in = SpringExpressionAwareProcessEngineTest.class.getResourceAsStream("SampleProcessDefinitionForSAML1Authentication.xml")) { +			((ProcessEngineImpl) pe).registerProcessDefinition(in); +		} + +		initHibernateForTesting(); +	} + +	private static void initHibernateForTesting() throws IOException{ + +		InputStream in = SpringExpressionAwareProcessEngineTest.class.getResourceAsStream("/at/gv/egovernment/moa/id/process/hibernate.configuration.test.properties"); +		Properties props = new Properties(); +		props.load(in); + +		try { +			ConfigurationDBUtils.initHibernate(props); +			Configuration config = new Configuration(); +			config.addProperties(props); +			config.addAnnotatedClass(ProcessInstanceStore.class); +			config.addAnnotatedClass(InterfederationSessionStore.class); +			MOASessionDBUtils.initHibernate(config, props); +		} catch (MOADatabaseException e) { +			e.printStackTrace(); +		} +	} + + +	@Test +	public void testSampleProcessDefinitionWithExpression1() throws IOException, ProcessDefinitionParserException, ProcessExecutionException { + +		String piId = pe.createProcessInstance("SampleProcessWithExpression1"); +		ProcessInstance pi = pe.getProcessInstance(piId); +		assertEquals(NOT_STARTED, pi.getState()); +		 +		 +		// start process +		pe.start(piId); +		pi = pe.getProcessInstance(piId); +		assertEquals(ENDED, pi.getState()); +	} + +	@Test +	public void testSampleProcessDefinitionForSAML1Authentication() throws IOException, ProcessDefinitionParserException, ProcessExecutionException { + +		String piId = pe.createProcessInstance("SampleProcessDefinitionForSAML1Authentication"); +		ProcessInstance pi = pe.getProcessInstance(piId); +		assertEquals(NOT_STARTED, pi.getState()); + +		// start process +		pe.start(piId); +		pi = pe.getProcessInstance(piId); +		assertEquals(ENDED, pi.getState()); + +		pi = pe.getProcessInstance(piId); +		ExecutionContext ec = pi.getExecutionContext(); +		assertNotNull(ec); +		System.out.println(ec.keySet()); + +		assertNotNull(ec.get("bkuURL")); +		assertNotNull(ec.get("IdentityLink")); +		assertNotNull(ec.get("isIdentityLinkValidated")); +		assertNotNull(ec.get("SignedAuthBlock")); +		assertNotNull(ec.get("isSignedAuthBlockValidated")); +		assertNotNull(ec.get("SAML1Assertion")); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionEvaluatorTest.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionEvaluatorTest.java new file mode 100644 index 000000000..bc9d1d399 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionEvaluatorTest.java @@ -0,0 +1,54 @@ +package at.gv.egovernment.moa.id.process.spring.test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator; + +/** + * Tests the {@link ExpressionEvaluator} using a Spring EL based implementation capable of dereferencing Spring beans. + *  + * @author tknall + *  + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class SpringExpressionEvaluatorTest { + +	private ExpressionContextAdapter ctx; + +	@Autowired +	private ExpressionEvaluator expressionEvaluator; + +	@Before +	public void prepareTest() { +		ctx = new ExpressionContextAdapter(); +	} + +	@Test +	public void testEvaluateSimpleExpression() { +		assertTrue(expressionEvaluator.evaluate(ctx, "'true'")); +	} + +	@Test +	public void testEvaluateExpressionWithCtx() { +		ctx.put("myProperty", false); +		assertFalse(expressionEvaluator.evaluate(ctx, "ctx['myProperty']")); +	} + +	@Test +	public void testEvaluateExpressionWithBeanReference() { +		assertTrue(expressionEvaluator.evaluate(ctx, "@simplePojo.booleanValue")); +		assertTrue(expressionEvaluator.evaluate(ctx, "'HelloWorld'.equals(@simplePojo.stringValue)")); +		assertTrue(expressionEvaluator.evaluate(ctx, "@simplePojo.integerValue == 42")); +		assertTrue(expressionEvaluator.evaluate(ctx, "@simplePojo.stringValue.length() == 10")); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/CreateSAML1AssertionTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/CreateSAML1AssertionTask.java new file mode 100644 index 000000000..7e56071bd --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/CreateSAML1AssertionTask.java @@ -0,0 +1,54 @@ +package at.gv.egovernment.moa.id.process.spring.test.task; + +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Objects; + +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * A dummy task simulating the creation of a SAML1 assertion. + * <p> + * Requires context data: + * <ul> + * <li>{@code IdentityLink}</li> + * <li>{@code isIdentityLinkValidated}</li> + * <li>{@code SignedAuthBlock}</li> + * <li>{@code isSignedAuthBlockValidated}</li> + * </ul> + * </p> + * <p> + * Enriches context data with: + * <ul> + * <li>{@code SAML1Assertion}</li> + * </ul> + * </p> + *  + * @author tknall + *  + */ +public class CreateSAML1AssertionTask implements Task { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	@Override +	public void execute(ExecutionContext executionContext) throws Exception { +		Objects.requireNonNull(executionContext.get("IdentityLink")); +		assert (Boolean.TRUE.equals(Objects.requireNonNull(executionContext.get("isIdentityLinkValidated")))); +		Objects.requireNonNull(executionContext.get("SignedAuthBlock")); +		assert (Boolean.TRUE.equals(Objects.requireNonNull(executionContext.get("isSignedAuthBlockValidated")))); + +		log.debug("Using IdentityLink and signed auth block in order to create SAML1 assertion."); + +		try (InputStream in = getClass().getResourceAsStream("SAML1Assertion.xml")) { +			executionContext.put("SAML1Assertion", IOUtils.toString(in, Charset.forName("UTF-8"))); +		} + +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/GetIdentityLinkTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/GetIdentityLinkTask.java new file mode 100644 index 000000000..412fb0123 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/GetIdentityLinkTask.java @@ -0,0 +1,50 @@ +package at.gv.egovernment.moa.id.process.spring.test.task; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Objects; + +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * A dummy task simulating the retrieval of an IdentityLink. + * <p/> + * Asynchonous + * <p> + * Requires context data: + * <ul> + * <li>{@code bkuURL}</li> + * </ul> + * </p> + * <p> + * Enriches context data with: + * <ul> + * <li>{@code IdentityLink}</li> + * </ul> + * </p> + *  + * @author tknall + *  + */ +public class GetIdentityLinkTask implements Task { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	@Override +	public void execute(ExecutionContext executionContext) throws IOException { +		Objects.requireNonNull(executionContext.get("bkuURL")); + +		log.debug("Using bkuURL in order to retrieve IdentityLink."); + +		try (InputStream in = getClass().getResourceAsStream("IdentityLink_Max_Mustermann.xml")) { +			executionContext.put("IdentityLink", IOUtils.toString(in, Charset.forName("UTF-8"))); +		} +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/SelectBKUTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/SelectBKUTask.java new file mode 100644 index 000000000..54195ec91 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/SelectBKUTask.java @@ -0,0 +1,33 @@ +package at.gv.egovernment.moa.id.process.spring.test.task; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * A dummy task simulating a bku selection. + * <p/> + * Asynchonous + * <p> + * Enriches context data with: + * <ul> + * <li>{@code bkuURL}</li> + * </ul> + * </p> + *  + * @author tknall + *  + */ +public class SelectBKUTask implements Task { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	@Override +	public void execute(ExecutionContext executionContext) { +		log.debug("Providing BKU selection."); +		executionContext.put("bkuURL", "https://127.0.0.1:3496/https-security-layer-request"); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/SignAuthBlockTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/SignAuthBlockTask.java new file mode 100644 index 000000000..8099c0f98 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/SignAuthBlockTask.java @@ -0,0 +1,52 @@ +package at.gv.egovernment.moa.id.process.spring.test.task; + +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Objects; + +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * A dummy task simulating the signature of an auth block. + * <p/> + * Asynchonous + * <p> + * Requires context data: + * <ul> + * <li>{@code IdentityLink}</li> + * <li>{@code isIdentityLinkValidated}</li> + * <li>{@code bkuURL}</li> + * </ul> + * </p> + * <p> + * Enriches context data with: + * <ul> + * <li>{@code SignedAuthBlock}</li> + * </ul> + * </p> + *  + * @author tknall + *  + */ +public class SignAuthBlockTask implements Task { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	@Override +	public void execute(ExecutionContext executionContext) throws Exception { +		Objects.requireNonNull(executionContext.get("IdentityLink")); +		assert (Boolean.TRUE.equals(Objects.requireNonNull(executionContext.get("isIdentityLinkValidated")))); +		Objects.requireNonNull(executionContext.get("bkuURL")); + +		log.debug("Using validated IdentityLink and bkuURL in order to sign auth block."); +		try (InputStream in = getClass().getResourceAsStream("SignedAuthBlock.xml")) { +			executionContext.put("SignedAuthBlock", IOUtils.toString(in, Charset.forName("UTF-8"))); +		} +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/ValidateIdentityLinkTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/ValidateIdentityLinkTask.java new file mode 100644 index 000000000..a8e7df3d7 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/ValidateIdentityLinkTask.java @@ -0,0 +1,42 @@ +package at.gv.egovernment.moa.id.process.spring.test.task; + +import java.util.Objects; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * Dummy task simulating the validation of an IdentityLink. + * <p> + * Requires context data: + * <ul> + * <li>{@code IdentityLink}</li> + * </ul> + * </p> + * <p> + * Enriches context data with: + * <ul> + * <li>{@code isIdentityLinkValidated}</li> + * </ul> + * </p> + *  + * @author tknall + *  + */ +public class ValidateIdentityLinkTask implements Task { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	@Override +	public void execute(ExecutionContext executionContext) { +		Objects.requireNonNull(executionContext.get("IdentityLink")); + +		log.debug("Validating IdentityLink."); + +		executionContext.put("isIdentityLinkValidated", true); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/ValidateSignedAuthBlockTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/ValidateSignedAuthBlockTask.java new file mode 100644 index 000000000..07b2ea69c --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/ValidateSignedAuthBlockTask.java @@ -0,0 +1,46 @@ +package at.gv.egovernment.moa.id.process.spring.test.task; + +import java.util.Objects; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * A dummy task simulating the validation of an auth block. + * <p> + * Requires context data: + * <ul> + * <li>{@code IdentityLink}</li> + * <li>{@code isIdentityLinkValidated}</li> + * <li>{@code SignedAuthBlock}</li> + * </ul> + * </p> + * <p> + * Enriches context data with: + * <ul> + * <li>{@code isSignedAuthBlockValidated}</li> + * </ul> + * </p> + *  + * @author tknall + *  + */ +public class ValidateSignedAuthBlockTask implements Task { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	@Override +	public void execute(ExecutionContext executionContext) throws Exception { +		Objects.requireNonNull(executionContext.get("IdentityLink")); +		assert (Boolean.TRUE.equals(Objects.requireNonNull(executionContext.get("isIdentityLinkValidated")))); +		Objects.requireNonNull(executionContext.get("SignedAuthBlock")); + +		log.debug("Using validated IdentityLink and signed auth block in order to validate signed auth block."); + +		executionContext.put("isSignedAuthBlockValidated", true); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/BooleanStringExpressionEvaluator.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/BooleanStringExpressionEvaluator.java new file mode 100644 index 000000000..20dfc50ef --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/BooleanStringExpressionEvaluator.java @@ -0,0 +1,24 @@ +package at.gv.egovernment.moa.id.process.test; + +import java.util.Objects; + +import org.apache.commons.lang3.BooleanUtils; + +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext; +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator; + +/** + * Expression evaluator that guesses the boolean value from a String. Refer to {@link BooleanUtils#toBoolean(String)} + * for further information. + *  + * @author tknall + *  + */ +public class BooleanStringExpressionEvaluator implements ExpressionEvaluator { + +	@Override +	public boolean evaluate(ExpressionEvaluationContext expressionContext, String expression) { +		return BooleanUtils.toBoolean(Objects.requireNonNull(expression, "Expression must not be null.")); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/HalloWeltTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/HalloWeltTask.java new file mode 100644 index 000000000..d05200ee8 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/HalloWeltTask.java @@ -0,0 +1,19 @@ +package at.gv.egovernment.moa.id.process.test; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * Simple task that just outputs a "Hallo World" text to the console. + *  + * @author tknall + *  + */ +public class HalloWeltTask implements Task { + +	@Override +	public void execute(ExecutionContext executionContext) { +		System.out.println("Hallo Welt"); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/HelloWorldTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/HelloWorldTask.java new file mode 100644 index 000000000..e79bb8198 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/HelloWorldTask.java @@ -0,0 +1,19 @@ +package at.gv.egovernment.moa.id.process.test; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * Simple task that just outputs a "Hello World" text to the console. + *  + * @author tknall + *  + */ +public class HelloWorldTask implements Task { + +	@Override +	public void execute(ExecutionContext executionContext) { +		System.out.println("Hello World"); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/ProcessDefinitionParserTest.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/ProcessDefinitionParserTest.java new file mode 100644 index 000000000..df13f064b --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/ProcessDefinitionParserTest.java @@ -0,0 +1,137 @@ +package at.gv.egovernment.moa.id.process.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.InputStream; + +import org.junit.Test; + +import at.gv.egovernment.moa.id.process.ProcessDefinitionParser; +import at.gv.egovernment.moa.id.process.ProcessDefinitionParserException; +import at.gv.egovernment.moa.id.process.model.EndEvent; +import at.gv.egovernment.moa.id.process.model.ProcessDefinition; +import at.gv.egovernment.moa.id.process.model.ProcessNode; +import at.gv.egovernment.moa.id.process.model.StartEvent; +import at.gv.egovernment.moa.id.process.model.TaskInfo; +import at.gv.egovernment.moa.id.process.model.Transition; + +public class ProcessDefinitionParserTest { +	 +	@Test(expected = ProcessDefinitionParserException.class) +	public void testParseInvalidProcessDefinition_MultipleStartEvents() throws IOException, ProcessDefinitionParserException { +		try (InputStream in = getClass().getResourceAsStream("InvalidProcessDefinition_MultipleStartEvents.xml")) { +			new ProcessDefinitionParser().parse(in); +		} +	} +	 +	@Test(expected = ProcessDefinitionParserException.class) +	public void testParseInvalidProcessDefinition_TransitionLoop() throws IOException, ProcessDefinitionParserException { +		try (InputStream in = getClass().getResourceAsStream("InvalidProcessDefinition_TransitionLoop.xml")) { +			new ProcessDefinitionParser().parse(in); +		} +	} +	 +	@Test(expected = ProcessDefinitionParserException.class) +	public void testParseInvalidProcessDefinition_TransitionStartsFromEndEvent() throws IOException, ProcessDefinitionParserException { +		try (InputStream in = getClass().getResourceAsStream("InvalidProcessDefinition_TransitionStartsFromEndEvent.xml")) { +			new ProcessDefinitionParser().parse(in); +		} +	} +	 +	@Test(expected = ProcessDefinitionParserException.class) +	public void testParseInvalidProcessDefinition_TransitionRefsTransition() throws IOException, ProcessDefinitionParserException { +		try (InputStream in = getClass().getResourceAsStream("InvalidProcessDefinition_TransitionRefsTransition.xml")) { +			new ProcessDefinitionParser().parse(in); +		} +	} +	 +	@Test(expected = ProcessDefinitionParserException.class) +	public void testParseInvalidProcessDefinition_NoStartEvents() throws IOException, ProcessDefinitionParserException { +		try (InputStream in = getClass().getResourceAsStream("InvalidProcessDefinition_NoStartEvents.xml")) { +			new ProcessDefinitionParser().parse(in); +		} +	} +	 +	@Test +	public void testParseSampleProcessDefinition() throws IOException, ProcessDefinitionParserException { +		try (InputStream in = getClass().getResourceAsStream("SampleProcessDefinition1.xml")) { +			 +			ProcessDefinitionParser parser = new ProcessDefinitionParser(); +			ProcessDefinition pd = parser.parse(in); +			 +			assertNotNull(pd); +			assertEquals("SampleProcess1", pd.getId()); +			 +			// first assert tasks then transitions +			// start event +			StartEvent startEvent = pd.getStartEvent(); +			assertNotNull(startEvent); +			assertEquals("start", startEvent.getId()); +			assertEquals(startEvent, pd.getProcessNode("start")); +			// task1 +			ProcessNode processNode = pd.getProcessNode("task1"); +			assertNotNull(processNode); +			assertTrue(processNode instanceof TaskInfo); +			TaskInfo task1 = (TaskInfo) processNode; +			assertEquals("task1", task1.getId()); +			assertFalse(task1.isAsync()); +			// task2  +			processNode = pd.getProcessNode("task2"); +			assertNotNull(processNode); +			assertTrue(processNode instanceof TaskInfo); +			TaskInfo task2 = (TaskInfo) processNode; +			assertEquals("task2", task2.getId()); +			assertTrue(task2.isAsync()); +			// end event +			processNode = pd.getProcessNode("end"); +			assertNotNull(processNode); +			assertTrue(processNode instanceof EndEvent); +			EndEvent endEvent = (EndEvent) processNode; +			assertEquals("end", endEvent.getId()); +			 +			// assert transitions +			// start event +			assertNotNull(startEvent.getIncomingTransitions()); +			assertTrue(startEvent.getIncomingTransitions().isEmpty()); +			assertNotNull(startEvent.getOutgoingTransitions()); +			assertEquals(1, startEvent.getOutgoingTransitions().size()); +			// transition from start to task1 +			Transition startToTask1 = startEvent.getOutgoingTransitions().get(0); +			assertEquals("fromStart", startToTask1.getId()); +			assertEquals(startEvent, startToTask1.getFrom()); +			assertEquals(task1, startToTask1.getTo()); +			assertEquals("true", startToTask1.getConditionExpression()); +			// task1 +			assertNotNull(task1.getIncomingTransitions()); +			assertEquals(1, task1.getIncomingTransitions().size()); +			assertEquals(startToTask1, task1.getIncomingTransitions().get(0)); +			assertNotNull(task1.getOutgoingTransitions()); +			assertEquals(1, task1.getOutgoingTransitions().size()); +			// transition from task1 to task2 +			Transition task1ToTask2 = task1.getOutgoingTransitions().get(0); +			assertNull(task1ToTask2.getId()); +			assertEquals(task1, task1ToTask2.getFrom()); +			assertEquals(task2, task1ToTask2.getTo()); +			assertNull(task1ToTask2.getConditionExpression()); +			// task2 +			assertNotNull(task2.getIncomingTransitions()); +			assertEquals(1, task2.getIncomingTransitions().size()); +			assertEquals(task1ToTask2, task2.getIncomingTransitions().get(0)); +			assertNotNull(task2.getOutgoingTransitions()); +			assertEquals(1, task2.getOutgoingTransitions().size()); +			// transition from task2 to end +			Transition task2ToEnd = task2.getOutgoingTransitions().get(0); +			assertNull(task2ToEnd.getId()); +			assertEquals(task2, task2ToEnd.getFrom()); +			assertEquals(endEvent, task2ToEnd.getTo()); +			assertNull(task2ToEnd.getConditionExpression()); +			 +		} +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/ProcessEngineTest.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/ProcessEngineTest.java new file mode 100644 index 000000000..4f24468fe --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/ProcessEngineTest.java @@ -0,0 +1,108 @@ +package at.gv.egovernment.moa.id.process.test; + +import static at.gv.egovernment.moa.id.process.ProcessInstanceState.*; +import static org.junit.Assert.*; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.hibernate.cfg.Configuration; +import org.junit.BeforeClass; +import org.junit.Test; + +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils; +import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; +import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.process.ProcessDefinitionParser; +import at.gv.egovernment.moa.id.process.ProcessDefinitionParserException; +import at.gv.egovernment.moa.id.process.ProcessEngine; +import at.gv.egovernment.moa.id.process.ProcessEngineImpl; +import at.gv.egovernment.moa.id.process.ProcessExecutionException; +import at.gv.egovernment.moa.id.process.ProcessInstance; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStore; + +public class ProcessEngineTest { +	 +	private static ProcessEngine pe; + +	@BeforeClass +	public static void init() throws IOException, ProcessDefinitionParserException { + +		ProcessDefinitionParser pdp = new ProcessDefinitionParser(); + +		pe = new ProcessEngineImpl(); + +		((ProcessEngineImpl) pe).setTransitionConditionExpressionEvaluator(new BooleanStringExpressionEvaluator()); +		try (InputStream in = ProcessEngineTest.class.getResourceAsStream("SampleProcessDefinition1.xml")) { +			((ProcessEngineImpl) pe).registerProcessDefinition(pdp.parse(in)); +		} +		try (InputStream in = ProcessEngineTest.class.getResourceAsStream("SampleProcessDefinition2.xml")) { +			((ProcessEngineImpl) pe).registerProcessDefinition(pdp.parse(in)); +		} + +		initHibernateForTesting(); +	} + + +	private static void initHibernateForTesting() throws IOException{ + +		InputStream in = ProcessEngineTest.class.getResourceAsStream("/at/gv/egovernment/moa/id/process/hibernate.configuration.test.properties"); +		Properties props = new Properties(); +		props.load(in); + +		try { +			ConfigurationDBUtils.initHibernate(props); +			Configuration config = new Configuration(); +			config.addProperties(props); +			config.addAnnotatedClass(ProcessInstanceStore.class); +			config.addAnnotatedClass(InterfederationSessionStore.class); +			MOASessionDBUtils.initHibernate(config, props); +		} catch (MOADatabaseException e) { +			e.printStackTrace(); +		} +	} +	 +	@Test +	public void testSampleProcess1() throws IOException, ProcessDefinitionParserException, ProcessExecutionException { + +		String piId = pe.createProcessInstance("SampleProcess1"); +		ProcessInstance pi = pe.getProcessInstance(piId); +		assertEquals(NOT_STARTED, pi.getState()); + +		// start process +		pe.start(piId); +		pi = pe.getProcessInstance(piId); +		assertEquals(SUSPENDED, pi.getState()); + +		System.out.println("Do something asynchronously"); +		pe.signal(piId); +		pi = pe.getProcessInstance(piId); +		assertEquals(ENDED, pi.getState()); +	} +	 +	@Test +	public void testSampleProcess2() throws IOException, ProcessDefinitionParserException, ProcessExecutionException { + +		String piId = pe.createProcessInstance("SampleProcess2"); +		ProcessInstance pi = pe.getProcessInstance(piId); +		assertEquals(NOT_STARTED, pi.getState()); + +		// start process +		pe.start(piId); +		pi = pe.getProcessInstance(piId); +		assertEquals(SUSPENDED, pi.getState()); + +		System.out.println("Do something asynchronously"); +		pe.signal(piId); +		pi = pe.getProcessInstance(piId); +		assertEquals(ENDED, pi.getState()); +	} + +	@Test(expected = IllegalArgumentException.class) +	public void testProcessInstanceDoesNotExist() { +		pe.getProcessInstance("does not exist"); +	} + +} diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/hibernate.configuration.test.properties b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/hibernate.configuration.test.properties new file mode 100644 index 000000000..c4faa6d09 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/hibernate.configuration.test.properties @@ -0,0 +1,12 @@ +# minimal Hibnerate configuration for testing the process engine +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.connection.url=jdbc:h2:mem:moa.id-session;DB_CLOSE_DELAY=-1 +hibernate.connection.charSet=utf-8 +hibernate.connection.driver_class=org.h2.Driver +hibernate.connection.username= +hibernate.connection.password= + +hibernate.format_sql=true +hibernate.show_sql=false +hibernate.transaction.auto_close_session=true +hibernate.hbm2ddl.auto=update diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SampleProcessDefinitionForSAML1Authentication.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SampleProcessDefinitionForSAML1Authentication.xml new file mode 100644 index 000000000..764ad6405 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SampleProcessDefinitionForSAML1Authentication.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<pd:ProcessDefinition xmlns:pd="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	id="SampleProcessDefinitionForSAML1Authentication"> + +	<!-- +		returns String 'bkuURL' +	--> +	<pd:Task id="bkuSelectionTask" class="at.gv.egovernment.moa.id.process.spring.test.task.SelectBKUTask" /> + +	<!-- +		requires 'bkuURL' +		returns String 'IdentityLink' +	--> +	<pd:Task id="getIdentityLinkTask" class="at.gv.egovernment.moa.id.process.spring.test.task.GetIdentityLinkTask" /> + +	<!-- +		requires 'IdentityLink' +		returns Boolean 'isIdentityLinkValidated' +	--> +	<pd:Task id="validateIdentityLinkTask" class="at.gv.egovernment.moa.id.process.spring.test.task.ValidateIdentityLinkTask" /> + +	<!-- +		requires 'IdentityLink', 'isIdentityLinkValidated', 'bkuURL' +		returns String 'SignedAuthBlock' +	--> +	<pd:Task id="signAuthBlockTask" class="at.gv.egovernment.moa.id.process.spring.test.task.SignAuthBlockTask" /> + +	<!-- +		requires 'IdentityLink', 'isIdentityLinkValidated', 'SignedAuthBlock' +		returns Boolean 'isSignedAuthBlockValidated' +	--> +	<pd:Task id="validateSignedAuthBlockTask" class="at.gv.egovernment.moa.id.process.spring.test.task.ValidateSignedAuthBlockTask" /> +	 +	<!-- +		requires 'IdentityLink', 'isIdentityLinkValidated', 'SignedAuthBlock', 'isSignedAuthBlockValidated'; +		returns 'SAML1Assertion' +	--> +	<pd:Task id="createAssertionTask" class="at.gv.egovernment.moa.id.process.spring.test.task.CreateSAML1AssertionTask" /> + +	<pd:StartEvent id="start" /> +	<pd:EndEvent id="end" /> + +	<pd:Transition from="start" to="bkuSelectionTask"    conditionExpression="ctx['bkuURL'] == null" /> +	<pd:Transition from="start" to="getIdentityLinkTask"  /> +	 +	<pd:Transition from="bkuSelectionTask"            to="getIdentityLinkTask" /> +	<pd:Transition from="getIdentityLinkTask"         to="validateIdentityLinkTask" /> +	<pd:Transition from="validateIdentityLinkTask"    to="signAuthBlockTask"            conditionExpression="ctx['isIdentityLinkValidated']" /> +	<pd:Transition from="signAuthBlockTask"           to="validateSignedAuthBlockTask" /> +	<pd:Transition from="validateSignedAuthBlockTask" to="createAssertionTask"          conditionExpression="ctx['isSignedAuthBlockValidated']" /> +	 +	<pd:Transition from="createAssertionTask" to="end" /> + +</pd:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SampleProcessDefinitionWithExpression1.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SampleProcessDefinitionWithExpression1.xml new file mode 100644 index 000000000..dfe186423 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SampleProcessDefinitionWithExpression1.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<pd:ProcessDefinition xmlns:pd="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	id="SampleProcessWithExpression1"> + +	<pd:Task id="task1" /> +	<pd:Task id="task2" /> +	<pd:Task id="task3" /> +	<pd:Task id="task4" /> + +	<pd:StartEvent id="start" /> +	<pd:EndEvent id="end" /> + +	<pd:Transition from="start" to="task1" conditionExpression="'true'" /> +	<pd:Transition from="task1" to="task2" conditionExpression="'true'" /> +	<pd:Transition from="task2" to="task3" conditionExpression="'true'" /> +	<pd:Transition from="task3" to="task4" conditionExpression="'true'" /> +	<pd:Transition from="task4" to="end"   conditionExpression="'true'" /> +	 +</pd:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionAwareProcessEngineTest-context.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionAwareProcessEngineTest-context.xml new file mode 100644 index 000000000..9a381d83a --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionAwareProcessEngineTest-context.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xmlns:task="http://www.springframework.org/schema/task" +	xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd +		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> + +	<bean id="springElAwareExpressionEvaluator" class="at.gv.egovernment.moa.id.process.spring.SpringExpressionEvaluator" /> + +	<bean id="processEngine" class="at.gv.egovernment.moa.id.process.ProcessEngineImpl"> +		<property name="transitionConditionExpressionEvaluator" ref="springElAwareExpressionEvaluator" /> +	</bean> +</beans> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionEvaluatorTest-context.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionEvaluatorTest-context.xml new file mode 100644 index 000000000..95b88ca1a --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionEvaluatorTest-context.xml @@ -0,0 +1,14 @@ +<?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.xsd"> + +	<bean id="simplePojo" class="at.gv.egovernment.moa.id.process.spring.test.SimplePojo"> +		<property name="booleanValue" value="true" /> +		<property name="integerValue" value="42" /> +		<property name="stringValue" value="HelloWorld" /> +	</bean> +	 +	<bean id="expressionEvaluator" class="at.gv.egovernment.moa.id.process.spring.SpringExpressionEvaluator" /> + +</beans> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/IdentityLink_Max_Mustermann.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/IdentityLink_Max_Mustermann.xml new file mode 100644 index 000000000..c68972f13 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/IdentityLink_Max_Mustermann.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?><saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:si="http://www.w3.org/2001/XMLSchema-instance" AssertionID="szr.bmi.gv.at-AssertionID132860852347311974" IssueInstant="2012-02-07T10:55:23+01:00" Issuer="http://portal.bmi.gv.at/ref/szr/issuer" MajorVersion="1" MinorVersion="0"> +	<saml:AttributeStatement> +		<saml:Subject> +			<saml:SubjectConfirmation> +				<saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</saml:ConfirmationMethod> +				<saml:SubjectConfirmationData> +					<pr:Person si:type="pr:PhysicalPersonType"><pr:Identification><pr:Value>tqCQEC7+AqGEeeL390V5Jg==</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type></pr:Identification><pr:Name><pr:GivenName>Max</pr:GivenName><pr:FamilyName primary="undefined">Mustermann</pr:FamilyName></pr:Name><pr:DateOfBirth>1940-01-01</pr:DateOfBirth></pr:Person> +				</saml:SubjectConfirmationData> +			</saml:SubjectConfirmation> +		</saml:Subject> +	<saml:Attribute AttributeName="CitizenPublicKey" AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2"><saml:AttributeValue><ecdsa:ECDSAKeyValue><ecdsa:DomainParameters><ecdsa:NamedCurve URN="urn:oid:1.2.840.10045.3.1.7"/></ecdsa:DomainParameters><ecdsa:PublicKey><ecdsa:X Value="111409151487007036894649069746411000129419717653159596280366627647453458115517" si:type="ecdsa:PrimeFieldElemType"/><ecdsa:Y Value="94725036374184689337892465478597728884477416796494369571140658859618867645034" si:type="ecdsa:PrimeFieldElemType"/></ecdsa:PublicKey></ecdsa:ECDSAKeyValue></saml:AttributeValue></saml:Attribute></saml:AttributeStatement> +	<dsig:Signature> +		<dsig:SignedInfo> +			<dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> +			<dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> +			<dsig:Reference URI=""> +				<dsig:Transforms> +					<dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> +						<dsig:XPath>not(ancestor-or-self::pr:Identification)</dsig:XPath> +					</dsig:Transform> +					<dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> +				</dsig:Transforms> +				<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +				<dsig:DigestValue>Rmr5vkWXL/PvpoXnbK632QmzYms=</dsig:DigestValue> +			</dsig:Reference> +			<dsig:Reference Type="http://www.w3.org/2000/09/xmldsig#Manifest" URI="#manifest"> +				<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +				<dsig:DigestValue>HoPZWYll8aMFpKOlRSwckt5iCQk=</dsig:DigestValue> +			</dsig:Reference> +		</dsig:SignedInfo> +		<dsig:SignatureValue> +    NPpRwVo5/5kf5iHUyaEc7d7So3W4oPgOCYNgnKpgdZfttFkFFN+9oG60w7YvKEYSeTPhP3zp7eaH +ZFapj+naD+wd0y5ELWep9Y+s+qP7fNLrFECHQxQasLWtR4akxlWDpYQ0bvOuepK2ip1EQ6pRlccA +wJ1l4iOWFhfdA9YAg5QLkBqWSwgrNUswhLnDBM+Ot6Gj5g2rpYY7aoAOXvTR8B5Dkg94ASb4u0wv +VPV8+4mjOfP+l6QWLqywzcq3qj/qFZkbujjZbV/fNPDnDD1ff/M6ZfCGO8xzlYfjfEA7cmHuiJf2 +/ey/3nT7vI5XbpBPWChT5Sl4DQysxlfE6e4MZw== +  </dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>MIIF3TCCBMWgAwIBAgIDByniMA0GCSqGSIb3DQEBBQUAMIGfMQswCQYDVQQGEwJBVDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMSIwIAYDVQQLDBlhLXNpZ24tY29ycG9yYXRlLWxpZ2h0LTAyMSIwIAYDVQQDDBlhLXNpZ24tY29ycG9yYXRlLWxpZ2h0LTAyMB4XDTEwMDcyODExMzY0M1oXDTE1MDcyODExMzY0M1owgbYxCzAJBgNVBAYTAkFUMR4wHAYDVQQKDBVEYXRlbnNjaHV0emtvbW1pc3Npb24xIjAgBgNVBAsMGVN0YW1temFobHJlZ2lzdGVyYmVob2VyZGUxLjAsBgNVBAMMJVNpZ25hdHVyc2VydmljZSBEYXRlbnNjaHV0emtvbW1pc3Npb24xFTATBgNVBAUTDDMyNTkyODMyMzk5ODEcMBoGCSqGSIb3DQEJARYNZHNrQGRzay5ndi5hdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+dBSEBGj2jUXIK1Mp3lVxc/Za+pJMiyKrX3G1ZxgX/ikx7D9scsPYMt473LlAWl9cmCbHbJK+PV2XNNdURLMUCIX+4vUNs2MHeDTQtX8BXjJFpwJYSoaRJQ39FVS/1r5sWcra9Hhdm7w5Gtx/2ukyDX0kdkxawkhP4EQEzi/SI+Fugn+WqgQ1nAdlbxb/dcBw5w1h9b3lmuwUf4z3ooQWUD2DgA/kKd1KejNR43mLUsmvSzevPxT9zs78pOR1OacB7IszTVJPXeOEaaNZHnnB/UeO3g8LEV/3OkXcUgcMkbIIiaBHlll71Pq0COj9kqjXoe7OrRjLY5i3KwOpa6TMCAwEAAaOCAgcwggIDMBMGA1UdIwQMMAqACEkcWDpP6A0DMH8GCCsGAQUFBwEBBHMwcTAnBggrBgEFBQcwAYYbaHR0cDovL29jc3AuYS10cnVzdC5hdC9vY3NwMEYGCCsGAQUFBzAChjpodHRwOi8vd3d3LmEtdHJ1c3QuYXQvY2VydHMvYS1zaWduLWNvcnBvcmF0ZS1saWdodC0wMmEuY3J0MFQGA1UdIARNMEswSQYGKigAEQESMD8wPQYIKwYBBQUHAgEWMWh0dHA6Ly93d3cuYS10cnVzdC5hdC9kb2NzL2NwL2Etc2lnbi1BbXRzc2lnbmF0dXIwgZ4GA1UdHwSBljCBkzCBkKCBjaCBioaBh2xkYXA6Ly9sZGFwLmEtdHJ1c3QuYXQvb3U9YS1zaWduLWNvcnBvcmF0ZS1saWdodC0wMixvPUEtVHJ1c3QsYz1BVD9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0P2Jhc2U/b2JqZWN0Y2xhc3M9ZWlkQ2VydGlmaWNhdGlvbkF1dGhvcml0eTARBgNVHQ4ECgQITAgOnhr0tbowDgYDVR0PAQH/BAQDAgSwMCAGA1UdEQQZMBeBFW1hcmN1cy5oaWxkQGRzay5ndi5hdDAJBgNVHRMEAjAAMA4GByooAAoBBwEEAwEB/zAUBgcqKAAKAQEBBAkMB0JTQi1EU0swDQYJKoZIhvcNAQEFBQADggEBAHTklnvPCH/bJSOlIPbLUEkSGuFHsektSZ8Vr22x/Yv7EzsxoQrJIiz2mQ2gQqFuExdWYxvsowjiSbiis9iUf1c0zscvDS3mIZxGs4M89XHsjHnIyb+Fuwnamw65QrFvM1tNB1ZMjxJ3x+YmHLHdtT3BEBcr3/NCRHd2S0HoBspNz9HVgJaZY1llR7poKBvnAc4g1i+QTvyVb00PtKxR9Lw/9ABInX/1pzpxqrPy7Ib2OP8z6dd3WHmIsCiSHUaj0Dxwwln6fYJjhxZ141SnbovlCLYtrsZLXoi9ljIqX4xO0PwMI2RfNc9cXxTRrRS6rEOvX7PpvgXiDXhp592Yyp4=</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo> +		<dsig:Object> +			<dsig:Manifest Id="manifest"> +				<dsig:Reference URI=""> +					<dsig:Transforms> +						<dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> +							<dsig:XPath>not(ancestor-or-self::dsig:Signature)</dsig:XPath> +						</dsig:Transform> +					</dsig:Transforms> +					<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +					<dsig:DigestValue>7IkIdYti2dh3VZQ4Fp+9lPT67cM=</dsig:DigestValue> +				</dsig:Reference> +			</dsig:Manifest> +		</dsig:Object> +	</dsig:Signature> +</saml:Assertion>
\ No newline at end of file diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/SAML1Assertion.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/SAML1Assertion.xml new file mode 100644 index 000000000..3aeedd590 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/SAML1Assertion.xml @@ -0,0 +1,487 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml:Assertion AssertionID="6025428631468682100" IssueInstant="2008-07-14T17:51:38+02:00" Issuer="https://localhost:18443/moa-id-auth/" MajorVersion="1" MinorVersion="0" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:si="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> +  <saml:AttributeStatement> +	 <saml:Subject> +		<saml:NameIdentifier NameQualifier="urn:publicid:gv.at:wbpk+FN+www.act.at">K2YMyx3/5kIpNJR+SAD/rbRYH+c=</saml:NameIdentifier> +		<saml:SubjectConfirmation> +		  <saml:ConfirmationMethod>http://reference.e-government.gv.at/namespace/moa/20020822#cm</saml:ConfirmationMethod> +		  <saml:SubjectConfirmationData> +			 <saml:Assertion AssertionID="any" IssueInstant="2008-07-14T17:51:26+02:00" Issuer="Thomas Knall" MajorVersion="1" MinorVersion="0" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"> +				<saml:AttributeStatement> +				  <saml:Subject> +					 <saml:NameIdentifier>https://localhost:18443/moa-id-auth/</saml:NameIdentifier> +				  </saml:Subject> +				  <saml:Attribute AttributeName="wbPK" AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#"> +					 <saml:AttributeValue> +						<pr:Identification> +						  <pr:Value>K2YMyx3/5kIpNJR+SAD/rbRYH+c=</pr:Value> +						  <pr:Type>urn:publicid:gv.at:wbpk+FN+www.act.at</pr:Type> +						</pr:Identification> +					 </saml:AttributeValue> +				  </saml:Attribute> +				  <saml:Attribute AttributeName="OA" AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#"> +					 <saml:AttributeValue>https://localhost:48443/mandates/</saml:AttributeValue> +				  </saml:Attribute> +				  <saml:Attribute AttributeName="Geburtsdatum" AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#"> +					 <saml:AttributeValue>1978-04-29</saml:AttributeValue> +				  </saml:Attribute> +				  <saml:Attribute AttributeName="RepresentationType" AttributeNamespace="http://reference.e-government.gv.at/namespace/mandates/20040701#"> +					 <saml:AttributeValue>Vollmachtsvertreter</saml:AttributeValue> +				  </saml:Attribute> +				  <saml:Attribute AttributeName="MandatorName" AttributeNamespace="http://reference.e-government.gv.at/namespace/mandates/20040701#"> +					 <saml:AttributeValue>MeineTestFirma</saml:AttributeValue> +				  </saml:Attribute> +				  <saml:Attribute AttributeName="MandatorWbpk" AttributeNamespace="http://reference.e-government.gv.at/namespace/mandates/20040701#"> +					 <saml:AttributeValue>123456i</saml:AttributeValue> +				  </saml:Attribute> +				</saml:AttributeStatement> +				<dsig:Signature Id="signature-1216050695-35956125-21395" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> +				  <dsig:SignedInfo> +					 <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> +					 <dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"/> +					 <dsig:Reference Id="signed-data-reference-0-1216050695-35956125-19584" URI=""> +						<dsig:Transforms> +						  <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> +						  <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116"> +							 <xsl:stylesheet version="1.0" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> +								<xsl:template match="/" xmlns="http://www.w3.org/1999/xhtml"> +								  <html xmlns="http://www.w3.org/1999/xhtml"> +									 <head> +										<title>Signatur der Anmeldedaten</title> +										<style media="screen" type="text/css"> +		  .boldstyle { font-weight: bold; } +		  .italicstyle { font-style: italic; } +		  .annotationstyle { font-size: small; } +		  </style> +									 </head> +									 <body> +										<h1>Signatur der Anmeldedaten</h1> +										<p/> +										<h4>Mit meiner elektronischen Signatur beantrage ich, +			 <span class="boldstyle"> +											 <xsl:value-of select="//@Issuer"/> +										  </span>, geboren am +			 <xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,9,2)"/>. +			 <xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,6,2)"/>. +			 <xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,1,4)"/>, +			 <xsl:if test="//saml:Attribute[@AttributeName='OIDTextualDescription']"> +				in der Rolle als <xsl:value-of select="//saml:Attribute[@AttributeName='OIDTextualDescription']/saml:AttributeValue"/> +				(OID***= <xsl:value-of select="//saml:Attribute[@AttributeName='OID']/saml:AttributeValue"/>), +			 </xsl:if> +			 den Zugang zur gesicherten Anwendung. +		  </h4> +										<p/> +										<h4>Datum und Uhrzeit: +			 <xsl:value-of select="substring(//@IssueInstant,9,2)"/>. +			 <xsl:value-of select="substring(//@IssueInstant,6,2)"/>. +			 <xsl:value-of select="substring(//@IssueInstant,1,4)"/>, +			 <xsl:value-of select="substring(//@IssueInstant,12,2)"/>: +			 <xsl:value-of select="substring(//@IssueInstant,15,2)"/>: +			 <xsl:value-of select="substring(//@IssueInstant,18,2)"/> +										</h4> +										<xsl:if test="//saml:Attribute[@AttributeName='HPI']"> +										  <h4>HPI(**): <xsl:value-of select="//saml:Attribute[@AttributeName='HPI']/saml:AttributeValue"/> +										  </h4> +										</xsl:if> +										<xsl:if test="//saml:Attribute[@AttributeName='wbPK']"> +										  <h4>wbPK(*): <xsl:value-of select="//saml:Attribute[@AttributeName='wbPK']/saml:AttributeValue/pr:Identification/pr:Value"/> +										  </h4> +										</xsl:if> +										<xsl:if test="//saml:Attribute[@AttributeName='MandatorName']"> +										  <hr/> +										  <h4>Ich bin weiters ermächtigt als <xsl:value-of select="//saml:Attribute[@AttributeName='RepresentationType']/saml:AttributeValue/text()"/> +				von <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorName']/saml:AttributeValue/text()"/> +											 <xsl:if test="//saml:Attribute[@AttributeName='MandatorDateOfBirth']">, geboren am +				  <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,9,2)"/>. +				  <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,6,2)"/>. +				  <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,1,4)"/> +											 </xsl:if> +											 <xsl:if test="//saml:Attribute[@AttributeName='MandatorDomainIdentifier']">, +				  <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorDomainIdentifier']/saml:AttributeValue/text()"/> +											 </xsl:if>, in deren Auftrag zu handeln. +			 </h4> +										  <xsl:if test="//saml:Attribute[@AttributeName='MandatorWbpk']"> +											 <h4>wbPK(*) des Vollmachtgebers: <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorWbpk']/saml:AttributeValue/text()"/> +											 </h4> +										  </xsl:if> +										  <p/> +										</xsl:if> +										<xsl:choose> +										  <xsl:when test="//saml:Attribute[@AttributeName='OID']"> +											 <p/> +											 <hr/> +										  </xsl:when> +										  <xsl:when test="//saml:Attribute[@AttributeName='HPI']"> +											 <p/> +											 <hr/> +										  </xsl:when> +										  <xsl:when test="//saml:Attribute[@AttributeName='wbPK']"> +											 <p/> +											 <hr/> +										  </xsl:when> +										</xsl:choose> +										<xsl:if test="//saml:Attribute[@AttributeName='wbPK']"> +										  <div class="annotationstyle">(*) wbPK: Das <span class="italicstyle">wirtschaftsbereichsspezifische Personenkennzeichen</span> wird aus den +			 jeweiligen Stammzahlen des Bürgers und des Wirtschaftsunternehmens berechnet und ermöglicht eine eindeutige Zuordnung des Bürgers zum +			 Wirtschaftsunternehmen.</div> +										</xsl:if> +										<xsl:if test="//saml:Attribute[@AttributeName='HPI']"> +										  <div class="annotationstyle">(**) HPI: Der <span class="italicstyle">eHealth Professional Identifier</span> wird aus den jeweiligen +			 Stammzahlen der Gesundheitsdiensteanbieterinnen / Gesundheitsdiensteanbieter berechnet und ermöglicht eine eindeutige Zuordnung der +			 Gesundheitsdiensteanbieterin / des Gesundheitsdiensteanbieters im Gesundheitsbereich.</div> +										</xsl:if> +										<xsl:if test="//saml:Attribute[@AttributeName='OID']"> +										  <div class="annotationstyle">(***) OID: <span class="italicstyle">Object Identifier</span> sind standardisierte Objekt-Bezeichner und +			 beschreiben eindeutig die Rollen des GDA-Token Inhabers.</div> +										</xsl:if> +									 </body> +								  </html> +								</xsl:template> +							 </xsl:stylesheet> +						  </dsig:Transform> +						  <dsig:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/> +						</dsig:Transforms> +						<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +						<dsig:DigestValue>0q9QWyqAyyiVNNLu1rIcU+nKsEE=</dsig:DigestValue> +					 </dsig:Reference> +					 <dsig:Reference Id="etsi-data-reference-0-1216050695-35956125-7815" Type="http://uri.etsi.org/01903/v1.1.1#SignedProperties" URI="#xmlns(etsi=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('etsi-data-object-0-1216050695-35956125-20638')/child::etsi:QualifyingProperties/child::etsi:SignedProperties)"> +						<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +						<dsig:DigestValue>WtB0/ptvoB/r/7+fauSUIBULymg=</dsig:DigestValue> +					 </dsig:Reference> +				  </dsig:SignedInfo> +				  <dsig:SignatureValue>mZt9DuZiDqG81scsf30qjSDdy6vKC2/n034ZZwMUAvfWOXy3+Ubsk5X5CHhz ++lyI</dsig:SignatureValue> +				  <dsig:KeyInfo> +					 <dsig:X509Data> +						<dsig:X509Certificate>MIIEtDCCA5ygAwIBAgIDAgTEMA0GCSqGSIb3DQEBBQUAMIGXMQswCQYDVQQG +EwJBVDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lz +dGVtZSBpbSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMR4wHAYDVQQLDBVh +LXNpZ24tUHJlbWl1bS1TaWctMDIxHjAcBgNVBAMMFWEtc2lnbi1QcmVtaXVt +LVNpZy0wMjAeFw0wNjA0MDQwOTUyMjhaFw0xMTA0MDQwOTUyMjhaMGkxCzAJ +BgNVBAYTAkFUMRUwEwYDVQQDDAxUaG9tYXMgS25hbGwxDjAMBgNVBAQMBUtu +YWxsMQ8wDQYDVQQqDAZUaG9tYXMxFTATBgNVBAUTDDUzNTE5ODkyMzM0OTEL +MAkGA1UEDAwCREkwSTATBgcqhkjOPQIBBggqhkjOPQMBAQMyAARrnYW5sXCQ +6M3irWaanDPi/ROXueKWiPRyZGjNH0Cp/NaiOuvrpv2RDVEKQm2tBiajggIP +MIICCzATBgNVHSMEDDAKgAhN3+H/S9nJ3zAnBggrBgEFBQcBAwEB/wQYMBYw +CAYGBACORgEBMAoGCCsGAQUFBwsBMHsGCCsGAQUFBwEBBG8wbTBCBggrBgEF +BQcwAoY2aHR0cDovL3d3dy5hLXRydXN0LmF0L2NlcnRzL2Etc2lnbi1QcmVt +aXVtLVNpZy0wMmEuY3J0MCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5hLXRy +dXN0LmF0L29jc3AwWQYDVR0gBFIwUDBEBgYqKAARAQswOjA4BggrBgEFBQcC +ARYsaHR0cDovL3d3dy5hLXRydXN0LmF0L2RvY3MvY3AvYS1zaWduLVByZW1p +dW0wCAYGBACLMAEBMIGaBgNVHR8EgZIwgY8wgYyggYmggYaGgYNsZGFwOi8v +bGRhcC5hLXRydXN0LmF0L291PWEtc2lnbi1QcmVtaXVtLVNpZy0wMixvPUEt +VHJ1c3QsYz1BVD9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0P2Jhc2U/b2Jq +ZWN0Y2xhc3M9ZWlkQ2VydGlmaWNhdGlvbkF1dGhvcml0eTARBgNVHQ4ECgQI +SNyH29WUoCgwDgYDVR0PAQH/BAQDAgbAMCgGA1UdCQQhMB8wHQYIKwYBBQUH +CQExERgPMTk3ODA0MjkwMDAwMDBaMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEF +BQADggEBAFkSCJE0YD4p4izU3ekQYPv4Z7gm/VFlpma5hXNvwkajVjHlAqo/ +ylYn8NQ4mMkD+yCDNtm8m8nr0K/yICb8Gnkbv59i6nh2AbzYBBb49VnYYGL6 +uunLH0aFUpAhy+3mDdlH8uhhIQBHwCfgwG1qa5zXY7bz4Vzkac/h6T+JVFkI +egO8OHQDadhgJvW80qspiao2DTac6vVgx4tGvjpdmw1R2pXBYhHD5rkPHlkf +GoeL3ak6hq4ea94Oy5VfNTIJv5MA0J2G1mwnW9B8uPWSM5EYPoWJyBOWcKBL +SSUqOt9D/9215ZGfbchkdRZjx0dTAD3FIhgG8nA72/uCFrBzyTk= +</dsig:X509Certificate> +					 </dsig:X509Data> +				  </dsig:KeyInfo> +				  <dsig:Object Id="etsi-data-object-0-1216050695-35956125-20638"> +					 <etsi:QualifyingProperties Target="#signature-1216050695-35956125-21395" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#"> +						<etsi:SignedProperties> +						  <etsi:SignedSignatureProperties> +							 <etsi:SigningTime>2008-07-14T15:51:35Z</etsi:SigningTime> +							 <etsi:SigningCertificate> +								<etsi:Cert> +								  <etsi:CertDigest> +									 <etsi:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +									 <etsi:DigestValue>inMYWBmAxMHP7mDENjLFaEtv0Zk=</etsi:DigestValue> +								  </etsi:CertDigest> +								  <etsi:IssuerSerial> +									 <dsig:X509IssuerName>CN=a-sign-Premium-Sig-02,OU=a-sign-Premium-Sig-02,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT</dsig:X509IssuerName> +									 <dsig:X509SerialNumber>132292</dsig:X509SerialNumber> +								  </etsi:IssuerSerial> +								</etsi:Cert> +							 </etsi:SigningCertificate> +							 <etsi:SignaturePolicyIdentifier> +								<etsi:SignaturePolicyImplied/> +							 </etsi:SignaturePolicyIdentifier> +						  </etsi:SignedSignatureProperties> +						  <etsi:SignedDataObjectProperties> +							 <etsi:DataObjectFormat ObjectReference="#signed-data-reference-0-1216050695-35956125-19584"> +								<etsi:MimeType>application/xhtml+xml</etsi:MimeType> +							 </etsi:DataObjectFormat> +						  </etsi:SignedDataObjectProperties> +						</etsi:SignedProperties> +					 </etsi:QualifyingProperties> +				  </dsig:Object> +				</dsig:Signature> +			 </saml:Assertion> +			 <saml:Assertion AssertionID="szr.bmi.gv.at-AssertionID11936526102761952" IssueInstant="2007-10-29T10:10:10+01:00" Issuer="http://portal.bmi.gv.at/ref/szr/issuer" MajorVersion="1" MinorVersion="0" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:si="http://www.w3.org/2001/XMLSchema-instance"> +				<saml:AttributeStatement> +				  <saml:Subject> +					 <saml:SubjectConfirmation> +						<saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</saml:ConfirmationMethod> +						<saml:SubjectConfirmationData> +						  <pr:Person si:type="pr:PhysicalPersonType"> +							 <pr:Identification> +								<pr:Value>K2YMyx3/5kIpNJR+SAD/rbRYH+c=</pr:Value> +								<pr:Type>urn:publicid:gv.at:wbpk+FN+www.act.at</pr:Type> +							 </pr:Identification> +							 <pr:Name> +								<pr:GivenName>Thomas</pr:GivenName> +								<pr:FamilyName primary="undefined">Knall</pr:FamilyName> +							 </pr:Name> +							 <pr:DateOfBirth>1978-04-29</pr:DateOfBirth> +						  </pr:Person> +						</saml:SubjectConfirmationData> +					 </saml:SubjectConfirmation> +				  </saml:Subject> +				  <saml:Attribute AttributeName="CitizenPublicKey" AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2"> +					 <saml:AttributeValue> +						<ecdsa:ECDSAKeyValue> +						  <ecdsa:DomainParameters> +							 <ecdsa:NamedCurve URN="urn:oid:1.2.840.10045.3.1.1"/> +						  </ecdsa:DomainParameters> +						  <ecdsa:PublicKey> +							 <ecdsa:X Value="2638720011055700682018137297354399374048880611104468142324" si:type="ecdsa:PrimeFieldElemType"/> +							 <ecdsa:Y Value="2804889174475641803405778188053052844820705830770276369958" si:type="ecdsa:PrimeFieldElemType"/> +						  </ecdsa:PublicKey> +						</ecdsa:ECDSAKeyValue> +					 </saml:AttributeValue> +				  </saml:Attribute> +				  <saml:Attribute AttributeName="CitizenPublicKey" AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2"> +					 <saml:AttributeValue> +						<dsig:RSAKeyValue> +						  <dsig:Modulus>sWOqPZzPTn9VvBR5LjuopIWYdh5aGzuX2vMjofhn8bStba1CDW1qkDdlYW4Rs/DfU/I1uqor4Lje +/G3Yzh82yD0MHdzlW8MYUJ8RJe+czbjRUPaSbC/NRqhyF3eKnflxM++sJb2abrUH/9TV0q8P5QRS +uZC/JpAEYpSazysPz/fv8AEnU8oxcTvCiax1jf2GZPmm3qFjPc4qDYNHqfnE8yWYt7kHeqPV/cRw +x3aMGW8mRwQZb7VRFLW5g37nrt9N</dsig:Modulus> +						  <dsig:Exponent>AQAB</dsig:Exponent> +						</dsig:RSAKeyValue> +					 </saml:AttributeValue> +				  </saml:Attribute> +				</saml:AttributeStatement> +				<dsig:Signature> +				  <dsig:SignedInfo> +					 <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> +					 <dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> +					 <dsig:Reference URI=""> +						<dsig:Transforms> +						  <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> +							 <dsig:XPath>not(ancestor-or-self::pr:Identification)</dsig:XPath> +						  </dsig:Transform> +						  <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> +						</dsig:Transforms> +						<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +						<dsig:DigestValue>b3d/wcQb0Bl0/6GSPsrMxWpdRLA=</dsig:DigestValue> +					 </dsig:Reference> +					 <dsig:Reference Type="http://www.w3.org/2000/09/xmldsig#Manifest" URI="#manifest"> +						<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +						<dsig:DigestValue>eet0q3Thmw6+cbO1fazbEg0556I=</dsig:DigestValue> +					 </dsig:Reference> +				  </dsig:SignedInfo> +				  <dsig:SignatureValue> +oy55Cq7IyYy7z/TO2a3+m7tjG/ztiKhxhGzVqEYIWIObEOs/GVJDCCI4oe/HS8Fhc4TaXDcZXk4y +qBp4JJ288TeaNjPYkPzp38nWJ4xRatEyo7VaySXy+TqgwiBT5uhxrwkroCr4ZIWwOvt1uR5UBVAf +qk1ii+LPW2WYE3bMpoHfrM9CdFSPzWTRl/0zsEURc64EBPyIdKz+c70DaexeX2E0JVelKcj+jDaJ +mHsFhi/9QoscqPEVA87qv07yhyK5S41+f3HDvpuhYwvQDdOq50sclfsI+g9r473VxiRsOmJ9Ak4/ +k2KP0tgfAQ+h5hRGQUUo5LYPywjg7zPxe8SGGA== +</dsig:SignatureValue> +				  <dsig:KeyInfo> +					 <dsig:X509Data> +						<dsig:X509Certificate> +MIIFZTCCBE2gAwIBAgIDAt4cMA0GCSqGSIb3DQEBBQUAMIGfMQswCQYDVQQGEwJB +VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp +bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMSIwIAYDVQQLDBlhLXNpZ24tY29y +cG9yYXRlLWxpZ2h0LTAzMSIwIAYDVQQDDBlhLXNpZ24tY29ycG9yYXRlLWxpZ2h0 +LTAzMB4XDTA3MDExOTA5MDY0OFoXDTEyMDExOTA5MDY0OFowgZwxCzAJBgNVBAYT +AkFUMRkwFwYDVQQKDBBCdW5kZXNrYW56bGVyYW10MR4wHAYDVQQLDBVEYXRlbnNj +aHV0emtvbW1pc3Npb24xHTAbBgNVBAMMFERyLiBXYWx0cmF1dCBLb3RzY2h5MRUw +EwYDVQQFEww3MDAyNDc0OTk4MDQxHDAaBgkqhkiG9w0BCQEWDWRza0Bkc2suZ3Yu +YXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDfnQUhARo9o1FyCtTK +d5VcXP2WvqSTIsiq19xtWcYF/4pMew/bHLD2DLeO9y5QFpfXJgmx2ySvj1dlzTXV +ESzFAiF/uL1DbNjB3g00LV/AV4yRacCWEqGkSUN/RVUv9a+bFnK2vR4XZu8ORrcf +9rpMg19JHZMWsJIT+BEBM4v0iPhboJ/lqoENZwHZW8W/3XAcOcNYfW95ZrsFH+M9 +6KEFlA9g4AP5CndSnozUeN5i1LJr0s3rz8U/c7O/KTkdTmnAeyLM01ST13jhGmjW +R55wf1Hjt4PCxFf9zpF3FIHDJGyCImgR5ZZe9T6tAjo/ZKo16Huzq0Yy2OYtysDq +WukzAgMBAAGjggGpMIIBpTATBgNVHSMEDDAKgAhBkWkcv63YmDBVBggrBgEFBQcB +AQRJMEcwRQYIKwYBBQUHMAKGOWh0dHA6Ly93d3cuYS10cnVzdC5hdC9jZXJ0cy9h +LXNpZ24tY29ycG9yYXRlLWxpZ2h0LTAzLmNydDBYBgNVHSAEUTBPME0GByooABEB +BwEwQjBABggrBgEFBQcCARY0aHR0cDovL3d3dy5hLXRydXN0LmF0L2RvY3MvY3Av +YS1zaWduLWNvcnBvcmF0ZS1saWdodDCBngYDVR0fBIGWMIGTMIGQoIGNoIGKhoGH +bGRhcDovL2xkYXAuYS10cnVzdC5hdC9vdT1hLXNpZ24tY29ycG9yYXRlLWxpZ2h0 +LTAzLG89QS1UcnVzdCxjPUFUP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3Q/YmFz +ZT9vYmplY3RjbGFzcz1laWRDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5MBEGA1UdDgQK +BAhMCA6eGvS1ujAOBgNVHQ8BAf8EBAMCBLAwCQYDVR0TBAIwADAOBgcqKAAKAQcB +BAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAEoIvqPLAg0n2wCS27zTL+hmLi7zSbes +Od4e6pFT1l3cwGfdTkhiHVPnPRaDGLQkS384fAXBrOp6W13X9m2jD9csO6vZhd+T +nERXN1AqayoaecXFyHPykVUTLhn6pMdiSE21mEozfGLUDGMz74lvphEKFAOOCgp1 +o5ZCR09RbGAEbQNNn+ucXJxIa3mYjr1h3AElVbXoeoz12qUpqsNm9znymSkcmcNo +B5Pk6qXXx9UeC/Tj0aTglNkcMOSCFayldzOBaY6+qWKguPdzQUEryhGiNuARQpM5 +KMzvI0rmpc4Gau5HT9rQZHadr++VS8v1k6935uIyyZF9s+gdS5ywnSM= +</dsig:X509Certificate> +					 </dsig:X509Data> +				  </dsig:KeyInfo> +				  <dsig:Object> +					 <dsig:Manifest Id="manifest"> +						<dsig:Reference URI=""> +						  <dsig:Transforms> +							 <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> +								<dsig:XPath>not(ancestor-or-self::dsig:Signature)</dsig:XPath> +							 </dsig:Transform> +						  </dsig:Transforms> +						  <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +						  <dsig:DigestValue>JZGwiDzQAtJtnJMeeXyypTrDjwY=</dsig:DigestValue> +						</dsig:Reference> +					 </dsig:Manifest> +				  </dsig:Object> +				</dsig:Signature> +			 </saml:Assertion> +		  </saml:SubjectConfirmationData> +		</saml:SubjectConfirmation> +	 </saml:Subject> +	 <saml:Attribute AttributeName="PersonData" AttributeNamespace="http://reference.e-government.gv.at/namespace/persondata/20020228#"> +		<saml:AttributeValue> +		  <pr:Person si:type="pr:PhysicalPersonType" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:si="http://www.w3.org/2001/XMLSchema-instance"> +			 <pr:Identification> +				<pr:Value>K2YMyx3/5kIpNJR+SAD/rbRYH+c=</pr:Value> +				<pr:Type>urn:publicid:gv.at:wbpk+FN+www.act.at</pr:Type> +			 </pr:Identification> +			 <pr:Name> +				<pr:GivenName>Thomas</pr:GivenName> +				<pr:FamilyName primary="undefined">Knall</pr:FamilyName> +			 </pr:Name> +			 <pr:DateOfBirth>1978-04-29</pr:DateOfBirth> +		  </pr:Person> +		</saml:AttributeValue> +	 </saml:Attribute> +	 <saml:Attribute AttributeName="isQualifiedCertificate" AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#"> +		<saml:AttributeValue>true</saml:AttributeValue> +	 </saml:Attribute> +	 <saml:Attribute AttributeName="bkuURL" AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#"> +		<saml:AttributeValue>https://127.0.0.1:3496/https-security-layer-request</saml:AttributeValue> +	 </saml:Attribute> +	 <saml:Attribute AttributeName="SignerCertificate" AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#"> +		<saml:AttributeValue>MIIEtDCCA5ygAwIBAgIDAgTEMA0GCSqGSIb3DQEBBQUAMIGXMQswCQYDVQQGEwJB +VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp +bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMR4wHAYDVQQLDBVhLXNpZ24tUHJl +bWl1bS1TaWctMDIxHjAcBgNVBAMMFWEtc2lnbi1QcmVtaXVtLVNpZy0wMjAeFw0w +NjA0MDQwOTUyMjhaFw0xMTA0MDQwOTUyMjhaMGkxCzAJBgNVBAYTAkFUMRUwEwYD +VQQDDAxUaG9tYXMgS25hbGwxDjAMBgNVBAQMBUtuYWxsMQ8wDQYDVQQqDAZUaG9t +YXMxFTATBgNVBAUTDDUzNTE5ODkyMzM0OTELMAkGA1UEDAwCREkwSTATBgcqhkjO +PQIBBggqhkjOPQMBAQMyAARrnYW5sXCQ6M3irWaanDPi/ROXueKWiPRyZGjNH0Cp +/NaiOuvrpv2RDVEKQm2tBiajggIPMIICCzATBgNVHSMEDDAKgAhN3+H/S9nJ3zAn +BggrBgEFBQcBAwEB/wQYMBYwCAYGBACORgEBMAoGCCsGAQUFBwsBMHsGCCsGAQUF +BwEBBG8wbTBCBggrBgEFBQcwAoY2aHR0cDovL3d3dy5hLXRydXN0LmF0L2NlcnRz +L2Etc2lnbi1QcmVtaXVtLVNpZy0wMmEuY3J0MCcGCCsGAQUFBzABhhtodHRwOi8v +b2NzcC5hLXRydXN0LmF0L29jc3AwWQYDVR0gBFIwUDBEBgYqKAARAQswOjA4Bggr +BgEFBQcCARYsaHR0cDovL3d3dy5hLXRydXN0LmF0L2RvY3MvY3AvYS1zaWduLVBy +ZW1pdW0wCAYGBACLMAEBMIGaBgNVHR8EgZIwgY8wgYyggYmggYaGgYNsZGFwOi8v +bGRhcC5hLXRydXN0LmF0L291PWEtc2lnbi1QcmVtaXVtLVNpZy0wMixvPUEtVHJ1 +c3QsYz1BVD9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0P2Jhc2U/b2JqZWN0Y2xh +c3M9ZWlkQ2VydGlmaWNhdGlvbkF1dGhvcml0eTARBgNVHQ4ECgQISNyH29WUoCgw +DgYDVR0PAQH/BAQDAgbAMCgGA1UdCQQhMB8wHQYIKwYBBQUHCQExERgPMTk3ODA0 +MjkwMDAwMDBaMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADggEBAFkSCJE0YD4p +4izU3ekQYPv4Z7gm/VFlpma5hXNvwkajVjHlAqo/ylYn8NQ4mMkD+yCDNtm8m8nr +0K/yICb8Gnkbv59i6nh2AbzYBBb49VnYYGL6uunLH0aFUpAhy+3mDdlH8uhhIQBH +wCfgwG1qa5zXY7bz4Vzkac/h6T+JVFkIegO8OHQDadhgJvW80qspiao2DTac6vVg +x4tGvjpdmw1R2pXBYhHD5rkPHlkfGoeL3ak6hq4ea94Oy5VfNTIJv5MA0J2G1mwn +W9B8uPWSM5EYPoWJyBOWcKBLSSUqOt9D/9215ZGfbchkdRZjx0dTAD3FIhgG8nA7 +2/uCFrBzyTk=</saml:AttributeValue> +	 </saml:Attribute> +	 <saml:Attribute AttributeName="Mandate" AttributeNamespace="http://reference.e-government.gv.at/namespace/mandates/20040701#"> +		<saml:AttributeValue> +		  <md:Mandate MandateID="https://egov.act.at/mandates/20080714174835/886164" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:md="http://reference.e-government.gv.at/namespace/mandates/20040701#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#"> +			 <md:Annotation>Prokura - MeineTestFirma</md:Annotation> +			 <md:StatusInformationService>http://localhost:58080/omsp/OMSPRequest</md:StatusInformationService> +			 <md:Representative> +				<pr:PhysicalPerson> +				  <pr:Identification> +					 <pr:Value>K2YMyx3/5kIpNJR+SAD/rbRYH+c=</pr:Value> +					 <pr:Type>urn:publicid:gv.at:wbpk+FN+www.act.at</pr:Type> +				  </pr:Identification> +				  <pr:Name> +					 <pr:GivenName>Thomas</pr:GivenName> +					 <pr:FamilyName primary="undefined">Knall</pr:FamilyName> +				  </pr:Name> +				  <pr:DateOfBirth>1978-04-29</pr:DateOfBirth> +				</pr:PhysicalPerson> +			 </md:Representative> +			 <md:Mandator> +				<pr:CorporateBody> +				  <pr:Identification> +					 <pr:Value>123456i</pr:Value> +					 <pr:Type>urn:publicid:gv.at:baseid+XFN</pr:Type> +				  </pr:Identification> +				  <pr:FullName>MeineTestFirma</pr:FullName> +				</pr:CorporateBody> +			 </md:Mandator> +			 <md:Issued> +				<md:Place>Wien</md:Place> +				<md:Date>2008-07-14</md:Date> +			 </md:Issued> +			 <md:Properties> +				<md:SubstitutionAllowed>false</md:SubstitutionAllowed> +			 </md:Properties> +			 <md:SimpleMandateContent> +				<md:TextualDescription>Der/Die Bevollmächtigte wird zum Prokuristen/Prokuristin bestellt.</md:TextualDescription> +			 </md:SimpleMandateContent> +			 <dsig:Signature Id="signature-1-1" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> +				<dsig:SignedInfo> +				  <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> +				  <dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"/> +				  <dsig:Reference Id="reference-1-1" URI=""> +					 <dsig:Transforms> +						<dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> +						  <dsig:XPath xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:moa="http://reference.e-government.gv.at/namespace/moa/20020822#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#">not(ancestor-or-self::pr:Identification or ancestor-or-self::dsig:Signature)</dsig:XPath> +						</dsig:Transform> +						<dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> +						<dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> +					 </dsig:Transforms> +					 <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +					 <dsig:DigestValue>PRRF0sWBgoywztCKWEXafZfhpd0=</dsig:DigestValue> +				  </dsig:Reference> +				  <dsig:Reference Type="http://www.w3.org/2000/09/xmldsig#Manifest" URI="#dsig-manifest-1-1"> +					 <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +					 <dsig:DigestValue>NorNorUqPFMA06JfxSJopOq7Qv0=</dsig:DigestValue> +				  </dsig:Reference> +				</dsig:SignedInfo> +				<dsig:SignatureValue>IQMZFc57XZd9LjeiaZqSfzZtWuXhuikAqbKA7pWuDK02DLFSYZPXsGjcvnwNdVaP</dsig:SignatureValue> +				<dsig:KeyInfo> +				  <dsig:X509Data> +					 <dsig:X509Certificate>MIICtjCCAm6gAwIBAgIBATAJBgcqhkjOPQQBMGoxCzAJBgNVBAYTAkFUMQ0wCwYD +VQQHEwRXaWVuMRkwFwYDVQQJExBFc3NsaW5nZ2Fzc2UgNS85MQwwCgYDVQQKEwNB +Q1QxIzAhBgNVBAMTGlZvbGxtYWNodGVuIFNpZ25hdHVyZGllbnN0MB4XDTA4MDcw +ODE1MTk1MFoXDTEyMTIzMTIxNTk1OVowajELMAkGA1UEBhMCQVQxDTALBgNVBAcT +BFdpZW4xGTAXBgNVBAkTEEVzc2xpbmdnYXNzZSA1LzkxDDAKBgNVBAoTA0FDVDEj +MCEGA1UEAxMaVm9sbG1hY2h0ZW4gU2lnbmF0dXJkaWVuc3QwgfMwgbwGByqGSM49 +AgEwgbACAQEwJAYHKoZIzj0BAQIZAP////////////////////7//////////zA0 +BBj////////////////////+//////////wEGGQhBRnlnIDnD6fpq3IkMEn+uN7s +wUa5sQQxBBiNqA6wMJD2fL8g60OhiAD0/wr9gv8QEgcZK5X/yNp4YxAR7WskzdVz ++XehHnlIEQIZAP///////////////5ne+DYUa8mxtNIoMQIBAQMyAAS908G9FD5/ +LLYruwFbp9giXahdQ1FAqKwzohSn9pgsVTQBnvXxU8IWIzhPHs49DZCjazBpMAwG +A1UdEwEB/wQCMAAwHQYDVR0OBBYEFLOSgnkLSJ3l4Ah49rHX/FAV1wWcMBkGA1Ud +IAQSMBAwDgYMKwYBBAGVEgECBAEBMB8GA1UdIwQYMBaAFLOSgnkLSJ3l4Ah49rHX +/FAV1wWcMAkGByqGSM49BAEDNwAwNAIYTTppZzS6wqoLDFcf9frHzf1kMheY04dT +Ahg4Nrb54vE3DTRf9sbO4xs4dTARHSt1ihA=</dsig:X509Certificate> +				  </dsig:X509Data> +				</dsig:KeyInfo> +				<dsig:Object> +				  <dsig:Manifest Id="dsig-manifest-1-1"> +					 <dsig:Reference Id="reference-1-2" URI=""> +						<dsig:Transforms> +						  <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> +							 <dsig:XPath xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:moa="http://reference.e-government.gv.at/namespace/moa/20020822#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#">not(ancestor-or-self::dsig:Signature)</dsig:XPath> +						  </dsig:Transform> +						  <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> +						  <dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> +						</dsig:Transforms> +						<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +						<dsig:DigestValue>oz6ThHPL3V7RNibfPrDSWVhUgi8=</dsig:DigestValue> +					 </dsig:Reference> +				  </dsig:Manifest> +				</dsig:Object> +			 </dsig:Signature> +		  </md:Mandate> +		</saml:AttributeValue> +	 </saml:Attribute> +  </saml:AttributeStatement> +</saml:Assertion> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/SignedAuthBlock.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/SignedAuthBlock.xml new file mode 100644 index 000000000..450ba90f3 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/SignedAuthBlock.xml @@ -0,0 +1,179 @@ +<?xml version="1.0" encoding="UTF-8"?> +<dsig:Signature Id="signature-1216050695-35956125-21395" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> +  <dsig:SignedInfo> +	 <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> +	 <dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"/> +	 <dsig:Reference Id="signed-data-reference-0-1216050695-35956125-19584" URI=""> +		<dsig:Transforms> +		  <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> +		  <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116"> +			 <xsl:stylesheet version="1.0" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> +				<xsl:template match="/" xmlns="http://www.w3.org/1999/xhtml"> +				  <html xmlns="http://www.w3.org/1999/xhtml"> +					 <head> +						<title>Signatur der Anmeldedaten</title> +						<style media="screen" type="text/css"> +.boldstyle { font-weight: bold; } +.italicstyle { font-style: italic; } +.annotationstyle { font-size: small; } +</style> +					 </head> +					 <body> +						<h1>Signatur der Anmeldedaten</h1> +						<p/> +						<h4>Mit meiner elektronischen Signatur beantrage ich, +<span class="boldstyle"> +							 <xsl:value-of select="//@Issuer"/> +						  </span>, geboren am +<xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,9,2)"/>. +<xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,6,2)"/>. +<xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,1,4)"/>, +<xsl:if test="//saml:Attribute[@AttributeName='OIDTextualDescription']"> +in der Rolle als <xsl:value-of select="//saml:Attribute[@AttributeName='OIDTextualDescription']/saml:AttributeValue"/> +(OID***= <xsl:value-of select="//saml:Attribute[@AttributeName='OID']/saml:AttributeValue"/>), +</xsl:if> +den Zugang zur gesicherten Anwendung. +</h4> +						<p/> +						<h4>Datum und Uhrzeit: +<xsl:value-of select="substring(//@IssueInstant,9,2)"/>. +<xsl:value-of select="substring(//@IssueInstant,6,2)"/>. +<xsl:value-of select="substring(//@IssueInstant,1,4)"/>, +<xsl:value-of select="substring(//@IssueInstant,12,2)"/>: +<xsl:value-of select="substring(//@IssueInstant,15,2)"/>: +<xsl:value-of select="substring(//@IssueInstant,18,2)"/> +						</h4> +						<xsl:if test="//saml:Attribute[@AttributeName='HPI']"> +						  <h4>HPI(**): <xsl:value-of select="//saml:Attribute[@AttributeName='HPI']/saml:AttributeValue"/> +						  </h4> +						</xsl:if> +						<xsl:if test="//saml:Attribute[@AttributeName='wbPK']"> +						  <h4>wbPK(*): <xsl:value-of select="//saml:Attribute[@AttributeName='wbPK']/saml:AttributeValue/pr:Identification/pr:Value"/> +						  </h4> +						</xsl:if> +						<xsl:if test="//saml:Attribute[@AttributeName='MandatorName']"> +						  <hr/> +						  <h4>Ich bin weiters ermächtigt als <xsl:value-of select="//saml:Attribute[@AttributeName='RepresentationType']/saml:AttributeValue/text()"/> +von <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorName']/saml:AttributeValue/text()"/> +							 <xsl:if test="//saml:Attribute[@AttributeName='MandatorDateOfBirth']">, geboren am +  <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,9,2)"/>. +  <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,6,2)"/>. +  <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,1,4)"/> +							 </xsl:if> +							 <xsl:if test="//saml:Attribute[@AttributeName='MandatorDomainIdentifier']">, +  <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorDomainIdentifier']/saml:AttributeValue/text()"/> +							 </xsl:if>, in deren Auftrag zu handeln. +</h4> +						  <xsl:if test="//saml:Attribute[@AttributeName='MandatorWbpk']"> +							 <h4>wbPK(*) des Vollmachtgebers: <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorWbpk']/saml:AttributeValue/text()"/> +							 </h4> +						  </xsl:if> +						  <p/> +						</xsl:if> +						<xsl:choose> +						  <xsl:when test="//saml:Attribute[@AttributeName='OID']"> +							 <p/> +							 <hr/> +						  </xsl:when> +						  <xsl:when test="//saml:Attribute[@AttributeName='HPI']"> +							 <p/> +							 <hr/> +						  </xsl:when> +						  <xsl:when test="//saml:Attribute[@AttributeName='wbPK']"> +							 <p/> +							 <hr/> +						  </xsl:when> +						</xsl:choose> +						<xsl:if test="//saml:Attribute[@AttributeName='wbPK']"> +						  <div class="annotationstyle">(*) wbPK: Das <span class="italicstyle">wirtschaftsbereichsspezifische Personenkennzeichen</span> wird aus den +jeweiligen Stammzahlen des Bürgers und des Wirtschaftsunternehmens berechnet und ermöglicht eine eindeutige Zuordnung des Bürgers zum +Wirtschaftsunternehmen.</div> +						</xsl:if> +						<xsl:if test="//saml:Attribute[@AttributeName='HPI']"> +						  <div class="annotationstyle">(**) HPI: Der <span class="italicstyle">eHealth Professional Identifier</span> wird aus den jeweiligen +Stammzahlen der Gesundheitsdiensteanbieterinnen / Gesundheitsdiensteanbieter berechnet und ermöglicht eine eindeutige Zuordnung der +Gesundheitsdiensteanbieterin / des Gesundheitsdiensteanbieters im Gesundheitsbereich.</div> +						</xsl:if> +						<xsl:if test="//saml:Attribute[@AttributeName='OID']"> +						  <div class="annotationstyle">(***) OID: <span class="italicstyle">Object Identifier</span> sind standardisierte Objekt-Bezeichner und +beschreiben eindeutig die Rollen des GDA-Token Inhabers.</div> +						</xsl:if> +					 </body> +				  </html> +				</xsl:template> +			 </xsl:stylesheet> +		  </dsig:Transform> +		  <dsig:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/> +		</dsig:Transforms> +		<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +		<dsig:DigestValue>0q9QWyqAyyiVNNLu1rIcU+nKsEE=</dsig:DigestValue> +	 </dsig:Reference> +	 <dsig:Reference Id="etsi-data-reference-0-1216050695-35956125-7815" Type="http://uri.etsi.org/01903/v1.1.1#SignedProperties" URI="#xmlns(etsi=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('etsi-data-object-0-1216050695-35956125-20638')/child::etsi:QualifyingProperties/child::etsi:SignedProperties)"> +		<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +		<dsig:DigestValue>WtB0/ptvoB/r/7+fauSUIBULymg=</dsig:DigestValue> +	 </dsig:Reference> +  </dsig:SignedInfo> +  <dsig:SignatureValue>mZt9DuZiDqG81scsf30qjSDdy6vKC2/n034ZZwMUAvfWOXy3+Ubsk5X5CHhz ++lyI</dsig:SignatureValue> +  <dsig:KeyInfo> +	 <dsig:X509Data> +		<dsig:X509Certificate>MIIEtDCCA5ygAwIBAgIDAgTEMA0GCSqGSIb3DQEBBQUAMIGXMQswCQYDVQQG +EwJBVDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lz +dGVtZSBpbSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMR4wHAYDVQQLDBVh +LXNpZ24tUHJlbWl1bS1TaWctMDIxHjAcBgNVBAMMFWEtc2lnbi1QcmVtaXVt +LVNpZy0wMjAeFw0wNjA0MDQwOTUyMjhaFw0xMTA0MDQwOTUyMjhaMGkxCzAJ +BgNVBAYTAkFUMRUwEwYDVQQDDAxUaG9tYXMgS25hbGwxDjAMBgNVBAQMBUtu +YWxsMQ8wDQYDVQQqDAZUaG9tYXMxFTATBgNVBAUTDDUzNTE5ODkyMzM0OTEL +MAkGA1UEDAwCREkwSTATBgcqhkjOPQIBBggqhkjOPQMBAQMyAARrnYW5sXCQ +6M3irWaanDPi/ROXueKWiPRyZGjNH0Cp/NaiOuvrpv2RDVEKQm2tBiajggIP +MIICCzATBgNVHSMEDDAKgAhN3+H/S9nJ3zAnBggrBgEFBQcBAwEB/wQYMBYw +CAYGBACORgEBMAoGCCsGAQUFBwsBMHsGCCsGAQUFBwEBBG8wbTBCBggrBgEF +BQcwAoY2aHR0cDovL3d3dy5hLXRydXN0LmF0L2NlcnRzL2Etc2lnbi1QcmVt +aXVtLVNpZy0wMmEuY3J0MCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5hLXRy +dXN0LmF0L29jc3AwWQYDVR0gBFIwUDBEBgYqKAARAQswOjA4BggrBgEFBQcC +ARYsaHR0cDovL3d3dy5hLXRydXN0LmF0L2RvY3MvY3AvYS1zaWduLVByZW1p +dW0wCAYGBACLMAEBMIGaBgNVHR8EgZIwgY8wgYyggYmggYaGgYNsZGFwOi8v +bGRhcC5hLXRydXN0LmF0L291PWEtc2lnbi1QcmVtaXVtLVNpZy0wMixvPUEt +VHJ1c3QsYz1BVD9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0P2Jhc2U/b2Jq +ZWN0Y2xhc3M9ZWlkQ2VydGlmaWNhdGlvbkF1dGhvcml0eTARBgNVHQ4ECgQI +SNyH29WUoCgwDgYDVR0PAQH/BAQDAgbAMCgGA1UdCQQhMB8wHQYIKwYBBQUH +CQExERgPMTk3ODA0MjkwMDAwMDBaMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEF +BQADggEBAFkSCJE0YD4p4izU3ekQYPv4Z7gm/VFlpma5hXNvwkajVjHlAqo/ +ylYn8NQ4mMkD+yCDNtm8m8nr0K/yICb8Gnkbv59i6nh2AbzYBBb49VnYYGL6 +uunLH0aFUpAhy+3mDdlH8uhhIQBHwCfgwG1qa5zXY7bz4Vzkac/h6T+JVFkI +egO8OHQDadhgJvW80qspiao2DTac6vVgx4tGvjpdmw1R2pXBYhHD5rkPHlkf +GoeL3ak6hq4ea94Oy5VfNTIJv5MA0J2G1mwnW9B8uPWSM5EYPoWJyBOWcKBL +SSUqOt9D/9215ZGfbchkdRZjx0dTAD3FIhgG8nA72/uCFrBzyTk= +</dsig:X509Certificate> +	 </dsig:X509Data> +  </dsig:KeyInfo> +  <dsig:Object Id="etsi-data-object-0-1216050695-35956125-20638"> +	 <etsi:QualifyingProperties Target="#signature-1216050695-35956125-21395" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#"> +		<etsi:SignedProperties> +		  <etsi:SignedSignatureProperties> +			 <etsi:SigningTime>2008-07-14T15:51:35Z</etsi:SigningTime> +			 <etsi:SigningCertificate> +				<etsi:Cert> +				  <etsi:CertDigest> +					 <etsi:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +					 <etsi:DigestValue>inMYWBmAxMHP7mDENjLFaEtv0Zk=</etsi:DigestValue> +				  </etsi:CertDigest> +				  <etsi:IssuerSerial> +					 <dsig:X509IssuerName>CN=a-sign-Premium-Sig-02,OU=a-sign-Premium-Sig-02,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT</dsig:X509IssuerName> +					 <dsig:X509SerialNumber>132292</dsig:X509SerialNumber> +				  </etsi:IssuerSerial> +				</etsi:Cert> +			 </etsi:SigningCertificate> +			 <etsi:SignaturePolicyIdentifier> +				<etsi:SignaturePolicyImplied/> +			 </etsi:SignaturePolicyIdentifier> +		  </etsi:SignedSignatureProperties> +		  <etsi:SignedDataObjectProperties> +			 <etsi:DataObjectFormat ObjectReference="#signed-data-reference-0-1216050695-35956125-19584"> +				<etsi:MimeType>application/xhtml+xml</etsi:MimeType> +			 </etsi:DataObjectFormat> +		  </etsi:SignedDataObjectProperties> +		</etsi:SignedProperties> +	 </etsi:QualifyingProperties> +  </dsig:Object> +</dsig:Signature>
\ No newline at end of file diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_MultipleStartEvents.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_MultipleStartEvents.xml new file mode 100644 index 000000000..17fa17cb4 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_MultipleStartEvents.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:ProcessDefinition +	id="SampleProcess2" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd "> + +	<tns:StartEvent id="start1" /> + +	<tns:Task id="task1" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task2" async="true" class="at.gv.egovernment.moa.id.process.test.HalloWeltTask" /> +	<tns:Task id="task3" /> + +	<tns:StartEvent id="start2" /> +	<tns:EndEvent id="end" /> + +	<tns:Transition id="fromStart" from="start1" to="task1" conditionExpression="true" /> +	<tns:Transition from="task1" to="task2" /> +	<tns:Transition from="task2" to="task3" /> +	<tns:Transition from="task3" to="end" /> +	 +</tns:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_NoStartEvents.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_NoStartEvents.xml new file mode 100644 index 000000000..008309e3a --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_NoStartEvents.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:ProcessDefinition +	id="SampleProcess1" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd "> + +	<tns:Task id="task1" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task2" async="true" /> + +	<tns:EndEvent id="end" /> + +	<tns:Transition from="task1" to="task2" /> +	<tns:Transition from="task2" to="end" /> +	 +</tns:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionLoop.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionLoop.xml new file mode 100644 index 000000000..14b281192 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionLoop.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:ProcessDefinition +	id="SampleProcess1" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd "> + +	<tns:Task id="task1" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task2" async="true" /> + +	<tns:StartEvent id="start" /> +	<tns:EndEvent id="end" /> + +	<tns:Transition id="fromStart" from="start" to="task1" conditionExpression="true" /> +	<tns:Transition from="task1" to="task2" /> +	<tns:Transition from="task2" to="end" /> + +	<!-- Must be loop since we have no conditionExpression set. --> +	<tns:Transition id="loop" from="task1" to="task1" /> +	 +</tns:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionRefsTransition.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionRefsTransition.xml new file mode 100644 index 000000000..1152f3503 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionRefsTransition.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:ProcessDefinition +	id="SampleProcess1" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd "> + +	<tns:Task id="task1" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task2" async="true" /> + +	<tns:StartEvent id="start" /> +	<tns:EndEvent id="end" /> + +	<tns:Transition id="fromStart" from="start" to="task1" conditionExpression="true" /> +	<tns:Transition from="task1" to="task2" /> +	<tns:Transition id="invalidTransition" from="task1" to="fromStart" /> +	<tns:Transition from="task2" to="end" /> +	 +</tns:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionStartsFromEndEvent.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionStartsFromEndEvent.xml new file mode 100644 index 000000000..94bd25c9a --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionStartsFromEndEvent.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:ProcessDefinition +	id="SampleProcess1" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd "> + +	<tns:Task id="task1" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task2" async="true" /> + +	<tns:StartEvent id="start" /> +	<tns:EndEvent id="end" /> + +	<tns:Transition id="fromStart" from="start" to="task1" conditionExpression="true" /> +	<tns:Transition from="task1" to="task2" /> +	<tns:Transition from="task2" to="end" /> +	<tns:Transition from="end" to="task1" /> +	 +</tns:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/SampleProcessDefinition1.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/SampleProcessDefinition1.xml new file mode 100644 index 000000000..c161900c5 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/SampleProcessDefinition1.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:ProcessDefinition +	id="SampleProcess1" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd "> + +	<tns:Task id="task1" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task2" async="true" /> + +	<tns:StartEvent id="start" /> +	<tns:EndEvent id="end" /> + +	<tns:Transition id="fromStart" from="start" to="task1" conditionExpression="true" /> +	<tns:Transition from="task1" to="task2" /> +	<tns:Transition from="task2" to="end" /> +	 +</tns:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/SampleProcessDefinition2.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/SampleProcessDefinition2.xml new file mode 100644 index 000000000..9e419e124 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/SampleProcessDefinition2.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:ProcessDefinition +	id="SampleProcess2" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd "> + +	<tns:StartEvent id="start" /> + +	<tns:Task id="task1" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task2" async="true" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task3" /> + +	<tns:EndEvent id="end" /> + +	<tns:Transition id="fromStart" from="start" to="task1" conditionExpression="true" /> +	<tns:Transition from="task1" to="task2" /> +	<tns:Transition from="task2" to="task3" /> +	<tns:Transition from="task3" to="end" /> +	 +</tns:ProcessDefinition> | 
