Tuesday, January 9, 2018

TLS and Mutual TLS handshake data overhead



I needed to test the data transfer involved in TLS and Mutual TLS handshake. I found bits of information on different sites. I thought it will be good to put all the information in one place and show the E2E flow.

There are 3 steps:
  • Prepare the client and server certificates
  • Configure NGINX
  • Test the handshake


Prepare the client and the server certificates


Generate client key pair and self-signed certificate


$/rnd/TLS/rsaclient: keytool -genkey -keyalg RSA -alias test -keystore clientselfsignedrsa.jks -validity 30 -keysize 2048

You will be prompted to enter password and few other details when generating certificates.

Generate server key pair and self-signed certificate


$/rnd/TLS/rsaserver: keytool -genkey -keyalg RSA -alias test -keystore serverselfsignedrsa.jks -validity 30 -keysize 2048

You will be prompted to enter password and few other details when generating certificates.

Extract client certificate and private key



$/rnd/TLS/rsaclient: keytool -importkeystore -srckeystore clientselfsignedrsa.jks -destkeystore pkcs12-keystore.p12 -deststoretype PKCS12

$/rnd/TLS/rsaclient: openssl pkcs12 -nokeys -in pkcs12-keystore.p12 -out rsaclientcert.pem

$/rnd/TLS/rsaclient: openssl pkcs12 -nocerts -nodes -in pkcs12-keystore.p12 -out rcsclientkey.key


Extract server certificate and private key


$/rnd/TLS/rsaserver: keytool -importkeystore -srckeystore serverselfsignedrsa.jks -destkeystore pkcs12-keystore.p12 -deststoretype PKCS12

$/rnd/TLS/rsaserver: openssl pkcs12 -nokeys -in pkcs12-keystore.p12 -out rsaservercert.pem

$/rnd/TLS/rsaserver: openssl pkcs12 -nocerts -nodes -in pkcs12-keystore.p12 -out rsaserverkey.key



Configure NGINX


The config file on mac is under /usr/local/etc/nginx

Edit the HTTPS server section and reload nginx (nginx -s reload)

    # HTTPS server
    #
    server {
        listen       8443 ssl;
        server_name  localhost;

        ssl_certificate      /rnd/TLS/rsaserver/rsaservercert.pem;
        ssl_certificate_key  /rnd/TLS/rsaserver/rsaserverkey.key;
ssl_client_certificate /rnd/TLS/rsaclient/rsaclientcert.pem;
        # Comment/Uncomment following line based on whether you want Mutual TLS or not.
ssl_verify_client on;
ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;

        ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

        location / {
            root   html;
            index  index.html index.htm;
        }
    }


Start wireshark capture with filter as "port 8443"

Test TLS Handshake


I have stripped some of the details from below trace to keep the size in check.

Mutual TLS (ssl_verify_client on;)


$ openssl s_client -connect localhost:8443 -cert /rnd/TLS/rsaclient/rsaclientcert.pem -key /rnd/TLS/rsaclient/rcsclientkey.key  -CAfile /rnd/TLS/rsaserver/rsaservercert.pem -state -debug
CONNECTED(00000003)
SSL_connect:before/connect initialization
.......
SSL_connect:SSLv2/v3 write client hello A
......
SSL_connect:SSLv3 read server hello A
......
SSL_connect:SSLv3 read server certificate A
......
SSL_connect:SSLv3 read server key exchange A
......
SSL_connect:SSLv3 read server certificate request A
SSL_connect:SSLv3 read server done A
......
SSL_connect:SSLv3 write client certificate A
......
SSL_connect:SSLv3 write client key exchange A
......
SSL_connect:SSLv3 write certificate verify A
......
SSL_connect:SSLv3 write change cipher spec A
......
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
......
SSL_connect:SSLv3 read server session ticket A
......
SSL_connect:SSLv3 read finished A
---
Certificate chain
......
---
Server certificate
-----BEGIN CERTIFICATE-----
......
-----END CERTIFICATE-----
---
---
SSL handshake has read 2619 bytes and written 1621 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:

    Start Time: 1515538253
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)


Without Mutual TLS (comment ssl_verify_client on; in NGINX conf)



