Deploying a Secure Store

The Security Guide presents several different ways to deploy and configure an Oracle NoSQL Database store for secure access. For convenience, this section describes one particular set of steps you can take to deploy and configure such a store. Whether you prefer the technique presented here or one of the other techniques presented in the Security Guide, a secure store must be deployed and configured in order to run the secure form of the example presented in this document. For each of the steps presented below, in addition to the assumptions made in the non-secure case, also assume the following:

  • For convenience, the password manager the store uses to store and retrieve passwords needed for access to keystores and truststores is a password file rather than an Oracle Wallet, which is available in only the Enterprise Edition of Oracle NoSQL Database.
  • For simplicity, all passwords are set to the value No_Sql_00.
  • The name of the user that accesses the store is example-user.

Given the above assumptions, you can follow the steps below to deploy a secure store, where each item from the given assumptions should be replaced with its comparable value specific to your particular environment.

Generate Configuration Files For Each Storage Node (SN)

On kv-host-1, execute the following command and enter the appropriate responses when prompted:

java -jar /opt/oracle/kv-ee/lib/kvstore.jar \
    makebootconfig \
    -root /u01/nosql/sn1/kvroot \
    -config config.xml \
    -port 5000 \
    -host kv-host-1 \
    -harange 5002,5007 \
    -num_cpus 0 \
    -memory_mb 200 \
    -capacity 1 \
    -storagedir /u01/nosql/sn1/data \
    -storagedirsize 10000000 \
    -store-security configure \
    -pwdmgr pwdfile \
    -kspwd No_Sql_00

Enter a password for the Java KeyStore: No_Sql_00<RETURN>
Re-enter the KeyStore password for verification: No_Sql_00<RETURN>

Created files
    /u01/nosql/sn1/kvroot/security/store.trust
    /u01/nosql/sn1/kvroot/security/store.keys
    /u01/nosql/sn1/kvroot/security/store.passwd
    /u01/nosql/sn1/kvroot/security/client.trust
    /u01/nosql/sn1/kvroot/security/security.xml
    /u01/nosql/sn1/kvroot/security/client.security

Specifying the value configure for the -store-security parameter in the above command generates the security artifacts (files) needed for the store’s nodes, as well as clients of the store, to communicate securely. Each of the artifacts must be installed on the store’s remaining nodes, whereas only the client.trust artifact should be installed on any client nodes that will be accessing the store.

To install all of the artifacts listed above on each of the store’s remaining nodes, login to each node, create the appropriate KVROOT directory, and use a utility such as scp to copy the security directory from kv-host-1 to the given node’s KVROOT directory. That is,

On kv-host-2:
mkdir -p /u02/nosql/sn2/kvroot
cd /u02/nosql/sn2/kvroot
scp -r <username>@kv-host-1:/u01/nosql/sn1/kvroot/security .

On kv-host-3:
mkdir -p /u03/nosql/sn3/kvroot
cd /u03/nosql/sn3/kvroot
scp -r <username>@kv-host-1:/u01/nosql/sn1/kvroot/security .

To install the client.trust file on the client node, login to the client node and simply copy the desired file from kv-host-1 node. That is,

On client-host:
scp <username>@kv-host-1:\ 
    /u01/nosql/sn1/kvroot/security/client.trust /tmp

Once the security artifacts generated on kv-host-1 have been installed on each of the store's remaining nodes, the configuration files for the Storage Nodes that will be deployed to those remaining nodes can be generated. This is accomplished by executing the following commands on the respective node:

On kv-host-2:
java -jar /opt/oracle/kv-ee/lib/kvstore.jar \
    makebootconfig \
    -root /u02/nosql/sn2/kvroot \
    -config config.xml \
    -port 5000 \
    -host kv-host-1 \
    -harange 5002,5007 \
    -num_cpus 0 \
    -memory_mb 200 \
    -capacity 1 \
    -storagedir /u02/nosql/sn2/data \
    -storagedirsize 10000000 \
    -store-security enable \
    -pwdmgr pwdfile \
    -kspwd No_Sql_00

