SSL and PAM
June 7-9, 2016
iRODS User Group Meeting 2016
Chapel Hill, NC
Justin James
Application Engineer
iRODS Consortium
Two Ways iRODS Uses SSL
1) Encryption of data between iRODS components
2) Encryption of passwords when using PAM for authentication
We'll go over some configuration differences between these two cases.
Four Scenarios
Since iRODS can be configured with or without general SSL data encryption and with or without PAM, there are four possible scenarios to consider:
Default - No data encryption and no PAM
Using SSL for data encryption only
Using SSL for PAM only
Using SSL for both data encryption and PAM
We'll start with #2, and then show #4
Setting Up iRODS for Data Encryption
Initial Configuration
Two storage resources exist - one on each server:
The unix service account is "irods", the zone is "tempZone".
icat.renci.org - Certificate Creation
First, create a directory on icat.renci.org to hold the certificates:
irods@icat:~$ mkdir /etc/irods/ssl
irods@icat:~$ cd /etc/irods/ssl
irods@icat:/etc/irods/ssl$ openssl genrsa -out irods.key 2048
irods@icat:/etc/irods/ssl$ chmod 600 irods.key
Now create a secret key and make sure it is only readable by the irods user.
icat.renci.org - Certificate Creation
Now create the certificate.
Since we do not have certs signed by a recognized certificate authority, we will create a single self-signed certificate with a wildcard FQDN (*.renci.org). This will be used on both servers.
irods@icat:/etc/irods/ssl$ openssl req -new -x509 -key irods.key \
-out irods.crt -days 365
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:North Carolina
Locality Name (eg, city) []:Chapel Hill
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Renci
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:*.renci.org
Email Address []:
icat.renci.org - Certificate Creation
Generate some Diffie-Hellman parameters.
We should now have the following three files in /etc/irods/ssl.
irods@icat:/etc/irods/ssl$ openssl dhparam -2 -out dhparams.pem
irods@icat:/etc/irods/ssl$ ls -l
total 12
-rw-rw-r-- 1 irods irods 424 May 31 12:27 dhparams.pem
-rw-rw-r-- 1 irods irods 1306 May 31 13:53 irods.crt
-rw------- 1 irods irods 1679 May 31 13:52 irods.key
icat.renci.org - Configure Server
To make sure that we have SSL set up properly, we are going to configure the iCAT server to require SSL for all connections.
Update /etc/irods/core.re as follows:
There are three possible values for this client-server negotiation setting:
acPreConnect(*OUT) { *OUT="CS_NEG_REQUIRE"; }
icat.renci.org - Client Configuration
The next step is to update the clients for SSL.
The first client we will update is the iRODS service account.
We will update ~irods/.irods/irods_environment.json.
Note: This is a special client configuration file for the iRODS service account. When this iRODS server initiates communication with other peers, it is effectively acting as a client and the configuration in this file will be used.
icat.renci.org - Client Configuration
Set the contents of ~irods/.irods/irods_environment.json to the following:
{
"irods_host": "icat.renci.org",
"irods_port": 1247,
"irods_default_resource": "icatResc",
"irods_home": "/tempZone/home/rods",
"irods_cwd": "/tempZone/home/rods",
"irods_user_name": "rods",
"irods_zone_name": "tempZone",
"irods_client_server_negotiation": "request_server_negotiation",
"irods_client_server_policy": "CS_NEG_REQUIRE",
"irods_encryption_key_size": 32,
"irods_encryption_salt_size": 8,
"irods_encryption_num_hash_rounds": 16,
"irods_encryption_algorithm": "AES-256-CBC",
"irods_default_hash_scheme": "SHA256",
"irods_match_hash_policy": "compatible",
"irods_server_control_plane_port": 1248,
"irods_server_control_plane_key": "TEMPORARY__32byte_ctrl_plane_key",
"irods_server_control_plane_encryption_num_hash_rounds": 16,
"irods_server_control_plane_encryption_algorithm": "AES-256-CBC",
"irods_maximum_size_for_single_buffer_in_megabytes": 32,
"irods_default_number_of_transfer_threads": 4,
"irods_transfer_buffer_size_for_parallel_transfer_in_megabytes": 4,
"irods_ssl_certificate_chain_file": "/etc/irods/ssl/irods.crt",
"irods_ssl_certificate_key_file": "/etc/irods/ssl/irods.key",
"irods_ssl_dh_params_file": "/etc/irods/ssl/dhparams.pem",
"irods_ssl_ca_certificate_file": "/etc/irods/ssl/irods.crt"
}
icat.renci.org - Client Configuration
The following settings identify the certificate, the key, and the dhparams file.
"irods_ssl_certificate_chain_file": "/etc/irods/ssl/irods.crt",
"irods_ssl_certificate_key_file": "/etc/irods/ssl/irods.key",
"irods_ssl_dh_params_file": "/etc/irods/ssl/dhparams.pem",
The following setting forces the server to use SSL when connecting as a client to other servers.
"irods_client_server_policy": "CS_NEG_REQUIRE",
Since we have a self signed certificate, we need to tell the client to trust the certificate authority that has signed this certificate. In our case we are our own certificate authority so we simply add our certificate here:
"irods_ssl_ca_certificate_file": "/etc/irods/ssl/irods.crt"
icat.renci.org - Client Configuration
Now let's test the configuration using iinit.
After entering the password we should not have an error.
This indicates that we connected to the server successfully.
irods@icat:~/.irods$ iinit
Enter your current iRODS password:
icat.renci.org - Client Configuration
Let's set up one more client on icat.renci.org.
Exit out of the service account (irods).
Create ~/.irods/irods_environment.json and add the following content:
{
"irods_host": "icat.renci.org",
"irods_zone_name": "tempZone",
"irods_port": 1247,
"irods_user_name": "rods",
"irods_client_server_negotiation": "request_server_negotiation",
"irods_client_server_policy": "CS_NEG_REQUIRE",
"irods_ssl_ca_certificate_file": "/etc/irods/ssl/irods.crt",
"irods_encryption_key_size": 32,
"irods_encryption_salt_size": 8,
"irods_encryption_num_hash_rounds": 16,
"irods_encryption_algorithm": "AES-256-CBC"
}
icat.renci.org - Client Configuration
Let's again test our configuration using iinit.
Again, no error indicates that we connected to the server successfully, this time as a non-service account.
We are now finished setting up SSL on icat.renci.org.
Next we will do the same on resource1.renci.org.
myuser@icat:~/.irods$ iinit
Enter your current iRODS password:
resource1.renci.org - Certificate and Server Setup
We are going to use the same certificate on resource1.renci.org as we used on icat.renci.org.
"irods_client_server_policy": "CS_NEG_REQUIRE",
resource1.renci.org - Service Account Setup
Update ~irods/.irods/irods_environment.json:
{
"irods_host": "resource1.renci.org",
"irods_port": 1247,
"irods_default_resource": "resource1Resc",
"irods_home": "/tempZone/home/rods",
"irods_cwd": "/tempZone/home/rods",
"irods_user_name": "rods",
"irods_zone_name": "tempZone",
"irods_client_server_negotiation": "request_server_negotiation",
"irods_client_server_policy": "CS_NEG_REQUIRE",
"irods_encryption_key_size": 32,
"irods_encryption_salt_size": 8,
"irods_encryption_num_hash_rounds": 16,
"irods_encryption_algorithm": "AES-256-CBC",
"irods_default_hash_scheme": "SHA256",
"irods_match_hash_policy": "compatible",
"irods_server_control_plane_port": 1248,
"irods_server_control_plane_key": "TEMPORARY__32byte_ctrl_plane_key",
"irods_server_control_plane_encryption_num_hash_rounds": 16,
"irods_server_control_plane_encryption_algorithm": "AES-256-CBC",
"irods_maximum_size_for_single_buffer_in_megabytes": 32,
"irods_default_number_of_transfer_threads": 4,
"irods_transfer_buffer_size_for_parallel_transfer_in_megabytes": 4,
"irods_ssl_certificate_chain_file": "/etc/irods/ssl/irods.crt",
"irods_ssl_certificate_key_file": "/etc/irods/ssl/irods.key",
"irods_ssl_dh_params_file": "/etc/irods/ssl/dhparams.pem",
"irods_ssl_ca_certificate_file": "/etc/irods/ssl/irods.crt"
}
resource1.renci.org - Service Account Setup
Same as on icat.renci.org, the last four lines of the configuration setup the certificate information.
The irods_client_server_policy was set to "CS_NEG_REQUIRE".
Now test the connection:
No error... Success.
irods@resource1:~/.irods$ iinit
Enter your current iRODS password:
resource1.renci.org - Client Setup
Let's set up one more client on resource1.renci.org.
{
"irods_host": "resource1.renci.org",
"irods_zone_name": "tempZone",
"irods_port": 1247,
"irods_user_name": "rods",
"irods_client_server_negotiation": "request_server_negotiation",
"irods_client_server_policy": "CS_NEG_REQUIRE",
"irods_ssl_ca_certificate_file": "/etc/irods/ssl/irods.crt",
"irods_encryption_key_size": 16,
"irods_encryption_salt_size": 8,
"irods_encryption_num_hash_rounds": 16,
"irods_encryption_algorithm": "AES-256-CBC"
}
jjames@resource1:~/.irods$ iinit
Enter your current iRODS password:
SSL Setup - Testing
On icat.renci.org, while connected to the iCAT server, let's put a file onto resource1Resc and then retrieve the file contents.
On resource1.renci.org, let's put a file onto icatResc and then retrieve the file:
myuser@icat:~/.irods$ echo 'this is a test' > test.txt
myuser@icat:~/.irods$ iput -R resource1Resc test.txt
myuser@icat:~/.irods$ iget test.txt -
this is a test
myuser@resource1:~/.irods$ echo 'This is another test' > test2.txt
myuser@resource1:~/.irods$ iput -R icatResc test2.txt
myuser@resource1:~/.irods$ iget test2.txt -
This is another test
SSL Setup - Summary
We have now set up iRODS to use SSL for data encryption during transfer.
Further confirmation could be done with network packet sniffers.
Now we'll configure PAM authentication to use this SSL configuration.
PAM Setup
Now we will configure authentication using PAM.
For this training session we'll configure PAM to authenticate using standard local UNIX authentication.
PAM uses SSL to send the password over the wire.
We already have SSL configured so we can "skip" ahead to configuring PAM itself.
PAM Setup - Create a Test UNIX and iRODS Account
We'll start by creating a UNIX user alice and giving her a password of test123.
Now create an iRODS user alice, but do not give her a password.
myuser@icat:~$ sudo adduser alice
Adding user `alice' ...
Adding new group `alice' (1002) ...
Adding new user `alice' (1002) with group `alice' ...
Creating home directory `/home/alice' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
myuser@icat:~$ iadmin mkuser alice rodsuser
PAM Setup - Configure PAM
Configure iRODS to use native UNIX authentication.
As root, create /etc/pam.d/irods and set the contents to:
See the following for more information on pam.d configuration.
myuser@icat:~$ cat /etc/pam.d/irods
auth required pam_env.so
auth sufficient pam_unix.so
auth requisite pam_succeed_if.so uid >= 500 quiet
auth required pam_deny.so
PAM Setup - Testing PAM
Update ~/.irods/irods_environment.json and set the irods_user_name to alice and the irods_authentication_scheme to PAM.
Here is a sample configuration file:
Note: You do not have to do this under the alice UNIX user. We created that user to demonstrate how iRODS can be configured to use PAM with native local Unix authentication.
{
"irods_host": "icat.renci.org",
"irods_zone_name": "tempZone",
"irods_port": 1247,
"irods_user_name": "alice",
"irods_authentication_scheme": "PAM",
"irods_client_server_negotiation": "request_server_negotiation",
"irods_client_server_policy": "CS_NEG_REQUIRE",
"irods_ssl_ca_certificate_file": "/etc/irods/ssl/irods.crt",
"irods_encryption_key_size": 16,
"irods_encryption_salt_size": 8,
"irods_encryption_num_hash_rounds": 16,
"irods_encryption_algorithm": "AES-256-CBC"
}
PAM Setup - Testing PAM
Now run iinit, but enter an invalid password.
Try again, but this time, enter test123 as the correct password:
No errors.
This indicates we were able to connect to iRODS successfully.
myuser@icat:~$ iinit
Enter your current PAM password:
myuser@icat:~$ ils
/tempZone/home/alice:
myuser@icat:~$ iinit
Enter your current PAM password:
[-] libpam.cpp:250:pam_auth_client_request : status [PAM_AUTH_PASSWORD_FAILED] errno [] -- message [call to rcAuthRequest failed.]
failed with error -993000 PAM_AUTH_PASSWORD_FAILED
PAM Setup - Testing PAM
As one final demonstration, let's disable SSL but leave PAM configured.
Update the ~/.irods/irods_environment.json to the following:
Also update /etc/irods/core.re so that it no longer enforces SSL:
{
"irods_host": "icat.renci.org",
"irods_zone_name": "tempZone",
"irods_port": 1247,
"irods_user_name": "alice",
"irods_authentication_scheme": "PAM",
"irods_client_server_negotiation": "request_server_negotiation",
"irods_client_server_policy": "CS_NEG_REFUSE",
"irods_ssl_ca_certificate_file": "/etc/irods/ssl/irods.crt",
"irods_encryption_key_size": 16,
"irods_encryption_salt_size": 8,
"irods_encryption_num_hash_rounds": 16,
"irods_encryption_algorithm": "AES-256-CBC"
}
acPreConnect(*OUT) { *OUT="CS_NEG_DONT_CARE"; }
PAM Setup - Testing PAM
Now let's see if PAM still works:
PAM still worked with the SSL data encryption settings disabled.
When logging into iRODS via PAM, SSL is always used to send the password to the server (PAM is plaintext on its own).
The irods_client_server_policy has no effect on PAM password protection in this case; the password will always be encrypted in transit.
myuser@icat:~$ iinit
Enter your current PAM password:
myuser@icat:~$