$ openssl s_client -connect localhost:8443 -cert /rnd/TLS/rsaclient/rsaclientcert.pem -key /rnd/TLS/rsaclient/rcsclientkey.key  -CAfile /rnd/TLS/rsaserver/rsaservercert.pem -state -debug
CONNECTED(00000003)
SSL_connect:before/connect initialization
......
SSL_connect:SSLv2/v3 write client hello A
......
SSL_connect:SSLv3 read server hello A
......
SSL_connect:SSLv3 read server certificate A
......
SSL_connect:SSLv3 read server key exchange A
......
SSL_connect:SSLv3 read server done A
......
SSL_connect:SSLv3 write client key exchange A
......
SSL_connect:SSLv3 write change cipher spec A
......
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
......
SSL_connect:SSLv3 read server session ticket A
......
SSL_connect:SSLv3 read finished A
---
Certificate chain
......
---
Server certificate
-----BEGIN CERTIFICATE-----
......
-----END CERTIFICATE-----
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 1568 bytes and written 444 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
   
    Start Time: 1515538406
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)



Finally some numbers


Following is the summary of amount of data transferred during TLS handshake. This is relevant and may be a concern for OTA interfaces like cellular interfaces due to cost of data. These can be optimized with various TLS configuration on the server side. The objective of this exercise was to understand the data overhead in general.


  • TLS with RSA 2048 bit key - 2932 bytes
  • Mutual TLS with RSA 2048 bit key - 5384 bytes

  • TLS with ECC 256 bit key - 2356 bytes
  • Mutual TLS with ECC 256 bit key - 3847 bytes



Wednesday, October 4, 2017

Docker storage options

There are 2 options for storing data:
  • Within the container on its own filesystem - Not recommended for write heavy workloads
  • Outside the container

There are 3 options for mounting data from docker host:
  • Volumes
  • Bind mount
  • Tmpfs mount



