From 34a1bde3e4c771a44b8e0aac279e44717ec23390 Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Tue, 17 Feb 2015 10:28:55 +0200 Subject: [PATCH 1/8] Add pki login logic --- app/controllers/epp/sessions_controller.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/controllers/epp/sessions_controller.rb b/app/controllers/epp/sessions_controller.rb index 1485001a8..94ee568b0 100644 --- a/app/controllers/epp/sessions_controller.rb +++ b/app/controllers/epp/sessions_controller.rb @@ -4,7 +4,12 @@ class Epp::SessionsController < EppController end def login - @api_user = ApiUser.find_by(login_params) + # pki login + if request.env['HTTP_SSL_CLIENT_S_DN_CN'] == login_params[:username] + @api_user = ApiUser.find_by(username: login_params[:username]) + else + @api_user = ApiUser.find_by(login_params) + end if @api_user.try(:active) epp_session[:api_user_id] = @api_user.id From 316f9376fe375619d354c77817ab69c8c68ef032 Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Thu, 19 Feb 2015 14:44:42 +0200 Subject: [PATCH 2/8] Allow logging in with only username --- app/api/repp/api.rb | 14 ++++++++++++-- app/controllers/epp/sessions_controller.rb | 4 ++-- config/routes.rb | 1 + 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/api/repp/api.rb b/app/api/repp/api.rb index 04b805597..ec0b3167f 100644 --- a/app/api/repp/api.rb +++ b/app/api/repp/api.rb @@ -3,8 +3,18 @@ module Repp format :json prefix :repp - http_basic do |username, password| - @current_user ||= ApiUser.find_by(username: username, password: password) + before do + auth_param = request.headers['Authorization'].split(' ', 2).second + username, password = ::Base64.decode64(auth_param || '').split(':', 2) + + # allow user lookup only by username if request came from webclient + if request.ip == APP_CONFIG['webclient_ip'] && password.blank? + login_params = { username: username } + else + login_params = { username: username, password: password } + end + + @current_user ||= ApiUser.find_by(login_params) end helpers do diff --git a/app/controllers/epp/sessions_controller.rb b/app/controllers/epp/sessions_controller.rb index 94ee568b0..4d7e2481b 100644 --- a/app/controllers/epp/sessions_controller.rb +++ b/app/controllers/epp/sessions_controller.rb @@ -4,8 +4,8 @@ class Epp::SessionsController < EppController end def login - # pki login - if request.env['HTTP_SSL_CLIENT_S_DN_CN'] == login_params[:username] + # Allow login with only username + if request.ip == APP_CONFIG['webclient_ip'] && login_params[:password].nil? @api_user = ApiUser.find_by(username: login_params[:username]) else @api_user = ApiUser.find_by(login_params) diff --git a/config/routes.rb b/config/routes.rb index cd9f85b81..e2bb835b3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,6 +3,7 @@ require 'epp_constraint' Rails.application.routes.draw do namespace(:epp, defaults: { format: :xml }) do match 'session/:action', controller: 'sessions', via: :all + match 'session/pki/:action', controller: 'sessions', via: :all post 'command/:action', controller: 'domains', constraints: EppConstraint.new(:domain) post 'command/:action', controller: 'contacts', constraints: EppConstraint.new(:contact) From 384d0cb96286db03f7ae22b6fe31583f4ca0a3e7 Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Thu, 19 Feb 2015 16:11:02 +0200 Subject: [PATCH 3/8] Improve changelog, certificate validation --- CHANGELOG.md | 37 ++++++++++++++++++++-- app/controllers/epp/sessions_controller.rb | 12 ++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79f0cc390..a7ac4eee8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ Go to registry shared folder and setup CA directory tree: ``` mkdir ca cd ca -mkdir certs crl newcerts private +mkdir certs crl newcerts private csrs chmod 700 private touch index.txt echo 1000 > serial @@ -45,12 +45,13 @@ authorityKeyIdentifier=keyid:always,issuer basicConstraints = CA:true keyUsage = cRLSign, keyCertSign +# For the CA policy [ policy_match ] countryName = optional stateOrProvinceName = optional organizationName = optional organizationalUnitName = optional -commonName = optional +commonName = supplied emailAddress = optional ``` @@ -60,6 +61,18 @@ openssl req -new -x509 -days 3650 -key private/ca.key.pem -sha256 -extensions v3 chmod 444 certs/ca.cert.pem ``` +Create a CSR for the webclient: +``` +openssl genrsa -out private/webclient.key.pem 4096 +chmod 400 private/webclient.key.pem +openssl req -sha256 -new -key private/webclient.key.pem -out csrs/webclient.csr.pem +``` + +Sign the request and create certificate: +``` +openssl ca -keyfile private/ca.key.pem -cert certs/ca.cert.pem -extensions usr_cert -notext -md sha256 -in csrs/webclient.csr.pem -out certs/webclient.cert.pem +``` + Configure EPP virtual host: ``` sudo nano /etc/apache2/sites-enabled/epp.conf @@ -75,10 +88,30 @@ With these lines: SSLVerifyClient require SSLVerifyDepth 1 SSLCACertificateFile /home/registry/registry/shared/ca/certs/ca.cert.pem + RequestHeader set SSL_CLIENT_S_DN_CN "%{SSL_CLIENT_S_DN_CN}s" +``` + +Configure webclient virtual host: +``` + SSLVerifyClient none + SSLVerifyDepth 1 + SSLCACertificateFile /home/registry/registry/shared/ca/certs/ca.cert.pem + + RequestHeader set SSL_CLIENT_S_DN_CN "" + + + SSLVerifyClient require + + + + SSLVerifyClient require + RequestHeader set SSL_CLIENT_S_DN_CN "%{SSL_CLIENT_S_DN_CN}s" + ``` Reload apache: ``` +sudo a2enmod headers sudo /etc/init.d/apache2 reload ``` diff --git a/app/controllers/epp/sessions_controller.rb b/app/controllers/epp/sessions_controller.rb index 4d7e2481b..53ac68421 100644 --- a/app/controllers/epp/sessions_controller.rb +++ b/app/controllers/epp/sessions_controller.rb @@ -3,15 +3,23 @@ class Epp::SessionsController < EppController render_epp_response('greeting') end + # rubocop: disable Metrics/PerceivedComplexity + # rubocop: disable Metrics/CyclomaticComplexity def login + cert_valid = true # Allow login with only username if request.ip == APP_CONFIG['webclient_ip'] && login_params[:password].nil? @api_user = ApiUser.find_by(username: login_params[:username]) + elsif request.ip == APP_CONFIG['webclient_ip'] + @api_user = ApiUser.find_by(login_params) else + if request.env['HTTP_SSL_CLIENT_S_DN_CN'] != login_params[:username] + cert_valid = false + end @api_user = ApiUser.find_by(login_params) end - if @api_user.try(:active) + if @api_user.try(:active) && cert_valid epp_session[:api_user_id] = @api_user.id render_epp_response('login_success') else @@ -19,6 +27,8 @@ class Epp::SessionsController < EppController render_epp_response('login_fail') end end + # rubocop: enable Metrics/PerceivedComplexity + # rubocop: enable Metrics/CyclomaticComplexity def logout @api_user = current_user # cache current_user for logging From 0f3c8ba94417b49ac34ffc42ddb7559e6e5ecf6e Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Thu, 19 Feb 2015 16:21:25 +0200 Subject: [PATCH 4/8] Improve changelog --- CHANGELOG.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 679be1f81..1fafac27f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -92,6 +92,11 @@ With these lines: ``` Configure webclient virtual host: +``` +sudo nano /etc/apache2/sites-enabled/webclient.conf +``` + +Add these lines: ``` SSLVerifyClient none SSLVerifyDepth 1 @@ -115,13 +120,19 @@ sudo a2enmod headers sudo /etc/init.d/apache2 reload ``` -Configure application.yml to match the CA settings: +Configure registry application.yml to match the CA settings: ``` ca_cert_path: '/home/registry/registry/shared/ca/certs/ca.cert.pem' ca_key_path: '/home/registry/registry/shared/ca/private/ca.key.pem' ca_key_password: 'registryalpha' ``` +Configure webclient application.yml to match the CA settings: +``` +cert_path: '/home/registry/registry/shared/ca/certs/webclient.cert.pem' +key_path: '/home/registry/registry/shared/ca/private/webclient.key.pem' +``` + 20.01.2015 * Added dedicated mina cron:setup and mina cron:clear for manual cron management. From 4f290bc9fe638f8a0041ed94f529e212d1d63ef9 Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Thu, 19 Feb 2015 17:48:30 +0200 Subject: [PATCH 5/8] Enable certificate creating on api users --- CHANGELOG.md | 5 +++-- app/models/api_user.rb | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fafac27f..0b382086b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -117,14 +117,15 @@ Add these lines: Reload apache: ``` sudo a2enmod headers -sudo /etc/init.d/apache2 reload +sudo /etc/init.d/apache2 restart ``` -Configure registry application.yml to match the CA settings: +Configure registry and epp application.yml to match the CA settings: ``` ca_cert_path: '/home/registry/registry/shared/ca/certs/ca.cert.pem' ca_key_path: '/home/registry/registry/shared/ca/private/ca.key.pem' ca_key_password: 'registryalpha' +webclient_ip: '54.154.91.240' ``` Configure webclient application.yml to match the CA settings: diff --git a/app/models/api_user.rb b/app/models/api_user.rb index aee1ff203..1dd0b6ea6 100644 --- a/app/models/api_user.rb +++ b/app/models/api_user.rb @@ -9,7 +9,7 @@ class ApiUser < User validates :username, :password, :registrar, presence: true validates :username, uniqueness: true - # before_save :create_crt, if: -> (au) { au.csr_changed? } + before_save :create_crt, if: -> (au) { au.csr_changed? } attr_accessor :registrar_typeahead From 4a5234f7892b4cd72f1d898becc6423eadb344ab Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Thu, 19 Feb 2015 17:58:48 +0200 Subject: [PATCH 6/8] Show crt download link --- app/views/admin/api_users/show.haml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/admin/api_users/show.haml b/app/views/admin/api_users/show.haml index f8f09a701..63ffc3952 100644 --- a/app/views/admin/api_users/show.haml +++ b/app/views/admin/api_users/show.haml @@ -43,7 +43,7 @@ %dd - %dt= t('crt') - / - if @api_user.csr - / %dd= link_to(t('download'), download_crt_admin_api_user_path) - / - else - / %dd - + - if @api_user.csr + %dd= link_to(t('download'), download_crt_admin_api_user_path) + - else + %dd - From adfe2b3ddb58de26700c4a4024b67abf9f447e5e Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Thu, 19 Feb 2015 18:21:59 +0200 Subject: [PATCH 7/8] Improve readme --- CHANGELOG.md | 15 +++++----- README.md | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b382086b..fa40a47bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,8 +57,8 @@ emailAddress = optional Issue the root certificate (prompts for additional data): ``` -openssl req -new -x509 -days 3650 -key private/ca.key.pem -sha256 -extensions v3_ca -out certs/ca.cert.pem -chmod 444 certs/ca.cert.pem +openssl req -new -x509 -days 3650 -key private/ca.key.pem -sha256 -extensions v3_ca -out certs/ca.crt.pem +chmod 444 certs/ca.crt.pem ``` Create a CSR for the webclient: @@ -70,7 +70,7 @@ openssl req -sha256 -new -key private/webclient.key.pem -out csrs/webclient.csr. Sign the request and create certificate: ``` -openssl ca -keyfile private/ca.key.pem -cert certs/ca.cert.pem -extensions usr_cert -notext -md sha256 -in csrs/webclient.csr.pem -out certs/webclient.cert.pem +openssl ca -keyfile private/ca.key.pem -cert certs/ca.crt.pem -extensions usr_cert -notext -md sha256 -in csrs/webclient.csr.pem -out certs/webclient.crt.pem ``` Configure EPP virtual host: @@ -87,7 +87,7 @@ With these lines: ``` SSLVerifyClient require SSLVerifyDepth 1 - SSLCACertificateFile /home/registry/registry/shared/ca/certs/ca.cert.pem + SSLCACertificateFile /home/registry/registry/shared/ca/certs/ca.crt.pem RequestHeader set SSL_CLIENT_S_DN_CN "%{SSL_CLIENT_S_DN_CN}s" ``` @@ -100,7 +100,7 @@ Add these lines: ``` SSLVerifyClient none SSLVerifyDepth 1 - SSLCACertificateFile /home/registry/registry/shared/ca/certs/ca.cert.pem + SSLCACertificateFile /home/registry/registry/shared/ca/certs/ca.crt.pem RequestHeader set SSL_CLIENT_S_DN_CN "" @@ -109,7 +109,6 @@ Add these lines: - SSLVerifyClient require RequestHeader set SSL_CLIENT_S_DN_CN "%{SSL_CLIENT_S_DN_CN}s" ``` @@ -122,7 +121,7 @@ sudo /etc/init.d/apache2 restart Configure registry and epp application.yml to match the CA settings: ``` -ca_cert_path: '/home/registry/registry/shared/ca/certs/ca.cert.pem' +ca_cert_path: '/home/registry/registry/shared/ca/certs/ca.crt.pem' ca_key_path: '/home/registry/registry/shared/ca/private/ca.key.pem' ca_key_password: 'registryalpha' webclient_ip: '54.154.91.240' @@ -130,7 +129,7 @@ webclient_ip: '54.154.91.240' Configure webclient application.yml to match the CA settings: ``` -cert_path: '/home/registry/registry/shared/ca/certs/webclient.cert.pem' +cert_path: '/home/registry/registry/shared/ca/certs/webclient.crt.pem' key_path: '/home/registry/registry/shared/ca/private/webclient.key.pem' ``` diff --git a/README.md b/README.md index 92b8f67c6..2733fd2bd 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,8 @@ Be sure to update paths to match your system configuration. SSLVerifyClient require SSLVerifyDepth 1 - SSLCACertificateFile /home/registry/registry/shared/ca/certs/ca.cert.pem + SSLCACertificateFile /home/registry/registry/shared/ca/certs/ca.crt.pem + RequestHeader set SSL_CLIENT_S_DN_CN "%{SSL_CLIENT_S_DN_CN}s" EPPEngine On EPPCommandRoot /proxy/command @@ -181,6 +182,86 @@ All registry demo data can be found at: Initially you can use two type of users: admin users and EPP users. +### CA + +Go to registry shared folder and setup CA directory tree: +``` +mkdir ca +cd ca +mkdir certs crl newcerts private csrs +chmod 700 private +touch index.txt +echo 1000 > serial +``` + +Generate the root key (prompts for pass phrase): +``` +openssl genrsa -aes256 -out private/ca.key.pem 4096 +``` + +Configure OpenSSL: +``` +sudo su - +cd /etc/ssl/ +cp openssl.cnf openssl.cnf.bak +nano openssl.cnf +exit +``` + +Make sure the following options are in place: +``` +[ CA_default ] +# Where everything is kept +dir = /home/registry/registry/shared/ca + +[ usr_cert ] +# These extensions are added when 'ca' signs a request. +basicConstraints=CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +nsComment = "OpenSSL Generated Certificate" +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +[ v3_ca ] +# Extensions for a typical CA +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer +basicConstraints = CA:true +keyUsage = cRLSign, keyCertSign + +# For the CA policy +[ policy_match ] +countryName = optional +stateOrProvinceName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional +``` + +Issue the root certificate (prompts for additional data): +``` +openssl req -new -x509 -days 3650 -key private/ca.key.pem -sha256 -extensions v3_ca -out certs/ca.crt.pem +chmod 444 certs/ca.crt.pem +``` + +Create a CSR for the webclient: +``` +openssl genrsa -out private/webclient.key.pem 4096 +chmod 400 private/webclient.key.pem +openssl req -sha256 -new -key private/webclient.key.pem -out csrs/webclient.csr.pem +``` + +Sign the request and create certificate: +``` +openssl ca -keyfile private/ca.key.pem -cert certs/ca.crt.pem -extensions usr_cert -notext -md sha256 -in csrs/webclient.csr.pem -out certs/webclient.crt.pem +``` + +Certificates for API Users are generated via the user interface. CSR must be uploaded for each API User. Certificates are created automatically after saving the user. + +Private key and certificate must be packaged to pkcs12 and added to the browser's certificate bank. + +Make sure application configuration files contain correct paths to certificates. ### EPP web client From fe67c5143649b1cf77d276997b6303e105d91801 Mon Sep 17 00:00:00 2001 From: Martin Lensment Date: Fri, 20 Feb 2015 11:58:49 +0200 Subject: [PATCH 8/8] Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa40a47bc..cdee71470 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -108,7 +108,8 @@ Add these lines: SSLVerifyClient require - + + SSLVerifyClient require RequestHeader set SSL_CLIENT_S_DN_CN "%{SSL_CLIENT_S_DN_CN}s" ```