On kv-host-3:
java -jar /opt/oracle/kv-ee/lib/kvstore.jar makebootconfig \
    -root /u03/nosql/sn3/kvroot \
    -config config.xml \
    -port 5000 \
    -host kv-host-1 \
    -harange 5002,5007 \
    -num_cpus 0 \
    -memory_mb 200 \
    -capacity 1 \
    -storagedir /u03/nosql/sn3/data \
    -storagedirsize 10000000 \
    -store-security enable \
    -pwdmgr pwdfile \
    -kspwd No_Sql_00

For both commands above, notice that the value specified for the -store-security parameter is enable rather than configure, which was specified when generating the configuration on kv-host-1.

Launch a Storage Node Agent (SNA) On Each Host Making Up the Store

From each host’s command line, type a command like the following:

nohup java -jar /opt/oracle/kv-ee/lib/kvstore.jar start \
    -root /u0<n>/nosql/sn<n>/kvroot -config config.xml &

where the token <n> corresponds to the integer associated with the given host from which the above command is executed.

Configure and Deploy the Secure Store

From the command line of the host kv-host-1 launch the Admin CLI, connected to the boot SNA.

java -jar /opt/oracle/kv-ee/lib/kvstore.jar runadmin \
    -helper-hosts kv-host-1:5000,kv-host-2:5000,kv-host-3:5000 \
    -security /u01/nosql/sn1/kvroot/security/client.security

Next, from the Admin CLI’s command prompt, deploy the store by either entering each command shown below in succession or by using the load -file <file> command to load those same commands from a file.

configure -name example-store
plan deploy-zone -name zn1 -rf 3 -wait

plan deploy-sn -znname zn1 -host kv-host-1 -port 5000 -wait
plan deploy-admin -sn 1 -wait
pool create -name snpool
pool join -name snpool -sn sn1

plan deploy-sn -znname zn1 -host kv-host-2 -port 5000 -wait
plan deploy-admin -sn 2 -wait
pool join -name snpool -sn sn2

plan deploy-sn -znname zn1 -host kv-host-3 -port 5000 -wait
plan deploy-admin -sn 3 -wait
pool join -name snpool -sn sn3

change-policy -params "loggingConfigProps=oracle.kv.level=INFO;"

topology create -name store-layout -pool snpool -partitions 120
topology preview -name store-layout
plan deploy-topology -name store-layout -plan-name deploy-plan -wait

execute "CREATE USER root IDENTIFIED BY 'No_Sql_00' ADMIN";

Note:

The only difference between the set of store deployment commands presented in the Configure and Deploy the Non-secure Store appendix for a non-secure store and the commands above is the last command. Once the store is deployed, that last command will create a store user named root with administrative privileges and password equal to the value No_Sql_00.

When a secure store is deployed, before the store can be used, an initial user must be created and then provisioned with the necessary security credentials that grant that user privileges that allow it to administer the store. Once that user is created and provisioned, it can then be used to create other users of the store. In a typical production scenario, tables are generally created and populated with data by users with only user-level privileges rather than administrative privileges.

The last command above then simply creates that initial user that will be used to create a second user for executing the secure version of the example program presented in this document. But before that root user can create other users of the store, it must first be provisioned, as explained in the next section.

Provision the Secure Store’s Administrative User (root)

As described in the previous section, the last step of the secure store deployment process simply creates the store's administrative user but does not provision it. But in order to administer the store, that new user must be provisioned with credentials that grant administrative privileges for the store. To provision the root user created in the previous section, login to the store's kv-host-1 node, execute the commands shown, and enter the appropriate responses when prompted:

java -jar /opt/oracle/kv-ee/lib/kvstore.jar \
    securityconfig pwdfile create \
    -file /u01/nosql/sn1/kvroot/security/root.passwd

Created

