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:

 

  1. Default - No data encryption and no PAM

  2. Using SSL for data encryption only

  3. Using SSL for PAM only

  4. 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

 

  • iRODS iCAT server - icat.renci.org
  • iRODS Resource server - resource1.renci.org

 

Two storage resources exist - one on each server:

 

  • icatResc
  • resource1Resc

 

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:

  • CS_NEG_REQUIRE - Require all connections to use SSL
  • CS_NEG_REFUSE - Refuse any connections that attempt to use SSL
  • CS_NEG_DONT_CARE - Allow either with a preference towards SSL
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.

 

  • Create /etc/irods/ssl on resource1.renci.org and copy irods.crt, irods.key, and dhparams.pem into this directory.

 

  • Update /etc/irods/core.re to require SSL:
    "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.

  • Exit out of the service account (irods).
  • Create or update ~/.irods/irods_environment.json and add the following content:

 

 

 

 

 

 

  • Test the connection:
{
    "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.  

 

  1. We created a key and certificate and placed these on
    • icat.renci.org and
    • resource1.renci.org
  2. We configured both servers to require SSL.
  3. We configured four clients to require SSL.
    • The unix iRODS service accounts.
    • An additional account on each server.
  4. We tested the SSL connection two ways
    • On icat, we connected locally, and put/get a file onto resource1
    • On resource1, we connected locally, and put/get a file onto icat

 

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.

 https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Managing_Smart_Cards/PAM_Configuration_Files.html

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:~$ 
Made with Slides.com