Volumes

  • Stored on host filesystem
  • Managed by docker (/var/lib/docker/volumes/
  • Option recommended by docker
  • Can create named volumes or anonymous volumes
  • Support use of volume drivers that allow you to write data outside container. For eg Flocker, Convoy, sshfs etc See list here
  • Good option when sharing data between containers
  • Reference: https://docs.docker.com/engine/admin/volumes/volumes/

Bind mounts


Tmpfs mount


Performance Difference

Following shows performance of different mount options on Ubuntu instance on AWS t2.micro. (Doesn't include volume driver option as it will vary from driver to driver). Look for kB/s or MB/s
Reference: https://github.com/moby/moby/issues/21485

On host
ubuntu@host:~/nks$ sudo time dd if=/dev/zero of=/home/ubuntu/nks/out.txt bs=512 count=1000 oflag=dsync
1000+0 records in
1000+0 records out
512000 bytes (512 kB, 500 KiB) copied, 1.91264 s, 268 kB/s
0.02user 0.00system 0:01.91elapsed 1%CPU (0avgtext+0avgdata 2032maxresident)k
0inputs+8000outputs (0major+82minor)pagefaults 0swaps


Named volume
ubuntu@host:~/nks$ sudo docker volume create my-vol
my-vol
ubuntu@host:~/nks$ sudo docker volume ls
DRIVER              VOLUME NAME
local               my-vol
ubuntu@host:~/nks$ sudo docker run --rm --net=none --log-driver=none --read-only -v "my-vol:/nks" ubuntu bash -c "time dd if=/dev/zero of=/nks/out.txt bs=512 count=1000 oflag=dsync"
1000+0 records in
1000+0 records out
512000 bytes (512 kB, 500 KiB) copied, 1.90823 s, 268 kB/s

real 0m1.909s
user 0m0.000s
sys 0m0.028s

Host bind mount

ubuntu@host:~/nks$ sudo docker run --rm --net=none --log-driver=none --read-only -v "/home/ubuntu/nks:/nks" ubuntu bash -c "time dd if=/dev/zero of=/nks/out.txt bs=512 count=1000 oflag=dsync"
1000+0 records in
1000+0 records out
512000 bytes (512 kB, 500 KiB) copied, 2.10316 s, 243 kB/s

real 0m2.104s
user 0m0.028s
sys 0m0.000s

tmpfs mount

ubuntu@host:~/nks$ sudo docker run --rm --net=none --log-driver=none --read-only --mount type=tmpfs,destination=/nks ubuntu bash -c "time dd if=/dev/zero of=/nks/out.txt bs=512 count=1000 oflag=dsync"
1000+0 records in
1000+0 records out
512000 bytes (512 kB, 500 KiB) copied, 0.000757215 s, 676 MB/s

real 0m0.001s
user 0m0.000s
sys 0m0.000s
ubuntu@host:~/nks$
 

Storing data within container

  • Data is not persistent across container lifecycle
  • Inefficient for write heavy workloads due to disk block allocation and write through storage drivers
  • Pick driver that works best for you. Choice may be limited by the OS.
  • Reference: https://docs.docker.com/engine/userguide/storagedriver/




Wednesday, September 13, 2017

Build nginx from source on AWS EC2




Launch a new EC2

Type: t2.small (t2.micro may also be fine)
AMIUbuntu Server 16.04 LTS (HVM), SSD Volume Type - ami-6e1a0117

Configure nginx repository

ubuntu@ubuntu:sudo su
root@ubuntu:edit /etc/hosts and add entry for hostname to ip
root@ubuntu:cd /opt
root@ubuntu:add-apt-repository ppa:nginx/stable
edit /etc/apt/sources.list.d/nginx-ubuntu-stable-xenial.list and uncomment deb-src line
root@ubuntu:apt-get update

Install nginx dependencies and get source

root@ubuntu:apt-get build-dep nginx

root@ubuntu:/opt# apt-get source nginx
Reading package lists... Done
NOTICE: 'nginx' packaging is maintained in the 'Git' version control system at:
https://anonscm.debian.org/cgit/pkg-nginx/nginx.git
Please use:
git clone https://anonscm.debian.org/cgit/pkg-nginx/nginx.git
to retrieve the latest (possibly unreleased) updates to the package.
Need to get 1,835 kB of source archives.
Get:1 http://ppa.launchpad.net/nginx/stable/ubuntu xenial/main nginx 1.12.1-0+xenial0 (tar) [981 kB]
Get:2 http://ppa.launchpad.net/nginx/stable/ubuntu xenial/main nginx 1.12.1-0+xenial0 (diff) [849 kB]
Get:3 http://ppa.launchpad.net/nginx/stable/ubuntu xenial/main nginx 1.12.1-0+xenial0 (dsc) [4,187 B]
Fetched 1,835 kB in 1s (924 kB/s)
gpgv: Signature made Wed 12 Jul 2017 11:41:54 PM UTC using RSA key ID F569EF55
gpgv: Can't check signature: public key not found
dpkg-source: warning: failed to verify signature on ./nginx_1.12.1-0+xenial0.dsc
dpkg-source: info: extracting nginx in nginx-1.12.1
dpkg-source: info: unpacking nginx_1.12.1.orig.tar.gz
dpkg-source: info: unpacking nginx_1.12.1-0+xenial0.debian.tar.xz
dpkg-source: info: applying 0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch
dpkg-source: info: applying 0003-define_gnu_source-on-other-glibc-based-platforms.patch
W: Can't drop privileges for downloading as file 'nginx_1.12.1.orig.tar.gz' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied)
root@ubuntu:/opt# ls 
nginx-1.12.1  nginx_1.12.1-0+xenial0.debian.tar.xz  nginx_1.12.1-0+xenial0.dsc  nginx_1.12.1.orig.tar.gz
root@ubuntu:/opt#

Build nginx (debian package)

root@ubuntu:/opt/nginx-1.12.1# cd nginx-1.12.1/
root@ubuntu:/opt/nginx-1.12.1# dpkg-buildpackage -uc -b
dpkg-buildpackage: source package nginx
dpkg-buildpackage: source version 1.12.1-0+xenial0
dpkg-buildpackage: source distribution xenial
dpkg-buildpackage: source changed by Thomas Ward
dpkg-buildpackage: host architecture amd64
 dpkg-source --before-build nginx-1.12.1
 debian/rules clean
dh clean --with systemd
   dh_testdir
   dh_auto_clean
   debian/rules override_dh_clean
make[1]: Entering directory '/opt/nginx-1.12.1'
if [ -s /opt/nginx-1.12.1/debian/modules/nginx-cache-purge/.pc/applied-patches ]; then \
cd /opt/nginx-1.12.1/debian/modules/nginx-cache-purge && QUILT_PATCHES=/opt/nginx-1.12.1/debian/modules/patches/nginx-cache-purge quilt pop -q -a; \
...
...
...
   dh_builddeb
dpkg-deb --build debian/nginx ..
dpkg-deb: building package 'nginx' in '../nginx_1.12.1-0+xenial0_all.deb'.
dpkg-deb --build debian/nginx-doc ..
dpkg-deb: building package 'nginx-doc' in '../nginx-doc_1.12.1-0+xenial0_all.deb'.
dpkg-deb --build debian/nginx-common ..
dpkg-deb: building package 'nginx-common' in '../nginx-common_1.12.1-0+xenial0_all.deb'.
dpkg-deb --build debian/nginx-full ..
dpkg-deb: building package 'nginx-full' in '../nginx-full_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/nginx-light ..
dpkg-deb: building package 'nginx-light' in '../nginx-light_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/nginx-extras ..
dpkg-deb: building package 'nginx-extras' in '../nginx-extras_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-geoip ..
dpkg-deb: building package 'libnginx-mod-http-geoip' in '../libnginx-mod-http-geoip_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-image-filter ..
dpkg-deb: building package 'libnginx-mod-http-image-filter' in '../libnginx-mod-http-image-filter_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-xslt-filter ..
dpkg-deb: building package 'libnginx-mod-http-xslt-filter' in '../libnginx-mod-http-xslt-filter_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-mail ..
dpkg-deb: building package 'libnginx-mod-mail' in '../libnginx-mod-mail_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-stream ..
dpkg-deb: building package 'libnginx-mod-stream' in '../libnginx-mod-stream_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-perl ..
dpkg-deb: building package 'libnginx-mod-http-perl' in '../libnginx-mod-http-perl_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-auth-pam ..
dpkg-deb: building package 'libnginx-mod-http-auth-pam' in '../libnginx-mod-http-auth-pam_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-lua ..
dpkg-deb: building package 'libnginx-mod-http-lua' in '../libnginx-mod-http-lua_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-ndk ..
dpkg-deb: building package 'libnginx-mod-http-ndk' in '../libnginx-mod-http-ndk_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-nchan ..
dpkg-deb: building package 'libnginx-mod-nchan' in '../libnginx-mod-nchan_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-echo ..
dpkg-deb: building package 'libnginx-mod-http-echo' in '../libnginx-mod-http-echo_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-upstream-fair ..
dpkg-deb: building package 'libnginx-mod-http-upstream-fair' in '../libnginx-mod-http-upstream-fair_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-headers-more-filter ..
dpkg-deb: building package 'libnginx-mod-http-headers-more-filter' in '../libnginx-mod-http-headers-more-filter_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-cache-purge ..
dpkg-deb: building package 'libnginx-mod-http-cache-purge' in '../libnginx-mod-http-cache-purge_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-fancyindex ..
dpkg-deb: building package 'libnginx-mod-http-fancyindex' in '../libnginx-mod-http-fancyindex_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-uploadprogress ..
dpkg-deb: building package 'libnginx-mod-http-uploadprogress' in '../libnginx-mod-http-uploadprogress_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-subs-filter ..
dpkg-deb: building package 'libnginx-mod-http-subs-filter' in '../libnginx-mod-http-subs-filter_1.12.1-0+xenial0_amd64.deb'.
dpkg-deb --build debian/libnginx-mod-http-dav-ext ..
dpkg-deb: building package 'libnginx-mod-http-dav-ext' in '../libnginx-mod-http-dav-ext_1.12.1-0+xenial0_amd64.deb'.
 dpkg-genchanges -b >../nginx_1.12.1-0+xenial0_amd64.changes
dpkg-genchanges: binary-only upload (no source code included)
 dpkg-source --after-build nginx-1.12.1
dpkg-buildpackage: binary-only upload (no source included)
root@ubuntu:/opt/nginx-1.12.1#



Verify the build output

root@ubuntu:/opt/nginx-1.12.1# ls -l ../
total 4084
-rw-r--r--  1 root root  28526 Sep 13 21:51 libnginx-mod-http-auth-pam_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  30820 Sep 13 21:51 libnginx-mod-http-cache-purge_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  30218 Sep 13 21:51 libnginx-mod-http-dav-ext_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  39874 Sep 13 21:51 libnginx-mod-http-echo_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  33470 Sep 13 21:51 libnginx-mod-http-fancyindex_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  29760 Sep 13 21:51 libnginx-mod-http-geoip_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  33794 Sep 13 21:51 libnginx-mod-http-headers-more-filter_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  32984 Sep 13 21:51 libnginx-mod-http-image-filter_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root 166044 Sep 13 21:51 libnginx-mod-http-lua_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  29014 Sep 13 21:51 libnginx-mod-http-ndk_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  40154 Sep 13 21:51 libnginx-mod-http-perl_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  31482 Sep 13 21:51 libnginx-mod-http-subs-filter_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  34958 Sep 13 21:51 libnginx-mod-http-uploadprogress_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  31676 Sep 13 21:51 libnginx-mod-http-upstream-fair_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  31466 Sep 13 21:51 libnginx-mod-http-xslt-filter_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  59964 Sep 13 21:51 libnginx-mod-mail_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root 170052 Sep 13 21:51 libnginx-mod-nchan_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root  80960 Sep 13 21:51 libnginx-mod-stream_1.12.1-0+xenial0_amd64.deb
drwxr-xr-x 10 root root   4096 Sep 13 21:46 nginx-1.12.1
-rw-r--r--  1 root root  24320 Sep 13 21:51 nginx_1.12.1-0+xenial0_all.deb
-rw-r--r--  1 root root  10357 Sep 13 21:51 nginx_1.12.1-0+xenial0_amd64.changes
-rw-r--r--  1 root root 849428 Jul 14 14:28 nginx_1.12.1-0+xenial0.debian.tar.xz
-rw-r--r--  1 root root   4187 Jul 14 14:28 nginx_1.12.1-0+xenial0.dsc
-rw-r--r--  1 root root 981093 Jul 14 14:28 nginx_1.12.1.orig.tar.gz
-rw-r--r--  1 root root  56958 Sep 13 21:51 nginx-common_1.12.1-0+xenial0_all.deb
-rw-r--r--  1 root root  35892 Sep 13 21:51 nginx-doc_1.12.1-0+xenial0_all.deb
-rw-r--r--  1 root root 425094 Sep 13 21:51 nginx-extras_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root 412056 Sep 13 21:51 nginx-full_1.12.1-0+xenial0_amd64.deb
-rw-r--r--  1 root root 389160 Sep 13 21:51 nginx-light_1.12.1-0+xenial0_amd64.deb
root@ubuntu:/opt/nginx-1.12.1#

Install newly build nginx and dependencies

root@ubuntu:/opt# dpkg --install libnginx-mod-*
Selecting previously unselected package libnginx-mod-http-auth-pam.
(Reading database ... 57824 files and directories currently installed.)
Preparing to unpack libnginx-mod-http-auth-pam_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-auth-pam (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-http-cache-purge.
Preparing to unpack libnginx-mod-http-cache-purge_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-cache-purge (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-http-dav-ext.
Preparing to unpack libnginx-mod-http-dav-ext_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-dav-ext (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-http-echo.
Preparing to unpack libnginx-mod-http-echo_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-echo (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-http-fancyindex.
Preparing to unpack libnginx-mod-http-fancyindex_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-fancyindex (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-http-geoip.
Preparing to unpack libnginx-mod-http-geoip_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-geoip (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-http-headers-more-filter.
Preparing to unpack libnginx-mod-http-headers-more-filter_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-headers-more-filter (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-http-image-filter.
Preparing to unpack libnginx-mod-http-image-filter_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-image-filter (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-http-lua.
Preparing to unpack libnginx-mod-http-lua_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-lua (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-http-ndk.
Preparing to unpack libnginx-mod-http-ndk_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-ndk (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-http-perl.
Preparing to unpack libnginx-mod-http-perl_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-perl (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-http-subs-filter.
Preparing to unpack libnginx-mod-http-subs-filter_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-subs-filter (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-http-uploadprogress.
Preparing to unpack libnginx-mod-http-uploadprogress_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-uploadprogress (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-http-upstream-fair.
Preparing to unpack libnginx-mod-http-upstream-fair_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-upstream-fair (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-http-xslt-filter.
Preparing to unpack libnginx-mod-http-xslt-filter_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-http-xslt-filter (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-mail.
Preparing to unpack libnginx-mod-mail_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-mail (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-nchan.
Preparing to unpack libnginx-mod-nchan_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-nchan (1.12.1-0+xenial0) ...
Selecting previously unselected package libnginx-mod-stream.
Preparing to unpack libnginx-mod-stream_1.12.1-0+xenial0_amd64.deb ...
Unpacking libnginx-mod-stream (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-auth-pam (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-cache-purge (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-dav-ext (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-echo (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-fancyindex (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-geoip (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-headers-more-filter (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-image-filter (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-ndk (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-perl (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-subs-filter (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-uploadprogress (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-upstream-fair (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-xslt-filter (1.12.1-0+xenial0) ...
Setting up libnginx-mod-mail (1.12.1-0+xenial0) ...
Setting up libnginx-mod-nchan (1.12.1-0+xenial0) ...
Setting up libnginx-mod-stream (1.12.1-0+xenial0) ...
Setting up libnginx-mod-http-lua (1.12.1-0+xenial0) ...
root@ubuntu:/opt#

root@ubuntu:/opt# dpkg --install nginx-full_1.12.1-0+xenial0_amd64.deb
(Reading database ... 57921 files and directories currently installed.)
Preparing to unpack nginx-full_1.12.1-0+xenial0_amd64.deb ...
Unpacking nginx-full (1.12.1-0+xenial0) over (1.12.1-0+xenial0) ...
Setting up nginx-full (1.12.1-0+xenial0) ...
Processing triggers for man-db (2.7.5-1) ...


Verify Installation


root@ubuntu:/opt# which nginx
/usr/sbin/nginx

root@ubuntu:/opt# ls /etc/init.d/nginx
/etc/init.d/nginx
root@ubuntu:/opt#

root@ubuntu:/opt# nginx -V
nginx version: nginx/1.12.1
built with OpenSSL 1.0.2g  1 Mar 2016
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-mail=dynamic --with-mail_ssl_module --add-dynamic-module=/opt/nginx-1.12.1/debian/modules/nginx-auth-pam --add-dynamic-module=/opt/nginx-1.12.1/debian/modules/nginx-dav-ext-module --add-dynamic-module=/opt/nginx-1.12.1/debian/modules/nginx-echo --add-dynamic-module=/opt/nginx-1.12.1/debian/modules/nginx-upstream-fair --add-dynamic-module=/opt/nginx-1.12.1/debian/modules/ngx_http_substitutions_filter_module
root@ubuntu:/opt#


Try accessing "http://ipaddress" in browser. You will see following:

Welcome to nginx!

If you see this page, the nginx web server is successfully installed and working. Further configuration is required.
For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.
Thank you for using nginx.


References:

http://www.geoffstratton.com/install-latest-nginx-source-ubuntu-1604
https://serversforhackers.com/c/compiling-third-party-modules-into-nginx


Monday, January 30, 2017

Controller Area Network - CAN


Found couple of interesting links on CAN.

What is CAN?

http://www.axiomatic.com/whatiscan.pdf

Automative CAN Bus System

https://www.linkedin.com/pulse/automotive-can-bus-system-explained-kiril-mucevski


Thursday, January 5, 2017

Keycloak - Update user's username

User in Keycloak has a username and email attribute. User's username (used for login) is different from user's email address. In lot of applications user's email address gets used as username. This brings up the usecase where user changes his/her email and the user's username in Keycloak must also be updated.

Keycloak by default doesn't allow admin to update user's username either via UI or API. To update username one need to first enable it at the realm level. Following are the steps:

1. Authenticate as admin

URL: POST https:///auth/realms//protocol/openid-connect/grants/access

2. Get realm

URL: GET https:///auth/admin/realms/

Response:
{
  "id": "bbb4b7eb-ea1e-4ca2-a925-896763cef01a",
  "realm": "",
  "notBefore": 0,
  "accessTokenLifespan": 300,
  "ssoSessionIdleTimeout": 1800,
  "ssoSessionMaxLifespan": 36000,
  "accessCodeLifespan": 60,
  "accessCodeLifespanUserAction": 300,
  "accessCodeLifespanLogin": 1800,
  "enabled": true,
  "sslRequired": "external",
  "registrationAllowed": false,
  "registrationEmailAsUsername": false,
  "rememberMe": false,
  "verifyEmail": false,
  "resetPasswordAllowed": true,
  "editUsernameAllowed": false,
  "userCacheEnabled": true,
  "realmCacheEnabled": true,
  "bruteForceProtected": false,
  "maxFailureWaitSeconds": 900,
  "minimumQuickLoginWaitSeconds": 60,
  "waitIncrementSeconds": 60,
  "quickLoginCheckMilliSeconds": 1000,
  "maxDeltaTimeSeconds": 43200,
  "failureFactor": 30,
  "publicKey": "",
  "certificate": "",
  "requiredCredentials": [
    "password"
  ],
  "otpPolicyType": "totp",
  "otpPolicyAlgorithm": "HmacSHA1",
  "otpPolicyInitialCounter": 0,
  "otpPolicyDigits": 6,
  "otpPolicyLookAheadWindow": 1,
  "otpPolicyPeriod": 30,
  "browserSecurityHeaders": {
    "contentSecurityPolicy": "frame-src 'self'",
    "xFrameOptions": "SAMEORIGIN"
  },
  "smtpServer": {},
  "eventsEnabled": false,
  "eventsListeners": [
    "jboss-logging"
  ],
  "enabledEventTypes": [],
  "adminEventsEnabled": false,
  "adminEventsDetailsEnabled": false,
  "identityFederationEnabled": false,
  "internationalizationEnabled": false,
  "supportedLocales": [],
  "browserFlow": "browser",
  "registrationFlow": "registration",
  "directGrantFlow": "direct grant",
  "resetCredentialsFlow": "reset credentials",
  "clientAuthenticationFlow": "clients"
}

3. Update realm to allow updating username

URL: PUT https:///auth/admin/realms/

Body:
{
 "editUsernameAllowed": true,
}

4. Get user

URL: GET https:///auth/admin/realms//users/a552d630-a696-43ea-9c56-9fe132e5a9a4

Response:
{
  "id": "a552d630-a696-43ea-9c56-9fe132e5a9a4",
  "createdTimestamp": 1483624857856,
  "username": "test",
  "enabled": true,
  "totp": false,
  "emailVerified": true,
  "requiredActions": []
}

5. Update user's username

URL: https:///auth/admin/realms//users/a552d630-a696-43ea-9c56-9fe132e5a9a4

Body:
{
"username": "test1",
"enabled": true,
"emailVerified": true
}

note: Keycloak 1.5.0 updates the enabled and emailVerified attributes to false upon update when not explicitly passed. I haven't checked if there are other such attributes.

6. Get user

URL: GET https:///auth/admin/realms//users/a552d630-a696-43ea-9c56-9fe132e5a9a4

Response:
{
  "id": "a552d630-a696-43ea-9c56-9fe132e5a9a4",
  "createdTimestamp": 1483624857856,
  "username": "test1",
  "enabled": true,
  "totp": false,
  "emailVerified": true,
  "requiredActions": []
}

7. Validate by performing login with username test1 and password.


Feel free to leave comment.


Monday, June 27, 2016

git flow with bamboo and docker

git flow is well known branching model for git repositories. The challenge however is how to make it work when it comes to integrating with build, release and deployment process. This post describes one simple recipe to implement E2E process. The gist of the recipe is to use software version of the package as the docker image tag.

Git flow branching model

git flow branching model is the original post that describes the branching model in detail. I found this link very useful that provides good summary of the git flow with commands for implementing the branching model.

If you are using atlassian suite of products then it is best to name branches after JIRA tickets for better integration and traceability.

Bamboo build process

For every repository create 3 plans as following:

CI and CD Plan

This plan builds from develop branch and create docker image with tag as "latest". The bamboo plan can deploy the image automatically to CD environment. In addition, QualDev (QA) team can request deployment in QualDev environment.

Release Plan

This plan builds from master and release*/hotfix* branches. The docker images are created with tag as (npm package version or maven version). The deployment of images from this build are typically on demand.

Feature Plan

This plan builds from feature* branches. This plan doesn't generate any docker image. This is primarily for running unit and integration tests.


Bamboo plan and Docker Image

Following is the sample job in the bamboo plan to create docker image and push to AWS ECR. This is based on a nodejs project. The project source include a build.json file with placeholders for build key and build number. The dockerfile replaces them with the value passed in the build-arg parameters to docker build command. build.json along with npm package version provide complete context of the build currently deployed in a given environment.

#!/bin/bash
# Configure aws
echo $bamboo_AWS_AKEY > 1.txt
echo $bamboo_AWS_SKEY >> 1.txt
echo "" >> 1.txt
echo "" >> 1.txt
aws configure < 1.txt
# Login to AWS ECR
LOGIN_STRING=`aws ecr get-login --region us-east-1`
${LOGIN_STRING}
PRODUCT=
COMPONENT=
PACKAGE_VERSION=$(cat package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g' | tr -d '[[:space:]]')
TAG=
BUILDKEY=${bamboo.buildKey} 
BUILDNUMBER=${bamboo.buildNumber}
                    REPOURL= 
# Build and Push docker image
docker build --build-arg BUILD_KEY=$BUILDKEY --build-arg BUILD_NUMBER=$BUILDNUMBER -t $PRODUCT/$COMPONENT:$TAG -f dockerbuild/Dockerfile --no-cache=true .
docker tag $PRODUCT/$COMPONENT:$TAG      $REPOURL/$PRODUCT/$COMPONENT:$TAG
docker push $REPOURL/$PRODUCT/$COMPONENT:$TAG

Following command in dockerfile updates the build.json
# Update build key and number
RUN sed -i -- "s/BUILDKEY/$BUILD_KEY/g; s/BUILDNUMBER/$BUILD_NUMBER/g" ./build.json

Further an API like following can make the information available to internal users about the details of the service running.
    const build = require('./build.json');

    {
      method: 'GET',
      path: '/about',
      config: {
        handler: function (request, reply) {
          var about = {
            "name": process.env.npm_package_name,
            "version": process.env.npm_package_version,
            "buildKey":  build.buildKey,
            "buildNumber": build.buildNumber,
            "config": conf.getProperties()
          }
          return reply(about);
        }
      }
    }


Friday, April 22, 2016

Polymer 1.0 Vulcanize Error

I recently started getting following error when running "gulp" on polymer starter kit:

Starting 'vulcanize'...
ERROR finding /starter-kit/app/elements/bower_components/bower_components/promise-polyfill/Promise.js
ERROR finding /starter-kit/app/elements/bower_components/whenever.js/whenever.js
ERROR finding /starter-kit/app/elements/bower_components/bower_components/bower_components/bower_components/bower_components/web-animations-js/web-animations-next-lite.min.js
ERROR finding starter-kit/app/elements/bower_components/paper-datatable/weakCache.js
ERROR finding starter-kit/app/elements/weakCache.js
:starter-kit$

I spent multiple hours looking on google but couldn't find a concrete answer. The same code and command works on my collegues machines.

I figured out that one difference between their and my machine was the npm repository. They were using external repo while I was using internal repo.

The Polymer/vulcanize team released 1.14.9 and it had a critical bug (https://github.com/Polymer/vulcanize/issues/332). As soon as they found that, they unpublished 1.14.9 version. However, before they could unpublish, our internal repo had cached it.

To resolve this I had to manually downgrade to 1.14.8 which I did by changing repo path to public npm repo.