java -jar /opt/oracle/kv-ee/lib/kvstore.jar \
    securityconfig pwdfile secret \
    -file /u01/nosql/sn1/kvroot/security/root.passwd \
    -set -alias root

Enter the secret value to store: No_Sql_00<RETURN>
Re-enter the secret value for verification: No_Sql_00<RETURN>

Secret created
OK

cp /u01/nosql/sn1/kvroot/security/client.security \
    /u01/nosql/sn1/kvroot/security/root.login

echo oracle.kv.auth.username=root >> \
    /u01/nosql/sn1/kvroot/security/root.login
echo oracle.kv.auth.pwdfile.file=\
    /u01/nosql/sn1/kvroot/security/root.passwd >> \
    /u01/nosql/sn1/kvroot/security/root.login

The client.security properties file is one of the security artifacts that was generated in the Generate Configuration Files For Each Storage Node (SN) appendix. The contents of that file are copied to the file named root.login. The root.login file created here is used when clients wishing to connect to the secure store must authenticate as the user named root. For the purposes of this document, this authentication process will be referred to as logging in to the secure store. As a result, the properties file used in that authentication process is referred to as a login file, or login properties file.

For convenience, the system properties oracle.kv.auth.username and oracle.kv.auth.pwdfile.file are inserted into the root.login file. This will allow the client to connect to the secure store as the root user without having to specify the value of those properties on the command line.

Create Non-Administrative User

To create a user that will be provisioned with non-administrative privileges, from the store’s kv-host-1 node, login to the Admin CLI as the newly created root user.

java -jar /opt/oracle/kv-ee/lib/kvstore.jar runadmin \
    -host kv-host-1 \
    -port 5000 \
    -security /u01/nosql/sn1/kvroot/security/root.login

Then create a custom role with the name readwritemodifytables (for example) that consists of the privileges a user would need to create and populate a table in the store. After creating the desired role, create a user named example-user and grant the readwritemodifytables role to that user. To accomplish this, either enter each command shown below in succession or copy each command to a text file and execute the CLI’s load command, specifying the file you created ('load -file <file>').

execute 'CREATE ROLE readwritemodifytables'
execute 'GRANT SYSDBA TO readwritemodifytables'
execute 'GRANT READ_ANY TO readwritemodifytables'
execute 'GRANT WRITE_ANY TO readwritemodifytables'
execute 'CREATE USER example-user IDENTIFIED BY "No_Sql_00"'
execute 'GRANT readwritemodifytables TO USER example-user'

Note:

The name of the user created above is not required to be the same as the OS user name under which the example is executed. The name above and its associated credentials are registered with the secure store for the purpose of authenticating to the store. Thus, the name of the user that is created here can be any value you wish to use.

Provision the Secure Store's Non-Administrative User (example-user)

Once the user named example-user and its role have been created, use the KVSecurityCreation convenience program to generate the public and private credentials needed by that user to connect to the secure store. To do this, first compile KVSecurityCreation by executing the following command from the store's kv-host-1 node:

cd /opt/oracle/nosql/apps/kv
javac -classpath \
    /opt/oracle/kv-ee/lib/kvstore.jar:examples \
    examples/hadoop/table/KVSecurityCreation.java

This will produce the following class files on the kv-host-1 node:

/opt/oracle/nosql/apps/kv/examples/hadoop/table/
    KVSecurityUtil.class
    KVSecurityCreation.class

Once KVSecurityCreation has been compiled, it can then be executed to generate the desired security artifacts for the non-administrative user. If you want to store the password in a clear text password file, then type the following at the command line and enter the appropriate response when prompted:

cd /opt/oracle/nosql/apps/kv
java -classpath \
    /opt/oracle/kv-ee/lib/kvstore.jar:\
    /opt/oracle/kv-ee/lib/sklogger.jar:\
    /opt/oracle/kv-ee/lib/commonutil.jar:examples \
    hadoop.table.KVSecurityCreation \
    -pwdfile example-user.passwd \
    -set -alias example-user

