Wednesday, 4 June 2014

Client side SSL Certificate Authentication with Rails and Nginx

Hi,
     Recently i worked on one application which required SSL client certificate based authentication.
So just wanted to share it with you all about how it can be integrated in Rails application.This article is about using SSL certificates installed into a web browser to authenticate against a Ruby on Rails application with Nginx.

Steps for creating certificates,

1) First thing you will need is to configure openssl.cnf, check following gist for configuring your openssl.cnf , as its big file so cant embed here. https://gist.github.com/pandurang90/dbe6a67339747ef5bacf 
In this configuration important thing is setting path to CA dir,
[ CA_default ]
dir = /path/to/ca
this is the path where you are going create your CA.

2) Then you will need to create your own CA(Certificate Authority) that issues Digital certificates.
For that we will use CA.pl script is a perl script that supplies the relevant command line arguments to the openssl command for some common certificate operations. It is intended to simplify the process of certificate creation and management by the use of some simple options.
cd /path/to/ca
CA.pl -newca 
Make sure here you enter domain name in common name field when asked in this.

3) Now generate web server CSR
openssl req -new -nodes -keyout www.example.org.key -out www.example.org.csr
then self sign web server Certificate
openssl ca -config /etc/openssl.cnf -policy policy_anything -out www.example.org.crt -infiles www.example.org.csr
that gives you web server certificates

4) Now its time to configure nginx server,
 https://gist.github.com/pandurang90/8f0c11819db4c866d985

5) Generating Client certificate, 
CERT_DIR = "path/to/ca"
  user_name = "test user"
  id = 1

  def create_p12
    subj = "/C=US/ST=YourState/L=city/O=example/OU=example/CN=#{user_name})/emailAddress=#{email}"
    dir_name  = "#{CERT_DIR}#{id}"
    Dir.mkdir(dir_name) unless File.directory?(dir_name)
    create_cert(subj)
    sign_cert
    generate_p12
  end

  def create_cert(subj)
    system("openssl req -new -sha1 -newkey rsa:1024 -nodes -keyout #{CERT_DIR}#{id}/#{user_name}.key -out #{CERT_DIR}#{id}/#{user_name}.csr -subj '#{subj}'")
  end

  def sign_cert
    system("openssl ca -batch -config /usr/lib/ssl/openssl.cnf -policy policy_anything -extensions ssl_client -out #{CERT_DIR}#{id}/#{user_name}.crt -infiles #{CERT_DIR}#{id}/#{user_name}.csr")
  end

  def generate_p12
    system("openssl pkcs12 -export -clcerts -in #{CERT_DIR}#{id}/#{user_name}.crt -certfile #{CERT_DIR}demoCA/cacert.pem -inkey #{CERT_DIR}#{id}/#{user_name}.key -out #{CERT_DIR}#{id}/#{user_name}.p12 -name '#{name}' -passout pass:#{export_password} ")
  end
Here ,
subj = "/C=US/ST=YourState/L=city/O=example/OU=example/CN=#{user_name})/emailAddress=#{email}"
is a subject for certificate which can be unique for each user or same based on settings in your openssl.cnf.

6) Install your certificate on web browser(p12 file), then hit url of website and it will ask to submit client certificate , just select required certificate from list and submit. Then in your controller you can get certificate using,
cert = request.env["HTTP_X_SSL_CLIENT_S_DN"]
 as we have initialized variable in nginx configuration.
proxy_set_header X-SSL-Client-S-DN   $ssl_client_cert 
You can check more options on http://nginx.org/en/docs/http/ngx_http_ssl_module.html

7) You can verify whether certificate submitted by user is valid or not , using
request.env["HTTP-X-CLIENT-VERIFY"]
returns the result of client certificate verification: “SUCCESS”, “FAILED”, and “NONE” if a certificate was not present.







Wednesday, 22 January 2014

Transfer files over netcat using Applescript

Hi,
    At my workplace me and one of my colleague used to transfer files like database dumps etc. for projects from one machine to another.
I came across netcat (nc command) and when we tried that it just worked so quickly, i got surprised with the speed with which it got transferred. :)
So i wrote applescript that transfers file using netcat, with dialog boxes.

after saving(netcat.scpt) this file to your machine just type in your terminal
osascript your_path/netcat.scpt
It will simplify your work to transfer file rather than remembering syntax for netcat 
  OR 
if you want more shortcut to do this you can add it to .bash_profile file
alias netcat='osascript your_path/netcat.scpt'

and then just type netcat in terminal.. enjoy :)

Tuesday, 7 January 2014

Ruby gem feature_flags new features (0.1.0)

Hi,
Back again with new features in ruby gem feature_flags (0.1.0).
Here is my blog post on old version of feature_flags . I recommend to go through it first if you haven't, to know more features available in this gem.

Memoization of features is the main change in this version and it really improved performance. Its much more fast now,

What's new  ????

1)  Added Memoization:
In previous versions, Everytime it fires sql query to check whether particular feature is enabled or not when we check
FeatureFlags.enabled?(:feature_name)
worrying about that ???? Now you need not to because it will fire sql query only when there are changes into database, and memoise it, and that optimizes it to great extent.

2) Check for multiple features at a time:
There may be situation when you need to check following scenario with multiple features,
if FeatureFlags.enabled?(:feature_name1) && FeatureFlags.enabled?(:feature_name2) && FeatureFlags.enabled?(:feature_name3)
  ## some code
else
  ## some code
end

 which really increases your code, So now you can do it in better ways
if FeatureFlags.enabled?([:feature_name1, :feature_name2, :feature_name3])
   ## some code
end
 So when you have more than one features to check simultaneously, pass them as array of feature names
 but if you have single feature to check then just write
  if FeatureFlags.enabled?(:feature_name)
    ## some code
  end
3) Another feature is that you can check if any of given features are active or not:
if FeatureFlags.enabled_any?([:feature_name1, :feature_name2, :feature_name3])
   ## some code
end
this will execute code inside if any of [:feature_name1, :feature_name2, :feature_name3] feature is active

4) UI changes:
  Do everything on single page (add, edit, enable, disable, remove)



If you are already using previous versions(<= 0.0.3) and want to migrate to this version (0.1.0) then, after updating gem version
just add following line to your model
  include FeatureFlags::FeatureBase
and generate views again..if you have already generated for new updated view
rails generate feature_flags:views
thats it n you are done.  :)

Here is demo http://feature-flags.herokuapp.com/