This document describes how to configure the Teradata JDBC Driver with Stored Password Protection feature on the Linux platform using Network File System (NFSv4) with Kerberos.
Stored Password Protection uses two Java properties files: a password-encryption-key file and an encrypted-password file to provide a password for logging onto a database. The properties files can be located on a network volume to prevent loss of the file in case the physical client machine is stolen. To protect their contents while in transit, an encrypted protocol is used.
An example will be described in this document where for a given user, a password-encryption-key file will be placed on one server and an encrypted-password file on another and then provide access to each file through NFSv4 using encrypted Kerberos.
The approach used to secure these files will be that the top level imported directories are only accessible to users with valid Kerberos credentials. Without such credentials, the directories are inaccessible. Below that level, for the actual files that hold the encryption information, the ownership will be that of the User ID that is mapped to that Kerberos principal. So, a valid user will be able to see their own files, but will not be able to access those of other users.
This document is written using SUSE Linux Enterprise Server 11 & 12 systems. All of the systems need to be part of the same Kerberos domain. Our example will use the domain "mykerberos.com" with a realm of "MYKERBEROS.COM".
A total of five Linux systems will be used as shown in the table below.
System |
Requirement |
Description |
Linux |
Kerberos Distribution Server (KDC) | |
system1 |
JDK | Contains:
|
server1 |
Contains the password-encryption-key properties file | |
server2 |
Contains the encrypted-password properties file | |
client1 |
JDK | Contains:
|
The required packages for Kerberos and NFSv4 that are needed for "server1", "server2", and "client1" are listed in the table below.
System |
Package |
Description |
server1 |
krb5 | MIT Kerberos5 implementation - Libraries |
krb5-client | MIT Kerberos5 implementation - client programs | |
krb5-server | MIT Kerberos5 implementation - server | |
pam_krb5 | A Pluggable Authentication Module for Kerberos 5 | |
nfs-kernel-server | Support for Kernel nfsd | |
server2 |
krb5 | MIT Kerberos5 implementation - Libraries |
krb5-client | MIT Kerberos5 implementation - client programs | |
krb5-server | MIT Kerberos5 implementation - server | |
pam_krb5 | A Pluggable Authentication Module for Kerberos 5 | |
nfs-kernel-server | Support for Kernel nfsd | |
client1 |
krb5 | MIT Kerberos5 implementation - Libraries |
krb5-client | MIT Kerberos5 implementation - client programs | |
krb5-server | MIT Kerberos5 implementation - server | |
pam_krb5 | A Pluggable Authentication Module for Kerberos 5 | |
sssd | System Security Service Daemon |
On "server1" and "server2", start NFSv4. Using the system adminstrator tool YaST, go to Network Services → NFS Server.
These settings are shown below.
Click "Next" then "Finish".
NOTE: You may receive the errors in the screenshots below after clicking "Finish" if there are no entries in /etc/exports
. The entries
for /etc/exports will be configured in Modify /etc/exports later in this document and NFS & NFS server will be restarted in
Restart the servers after the servers have been configured.
Click "OK" to continue.
Set up two users on each system. This would normally be done by setting up an LDAP server, but we will use two local users to simplify the example.
The users will be "nfsuser1" & "nfsuser2". Verify that the users with the UIDs shown below do not exist in /etc/passwd
.
If the users already exists, the UID values can be changes as long as they are the same across all systems.
Create "nfsuser1" and "nfsuser2" with the following commands:
useradd -m -u 5210 -s /bin/sh nfsuser1
useradd -m -u 5010 -s /bin/sh nfsuser2
NOTE: These users are created WITHOUT passwords which is NOT the same as null passwords. The actual password will be provided via a Kerberos principal.
Now that the users have been created, the following changes are required for any system that you are planning to log into using ssh
with
"nfsuser1" and "nfsuser2". For our example, "client1" would need these changes.
Pluggable Authentication Modules (PAM) and (Secure Shell) SSH will be used so that these users have a default Kerberos principal when they log in. Make the following required configuration changes for both PAM and SSH as described in the table below:
File |
Setting |
Value |
/etc/ssh/ssh_config |
GSSAPIAuthentication | yes |
GSSAPIDelegateCredentials | yes | |
/etc/ssh/sshd_config |
KerberosAuthentication | yes |
KerberosOrLocalPasswd | yes | |
KerberosTicketCleanup | yes | |
GSSAPIAuthentication | yes | |
GSSAPICleanupCredentials | yes | |
GSSAPIKeyExchange | yes | |
AllowAgentForwarding | yes | |
ChallengeResponseAuthentication** | yes | |
UsePAM** | no | |
/etc/pam.d/common-auth |
auth sufficient pam_krb5.so use_first_pass ignore_root forwardable
(***add this as the first entry) |
|
/etc/shadow** |
nfsuser1 - change the 1st field after the username which is "!" (an exclamation point) to "NP" (no password) |
|
nfsuser2 - change the 1st field after the username which is "!" (an exclamation point) to "NP" (no password) |
** needed on SLES 12 client system ONLY
After making changes to /etc/ssh/sshd_config, the sshd service need to be restarted for the changes to take effect.
Enter:
service sshd restart
Modifications are needed in the /etc/hosts
file.
The first two entries should be:
ipaddress hostname.domainname hostname 127.0.0.1 localhost.localdomain localhost
As an example, for "server1" at mykerberos.com with an IP address of 10.25.30.13, the first two lines would be:
10.25.30.13 server1.mykerberos.com server1 127.0.0.1 localhost.localdomain localhost
NOTE: The 2nd line does NOT have any system specific values.
On the client system, it is important that the server hostnames resolve to the correct domain. When they do not, you are likely to see this error when trying to mount:
mount.nfs4:mount(2):Permission denied
For the client system "client1", in addition to modifying the first two lines as noted above, extra entries should be included to identify
the two server systems "server1" and "server2". For "client1", the first four lines of the /etc/hosts
file would be:
153.62.21.15 client1.mykerberos.com client1 127.0.0.1 localhost.localdomain localhost 10.25.30.13 server1.mykerberos.com server1 10.25.31.14 server2.mykerberos.com server2
Modify the "Domain" variable to the system's domain name. For our example, it is set to:
Domain = MYKERBEROS.com
Kerberos principals and keytabs need to be generated on the Linux Kerberos Distribution Server system in order to support NFSv4 with Kerberos. New principals must be added and keytab files are required on the client & server NFSv4 Kerberos systems. The specific entry we need on all systems is a "nfs/hostname.domain" credential on each system.
For our example, we will need the following principals:
nfs/client1.mykerberos.com@MYKERBEROS.COM
nfs/server1.mykerberos.com@MYKERBEROS.COM
nfs/server2.mykerberos.com@MYKERBEROS.COM
Use the "kadmin
" command to create the principals. An admin password is needed for "kadmin
" and will need to be provided
by the system administrator of your Kerberos environment. The principal and keytabs are written to the /etc/krb5.keytab
file.
This will be generated once and then distributed to all the affected systems.
Once you have successfully started "kadmin
", use the "listprincs
" subcommand to see which principals are present.
If you see all of the above principals (i.e. nfs/client1.mykerberos.com@MYKERBEROS.COM
, etc.) then you will not need to add them.
Otherwise, they can be added via the "addprinc
" subcommand as follows:
addprinc -randkey nfs/client1.mykerberos.com@MYKERBEROS.COM
addprinc -randkey nfs/server1.mykerberos.com@MYKERBEROS.COM
addprinc -randkey nfs/server2.mykerberos.com@MYKERBEROS.COM
Kerberos principals are also needed for the local users "nfsuser1" & "nfsuser2". The following will create both the user principals and their passwords in the
Kerberos database.
addprinc -randkey -pw nfsuser1p nfsuser1@MYKERBEROS.COM
addprinc -randkey -pw nfsuser2p nfsuser2@MYKERBEROS.COM
Now that the principals have been added to Kerberos database, they need to be put into the /etc/krb5.keytab
file on each system. One entry will be added
to each system.
NOTE: The actual value of the "-e encryption type/salt type"
parameter may vary, so you should consult with your system administrator.
Run "kadmin
" from the client and server systems and enter the following commands to update the keytab file on each system as shown in
the table below.
System |
Command |
client1 |
ktadd -k /etc/krb5.keytab -e rc4-hmac:normal nfs/client1.mykerberos.com@MYKERBEROS.COM |
server1 |
ktadd -k /etc/krb5.keytab -e rc4-hmac:normal nfs/server1.mykerberos.com@MYKERBEROS.COM |
server2 |
ktadd -k /etc/krb5.keytab -e rc4-hmac:normal nfs/server2.mykerberos.com@MYKERBEROS.COM |
After completing these "ktadd
" commands, exit "kadmin
" by entering "quit
".
The contents of the keytab can be viewed using "klist -k /etc/krb5.keytab
".
To validate that the created keytab entries are useable, run the following commands which produce no output but will fail and produce an error if there are problems with the keytab.
System |
Command |
client1 |
kinit -k nfs/client1.mykerberos.com |
server1 |
kinit -k nfs/server1.mykerberos.com |
server2 |
kinit -k nfs/server2.mykerberos.com |
The "klist
" command can be run after any of the above commands to verify that the default principal has been changed.
This section will create the encrypted password properties files needed for the Stored Password Protection example. The properties files will be created with the TJEncryptPassword.java sample program that is part of the Teradata JDBC Driver sample programs. Full documentation on how to run the program is included in the program file.
On "system1", the properties files that will be created are:
In a directory on the Linux system "system1" as listed in Prerequisites,
compile TJEncryptPassword.java and run the program as follows:
javac TJEncryptPassword.java
java -cp .:terajdbc4.jar TJEncryptPassword AES/CBC/NoPadding -default HmacSHA1 PassKey.properties EncPass.properties dbs1 user1 password1
Older versions prior to Teradata JDBC Driver 16.20.00.11 require tdgssconfig.jar
to be listed on the classpath as follows:
java -cp .:terajdbc4.jar:tdgssconfig.jar TJEncryptPassword AES/CBC/NoPadding -default HmacSHA1 PassKey.properties EncPass.properties dbs1 user1 password1
The command will encrypt the database password "password1" and generate two Stored Password Protection properties files. One file contains the password-encryption-key and the other contains the encrypted-password. These two files will be copied to the server systems in the next section.
Set up the export directory structure as listed in the table below (logged in as root
). The properties files created from the
section above will be copied from "system1" to local directories on the servers.
The two directories that we'll be setting up are:
/exports/JdbcKey/username/KeyPropertiesFile
/exports/JdbcPassword/username/PasswordPropertiesFile
We will also change the ownership of these directories so they are owned by the local user that is mapped to a Kerberos principal.
System |
Command |
server1 |
mkdir -p /exports/JdbcKey/nfs1 |
chown nfsuser1/exports/JdbcKey/nfs1 |
|
chmod 700 /exports/JdbcKey/nfs1 |
|
cp PassKey.properties /exports/JdbcKey/nfs1 (copy this file from "system1") |
|
chown nfsuser1 /exports/JdbcKey/nfs1/PassKey.properties |
|
chmod 700 /exports/JdbcKey/nfs1/PassKey.properties |
|
mkdir -p /exports/JdbcKey/nfs2 |
|
chown |
|
chmod 700 /exports/JdbcKey/nfs2 |
|
touch /exports/JdbcKey/nfs2/testfile1 |
|
chown nfsuser2 /exports/JdbcKey/nfs2/testfile1 |
|
chmod 700 /exports/JdbcKey/nfs2/testfile1 |
|
server2 |
mkdir -p /exports/JdbcPass/nfs1 |
chown nfsuser1/exports/JdbcPass/nfs1 |
|
chmod 700 /exports/JdbcPass/nfs1 |
|
cp EncPass.properties /exports/JdbcPass/nfs1 (copy this file from "system1") |
|
chown nfsuser1 /exports/JdbcPass/nfs1/EncPass.properties |
|
chmod 700 /exports/JdbcPass/nfs1/EncPass.properties |
|
mkdir -p /exports/JdbcPass/nfs2 |
|
chown |
|
chmod 700 /exports/JdbcPass/nfs2 |
|
touch /exports/JdbcPass/nfs2/testfile2 |
|
chown nfsuser2 /exports/JdbcPass/nfs2/testfile2 |
|
chmod 700 /exports/JdbcPass/nfs2/testfile2 |
Make the following changes to /etc/sysconfig/nfs
:
NFS4_SUPPORT="yes"
NFS_SECURITY_GSS="yes"
NFS_START_SERVICES="gssd,idmapd"
Add these lines to /etc/exports
on "server1":
/exports 153.62.21.15(ro,root_squash,no_subtree_check,fsid=0,no_all_squash,sec=krb5p)
/exports/JdbcKey 153.62.21.15(ro,nohide,root_squash,no_subtree_check,no_all_squash,sec=krb5p)
Add these lines to /etc/exports
on "server2":
/exports 153.62.21.15(ro,root_squash,no_subtree_check,fsid=0,no_all_squash,sec=krb5p)
/exports/JdbcPass 153.62.21.15(ro,nohide,root_squash,no_subtree_check,no_all_squash,sec=krb5p)
For both of these export files, we are using encrypted Kerberos (via sec=krb5p) and severely restricting who we export to by limiting the
export to 153.62.21.15 (the IP address of the client system "client1"). Running "man exports
" on Linux will provide details of the other options used along
with alternative ways to configure this file.
Run these commands on each server to export the NFSv4 filesystem, restart NFS, and restart the NFS server.
exportfs -rva
rcnfs restart
rcnfsserver restart
NOTE: These commands should be run whenever the /etc/exports
file is modified.
On the client system "client1", we will restart the local NFS server, create mount directories for the Stored Password Protection files, and then mount the remote directories.
Run the following commands as root:
rcnfs restart
sudo mkdir /importKey
sudo mkdir /importPass
sudo mount -vvv -t nfs4 -o sec=krb5p,proto=tcp,port=2049 server1:/ /importKey
sudo mount -vvv -t nfs4 -o sec=krb5p,proto=tcp,port=2049 server2:/ /importPass
Logon to "client1" as a local user other than nfsuser1
and nfsuser2
and run these commands:
kdestroy
ls -lR /importKey
ls -lR /importPass
A "Permission denied" error message should be returned because the local user is not identified as being a Kerberos user. An example is shown below.
Now, using SSH, log in as "nfsuser1". For our test environment, this would be done as:
ssh nfsuser1@client1
You should be prompted for the password as:
Password for nfsuser1@MYKERBEROS.COM:
NOTE: On a SLES 12 client system, you may receive a different login prompt than a SUSE 11 client system. When logging in you may see:
nfsuser1@client1's password:
Next, run the "klist
" command to ensure that you have a default principal and run the "ls
" commands again. The output should
show that you can see the "nfsuser1" files but not those of "nfsuser2". An example is shown below.
The encrypted password properties files generated above in Create the encrypted password properties files for Stored Password Protection
created by the TJEncryptPassword.java sample program are resources that will be accessed by the Teradata JDBC Driver.
These resources are accessed via the classpath or direct files by specifying a prefix of either classpath:
or file:
in the
ENCRYPTED_PASSWORD string.
To access the resource files using the classpath access, the following syntax is used:
"ENCRYPTED_PASSWORD(classpath:PassKey.properties,classpath:EncPass.properties)"
For security, classpath resources are required to have specific resource name prefixes. The PasswordEncryptionKeyResourceName (PassKey.properties
is used
in this document) must begin with "PassKey" and the EncryptedPasswordResourceName (EncPass.properties
is used in this document) must begin with "EncPass".
To access the resource files using the file access, the following syntax is used:
"ENCRYPTED_PASSWORD(file:PassKey.properties,file:EncPass.properties)"
There is no prefix requirement for the resource name when using file access.
For simplicity, the examples in this document use the same resource names "PassKey.properties
" and "EncPass.properties
" for
both classpath and file access.
For futher examples of file access using the current directory, relative paths, and absolute paths refer to the documentation in the program file.
Teradata JDBC Driver Stored Password Protection offers flexibility for accessing the password-encryption-key file and the encrypted-password file.
In general, classpath access offers greater control and security, whereas file access offers greater flexibility.
In this section, we will run a sample Java program LogonTest.java using Stored Password Protection on the Linux client system "client1
"
using both classpath and file access.
terajdbc4.jar
from "system1" to a directory on "client1".
Older versions prior to Teradata JDBC Driver 16.20.00.11 also require tdgssconfig.jar
.
javac LogonTest.java
java -classpath .:./terajdbc4.jar:/importKey/JdbcKey/nfs1:/importPass/JdbcPass/nfs1 LogonTest jdbc:teradata://dbs1 user1 "ENCRYPTED_PASSWORD(classpath:PassKey.properties,classpath:EncPass.properties)"
Older versions prior to Teradata JDBC Driver 16.20.00.11 also require tdgssconfig.jar
to be listed on the classpath.
The following results are returned:
Connecting to jdbc:teradata://dbs1 with user user1 and password ENCRYPTED_PASSWORD(classpath:PassKey.properties,classpath:EncPass.properties) Successfully logged on Closing Connection Pass
java -classpath .:./terajdbc4.jar LogonTest jdbc:teradata://dbs1 user1 "ENCRYPTED_PASSWORD(file:/importKey/JdbcKey/nfs1/PassKey.properties,file:/importPass/JdbcPass/nfs1/EncPass.properties)"
Older versions prior to Teradata JDBC Driver 16.20.00.11 also require tdgssconfig.jar
to be listed on the classpath.
The folllowing results are returned:
Connecting to jdbc:teradata://dbs1 with user user1 and password ENCRYPTED_PASSWORD(file:/importKey/JdbcKey/nfs1/PassKey.properties,file:/importPass/JdbcPass/nfs1/EncPass.properties) Successfully logged on Closing Connection Pass
These examples use the encrypted password properties files created in the previous section Create the encrypted password properties files for Stored Password Protection.