|
SAcctUserGuide_0_1_0
IntroductionIn the Payment Card Industry (PCI), security is always a major concern. A lot of enterprise applications have application passwords hard-coded in configuration files, which are not allowed by the Payment Card Industry Data Security Standard (PCI DSS). Smart Account Management (SAcct) is a light-weight Security Framework to ease your pain of removing the account passwords from application configuration files. The SAcct server reads in the account information from a secured soft token and acts as an account server. The SAcct client communicates with the SAcct Server over a secured channel to retrieve account passwords on behalf of the application on start-up. In this way, you also gain the benefit that you have a central place to manage your application accounts. Key WordsSecurity, Password, Application Account, Encrypt, Decrypt, Diffie-Hellman Key Exchange, One Time Password, PCI Compliance, JSON, Java, Spring, Guice, Maven. Problems and ChallengesTake a Spring application as an example, the following wiring file includes a database user name and a user password, <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="100"/>
<property name="maxWait" value="1000"/>
<property name="poolPreparedStatements" value="true"/>
<property name="defaultAutoCommit" value="true"/>
</bean>To put the database user password into the configuration file is a serious security problem and it is not allowed by the Payment Card Industry Data Security Standard (PCI DSS). Some frameworks try to encrypt the passwords, but they still need to wire in the encryption password, which does not really solve the problem. We propose to store the accounts in a secured token file, which you can put into a USB drive or other secured devices, then the SAcct framework can retrieve them on behalf of the application during the application start-up phase. SAcct FeaturesSAcct is a Java application and suitable for Enterprise Java applications. SAcct features are highlighted as follows,
SAcct ModulesThe SAcct 0.1.0 code structure is as follows, sacct-0.1.0
|-- assembly
| `-- sacct-server
|-- sacct-client
|-- sacct-common
|-- sacct-server
`-- tools
`-- sacct-springSAcct 0.1.0 includes the following modules
SAcct ArchitectureThe SAcct architecture is shown in the following diagram,
SAcct ServerThe SAcct server is a standalone Java application and it listens on a TCP port for requests. Upon receiving a request, it creates a socket worker from the thread pool to process the request. The SAcct server mainly consists of the following components:
SAcct ClientThe SAcct client is usually one part of the business application. It derives the session key by exchanging information with the SAcct server based on the Diffie-Hellman Key Exchange protocol and then stores the session information in a token. The SAcct client also includes a socket connector to communicate with the SAcct server. All requests are encrypted except the session id as shown in the above system diagram. Be aware, there is no key transmitted over the socket channel. The SAcct server and the client derive the same key on their own based on the Diffie-Hellman Key Exchange protocol. Message FormatsThe client request is represented by the Request Java class public class Request {
//a random string padding to the request
private String rnd;
private String command;
private RequestContext requestContext;
private List parameters;
}where the RequestContext is defined as public class RequestContext {
private String locale;
private String clientId;
//Use One Time Password sequence in the requestId to prevent session replay attack
private String requestId;
}and the command is the service call name, which will be described later. The actual request being sent over the socket channel is the SecureRequest public class SecureRequest{
private String sessionId;
private String request;Where the original request is first converted into a JSON string, compressed, encrypted with the session key, and then encoded in the base 64 format. Similarly, the response class is defined as follows, public class Response extends Entity {
//a random string padding to the response
private String rnd;
private String command;
private boolean isSuccessful;
private String errorCode;
protected List returnValue;
}The SAcct server will convert any exception to the isSuccessful flag and the error code so that the client knows how to react to different exceptions. The response is also converted to a JSON string, compressed, encrypted, and then encoded in the base 64 format. public class SecureResponse {
private String response;
}ServicesThe SAcct server provides two services, i.e., SessionService and AccountService. The SessionService is used to initiate and close sessions. public interface SessionService extends Service{
SessionInfo handshake(RequestContext context, String clientPubKey);
String closeSession(RequestContext context, String goodbye);
String hello(RequestContext context);
}and AccountService handles all account-related requests. public interface AccountService extends Service{
ApplicationAccount fetchAccount(RequestContext context, String account);
List<ApplicationAccount> fetchAllAccounts(RequestContext context);
}Communication FlowsLet's look a bit closer at the communication flows in the architecture diagram.
The communication flows can be better illustrated by the following sequence diagram, Apart from the above message flows, the SAcct server also provides a hello service call for the client to do health check with the server. Account TokenThe SAcct server reads in the account token on start-up. The plain text token is in the JSON format: {
"records" :
[
{
"accounts" :
[
{
"name" : "custApp",
"password" : "PwD4CustApp"
},
{
"name" : "prodApp",
"password" : "PwD4ProdApp"
}
],
"clientId" : "server"
},
{
"accounts" :
[
{
"name" : "johnfang@mycompany.com",
"password" : "P@ssword"
},
{
"name" : "johnfang@myhome.com",
"password" : "P@ssw0rd"
}
],
"clientId" : "jianfang"
}
]
}For each client, you need to provide a client id and then add the account information into the token file. SAcct provides two utility scripts, i.e., encrypt and decrypt, for you to encrypt and decrypt the account token file. The encrypted token file looks like the following string, CnUWakPDCwjhYijf7cyxw0ScugrHuWFkv+4LV8TJnn5kK8/o25lWBnHgc0JuQOLXhO/Dc71vF4jAKiiQl7EHc5/gFF5+r9G/TmXBx6kkynfuh8giq2TISxgatlp/gpxbzEs9SZ9kF1iYaH20TgZq/zpbPXc0+HIefwIT9VjW8deUrr9h/0b/qHb9NVFJ438gK4T/u6pqxxeGDmYIzQkWZg== How to Obtain SAcctDirect DownloadSAcct includes two parts, i.e., SAcct Server and SAcct client. You should download the SAcct server and other jar files from the SAcct download page. For a regular Java application, you will need the following jar files
For a Spring application, you need one more extra jar file
MavenTo obtain SAcct from Maven, you need to add SAcct Maven repositories to your Maven settings.xml or your project POM file. <repository>
<id>kungfuters-public-releases-repo</id>
<name>Kungfuters.org Public Releases Repository</name>
<url>http://kungfuters.org/nexus/content/repositories/releases</url>
</repository>
<snapshotRepository>
<id>kungfuters-public-snapshots-repo</id>
<name>Kungfuters.org Public Snapshot Repository</name>
<url>http://kungfuters.org/nexus/content/repositories/snapshots</url>
</snapshotRepository>For a regular Java application, please include the following Maven dependencies <dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>caja</groupId>
<artifactId>json_simple</artifactId>
<version>r1</version>
</dependency>
<dependency>
<groupId>org.stringtree</groupId>
<artifactId>stringtree-json</artifactId>
<version>2.0.10</version>
<dependency>
<groupId>org.osomit</groupId>
<artifactId>sacct-common</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>org.osomit</groupId>
<artifactId>sacct-client</artifactId>
<version>0.1.0</version>
</dependency>For a Spring application, you need the following extra dependency <dependency>
<groupId>org.osomit</groupId>
<artifactId>sacct-spring</artifactId>
<version>0.1.0</version>
</dependency>
How to Use SAcctSAcct ServerPrerequisitesSince SAcct uses the AES algorithm for encryption, you need to use Java 6 and download it from the Sun JDK download page. On the same page, you also need to download Java 6 Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files in the Other Downloads section. Then unzip the file jce_policy-6.zip and move local_policy.jar and US_export_policy.jar to JAVA_HOME/jre/lib/security. StructureThe SAcct Server is a standalone Java application and the application structure is listed as follows, sacct-server-0.1.0/
|-- LICENSE.txt
|-- README.txt
|-- bin
| |-- decrypt
| |-- encrypt
| `-- sacct_server
|-- conf
| |-- log4j.xml
| `-- sacct.properties
|-- data
| `-- accounts.reg
|-- lib
| |-- antlr.jar
| |-- aopalliance.jar
| |-- avalon-framework.jar
| |-- commons-codec.jar
| |-- commons-logging.jar
| |-- guice.jar
| |-- json_simple.jar
| |-- jsontools-core.jar
| |-- log4j.jar
| |-- logkit.jar
| |-- sacct-common.jar
| |-- sacct-server.jar
| `-- stringtree-json.jar
`-- logs
`-- sacct.logThe conf directory includes the SAcct global configuration file, sacct.properties, and Log4J configuration file, log4j.xml. The data directory includes a sample account token, accounts.reg, which is encrypted using the AES algorithm with the default password P@ssw0rd. Manage the Account TokenThe bin directory includes two utility scripts, encrypt and decrypt, for you to manage the soft token file. For example, use the following command to decrypt the account token file, ./decrypt ../data/accounts.reg accounts.txt You will see the decrypted account file in the JSON format. You can update the plain text token file and encrypt it again. ./encrypt accounts.txt accounts.reg Then replace the old token file with the new one mv accounts.reg ../data/accounts.reg Remember to remove the plain text token file after you are done. rm accounts.txt Configure the ServerThe SAcct server configuration file, sacct.properties, is pretty simple and self-explaining, useOTP = false <---Whether to use One Time Password to prevent session replay attack sessionExpirationPolicy = IdleTimeout <-- This is the only option now idletimeInMilliSeconds = 3000000 <--- Session maximum idle time in milliseconds maxSessionNum = 200 <--- Maximum concurrent sessions numToCleanSession = 25 <--- Clean up the session when the session number is builtup accountFileName = accounts.reg <--- Account token file serverPort = 9000 <--- SAcct server service port poolSize = 12 <--- Thread pool size randomIdLength = 12 <--- Session Id random part size Be aware, if you turn on the One Time Password (OTP), SAcct client must also turn on this feature. Start the ServerGo to the bin directory and run ./sacct_server You can simply use Contrl+C to stop the server. The SAcct server shutdown hook will do all the cleanup work before it exits. Windows SystemThe shell scripts are for Unix/Linux systems. If you need to run the SAcct Server in a Window system, you can create the Window batch scripts very easily based on these scripts. SAcct ClientAccount ProviderThe Account Provider is an abstraction of the SAcct client and the interface is defined as, public interface AccountProvider {
public boolean isActive();
public String getAccountPassword(String accountName);
}The account provider implementation also need to implement the following AccountProviderCifeCycle interface, public interface AccountProviderLifeCycle {
public void create();
public void destroy();
}Regular Java ApplicationsFor regular Java applications, SAcct provides a default Account Provider implementation, org.osomit.sacct.provider.imp.AccountProviderImpl, which has the following constructor public AccountProviderImpl(String clientId, String accountServerHost, int accountServerPort, boolean useOTP, boolean isActive) The AccountProviderImpl class provides the follow methods at your disposal, public void create(); public boolean isActive(); public String getAccountPassword(String accountName); public void destroy(); Spring ApplicationsThe sacct-spring module provides two factory beans for the Spring framework, i.e., AccountProviderFactoryBean and AccountFactoryBean. The AccountProviderFactoryBean is an encapsulation of the SAcct client and is responsible for communicating with the SAcct server to retrieve application accounts. It also handles the account provider lifecycle, i.e., create and destroy, automatically. The constructor of the SAcct account provider factory bean is defined as follows, public AccountProviderFactoryBean(String clientId, String accountServerHost, int accountServerPort, boolean useOTP, boolean active) In your Spring application, you can define the account provider similar to the following Spring bean. <bean id="accountProvider" class="org.osomit.sacct.provider.impl.spring.AccountProviderFactoryBean">
<constructor-arg index="0" type="java.lang.String" value="server"/> <-- Client ID
<constructor-arg index="1" type="java.lang.String" value="localhost"/> <-- SAcct Server Host
<constructor-arg index="2" value="9000"/> <-- SAcct Server Port
<constructor-arg index="3" value="false"/> <-- Wheather to Use One Time Password
<constructor-arg index="4" value="false"/> <-- Is active?
</bean>The AccountFactoryBean is used to provide the application password for an individual account. What it really does is to fetch the account information from the AccountProviderFactoryBean and its constructor is shown as follows, public AccountFactoryBean(AccountProvider provider, String accountName, String accountPassword) Optionally, you can provide the default/dummy password in the certain situations that the SAcct is not available. <bean id="databasepassword" class="org.osomit.sacct.provider.impl.spring.AccountFactoryBean">
<constructor-arg index="0" ref="accountProvider"/> <-- Account Provider
<constructor-arg index="1" value="${jdbc.username}"/> <-- Account Name
<constructor-arg index="2" value="defaultDataBasePwD"/> <-- Account default/dummy password (optional)
</bean>Finally, the dataSource bean can be rewritten as <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}">
<property name="password" ref="databasepassword"/> <-- Provide Data Source Password
<property name="maxActive" value="100"/>
<property name="maxWait" value="1000"/>
<property name="poolPreparedStatements" value="true"/>
<property name="defaultAutoCommit" value="true"/>
</bean>As you can see, you can turn off SAcct and switch back to original Spring wiring in some situation simply by setting the active flag in the "accountProvider" bean to be false. That's all and you do not need to change any other bean configuration. Resources |