INFO: removed file [/tmp/example-user.passwd]
INFO: removed file [/tmp/example-user-client-pwdfile.login]
created login properties file [/tmp/example-user-client-pwdfile.login]
created login properties file [/tmp/example-user-server.login]
created credentials store [/tmp/example-user.passwd]

Enter the secret value to store: No_Sql_00<RETURN>
Re-enter the secret value for verification: No_Sql_00<RETURN>

Secret created
OK

Alternatively, if you are using an Oracle Wallet (available only in the Enterprise Edition) to store the user's password, then type the following and again, enter the appropriate response when prompted:

cd /opt/oracle/nosql/apps/kv
java -classpath \
    /opt/oracle/kv-ee/lib/kvstore.jar:\
    /opt/oracle/kv-ee/lib/sklogger.jar:\
    /opt/oracle/kv-ee/lib/commonutil.jar:examples \
    hadoop.table.KVSecurityCreation \
    -wallet example-user-wallet.dir \
    -set -alias example-user

INFO: removed file [/tmp/example-user-wallet.dir/cwallet.sso]
INFO: removed directory [/tmp/example-user-wallet.dir]
INFO: removed file [/tmp/example-user-client-wallet.login]
created login properties file [/tmp/example-user-client-wallet.login]
created login properties file [/tmp/example-user-server.login]
created credentials store [/tmp/example-user-wallet.dir]
   
Enter the secret value to store: No_Sql_00<RETURN>
Re-enter the secret value for verification: No_Sql_00<RETURN>

Secret created
OK

Compare the artifacts generated when a password file is specified with the artifacts generated when a wallet is specified. When a password file is specified, you should see the following files:

/tmp
    example-user-client-pwdfile.login
    example-user-server.login
    example-user.passwd

Whereas when wallet storage is specified, you should see:

/tmp
    example-user-client-wallet.login
    example-user-server.login
    /example-user-wallet.dir
        cwallet.sso

Note:

As this is an example for demonstration purposes, the credential files generated by KVSecurityCreation are placed in the system's /tmp directory. For your applications, you may want to place the credential files you generate in a more permanent location that is password protected.

Note:

For both the password or wallet cases two login properties files are generated; one for client side connections, and one for server side connections. The only difference between the client side login file and the server side login file is that the client side login file specifies the username (the alias) along with the location of the user's password. For the login properties file associated with the use of a password file, the property oracle.kv.auth.pwdfile is used to specify the location of the file in which the user’s password is stored; whereas the property oracle.kv.auth.wallet.dir would be used if the password is stored in an Oracle Wallet. Although optional, the reason for using two login files is to avoid passing private security information to the server side, as explained in more detail in the Model For Building & Packaging Secure Clients appendix. Additionally, observe that the server side login file (example-user-server.login) is identical for both cases. This is because whether a password file or an Oracle Wallet is used to store the password, both use the same publicly visible communication transport information.

At this point, the store has been deployed, configured for secure access, and provisioned with the necessary users and credentials required for table creation and population. To demonstrate running a MapReduce job against table data contained in a secure store, the example presented in this document can now be executed by a user whose password is stored either in a clear text password file or an Oracle Wallet (Enterprise Edition only).

Note:

A final, important point is that the storage mechanism used for the example application's user password (password file or Oracle Wallet) does not depend on the password storage mechanism used by the store. That is, although this appendix (for convenience) deployed a secure store using a password file rather than a wallet, the fact that the store placed the passwords it manages in a password file does not prevent the developer/deployer of a client of that store from storing the client's user password in an Oracle Wallet, or vice versa. You should therefore view the use of an Oracle Wallet or a password file by any client application as simply a "safe" place (for some value of "safe") where the user password can be stored and accessed by only the user who owns the wallet or password file. This means that the choice of password storage mechanism is at the discretion of the application developer/deployer, no matter what mechanism is used by the store itself.