001 package org.cumulus4j.keymanager.api;
002
003 import java.io.IOException;
004
005 /**
006 * <p>
007 * A <code>CryptoSession</code> is a session in which key transfers can be performed.
008 * </p><p>
009 * Use {@link KeyManagerAPI#getCryptoSession(String)} to get a <code>CryptoSession</code> instance.
010 * This instance is a proxy which can be kept and never expires (though the underlying real session will expire if
011 * not used for some time). If the underlying real
012 * session expired, a new underlying session with a new <code>cryptoSessionID</code>
013 * will be created and bound to this <code>CryptoSession</code> instance.
014 * </p><p>
015 * <code>CryptoSession</code>s are thread-safe.
016 * </p>
017 *
018 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
019 */
020 public interface CryptoSession
021 {
022 /**
023 * Get the identifier of the application server. This denotes a logical application server, which
024 * can be composed of many physical machines (in a cluster/cloud).
025 * @return the application server's ID; never <code>null</code>.
026 */
027 String getAppServerID();
028
029 /**
030 * Get the base-url of the app-server-key-manager-channel. This is the part of the URL before the "/KeyManagerChannel" -
031 * e.g. if the REST URL of the KeyManagerChannel-service is
032 * "https://serverUsingCumulus4j.mydomain.org/org.cumulus4j.keymanager.back.webapp/KeyManagerChannel", then this must be
033 * "https://serverUsingCumulus4j.mydomain.org/org.cumulus4j.keymanager.back.webapp".
034 * @return the base-URL before the "/KeyManagerChannel".
035 */
036 String getAppServerBaseURL();
037
038 /**
039 * <p>
040 * Acquire an unlocked underlying real session.
041 * </p><p>
042 * The application server is only able to request keys from the key manager, while a crypto-session is
043 * acquired. It thus needs to be acquired, first, before it can be used for key transfers.
044 * </p><p>
045 * <b>Important:</b> It is essential that you call {@link #release()} once for every time you called <code>acquire()</code>.
046 * You should therefore use a try-finally-block like this:
047 * </p>
048 * <pre>
049 * String cryptoSessionID = session.acquire();
050 * try {
051 *
052 * // Do some operation that requires key access. For example
053 * // call an EJB method or perform a SOAP/REST request which
054 * // will make your app server read/write data.
055 *
056 * } finally {
057 * session.release();
058 * }
059 * </pre>
060 * <p>
061 * If multiple threads use the same <code>CryptoSession</code> (recommended!), the underlying real session will be
062 * acquired (unlocked) when the first thread requires it and it will be locked again when the last thread calls
063 * <code>release()</code>.
064 * However, releasing (locking) does not need to happen immediately. Instead it can be deferred a few seconds, in
065 * case a new <code>acquire()</code> would happen quickly again. This
066 * strategy is usually used with a remote key server (when latency makes acquiring/releasing a pretty expensive
067 * operation).
068 * </p>
069 * @return the cryptoSessionID to be used within the acquire-release-block for key-management. This ID must be
070 * passed to your application server in order to allow it perform database operations.
071 * @throws AuthenticationException if the authentication fails. This might happen for example, when
072 * a session was created and then the password was modified by another instance of {@link KeyManagerAPI}.
073 * Calling {@link KeyManagerAPI#putUser(String, char[])} automatically updates the authentication information
074 * of the current <code>KeyManagerAPI</code> if the current user's password was changed. But if the password
075 * is changed by another instance, this instance is locked out due to its outdated password.
076 * @throws IOException if communication with the key-store failed. This might be a socket error between
077 * client and remote key server or it might be a problem when reading/writing data in the local file system.
078 * @see #release()
079 */
080 String acquire() throws AuthenticationException, IOException;
081
082 /**
083 * <p>
084 * Release the session, after it was previously {@link #acquire() acquired}.
085 * </p><p>
086 * For every call to {@link #acquire()}, there must be exactly one call to {@link #release()}. You should
087 * therefore use a try-finally-block!
088 * </p><p>
089 * See {@link #acquire()} for further details.
090 * </p>
091 *
092 * @throws AuthenticationException if the authentication fails. This might happen for example, when
093 * a session was created and then the password was modified by another instance of {@link KeyManagerAPI}.
094 * Calling {@link KeyManagerAPI#putUser(String, char[])} automatically updates the authentication information
095 * of the current <code>KeyManagerAPI</code> if the current user's password was changed. But if the password
096 * is changed by another instance, this instance is locked out due to its outdated password.
097 * @throws IOException if communication with the key-store failed. This might be a socket error between
098 * client and remote key server or it might be a problem when reading/writing data in the local file system.
099 * @see #acquire()
100 */
101 void release() throws AuthenticationException, IOException;
102 }