{"id":1564,"date":"2018-07-17T01:00:00","date_gmt":"2018-07-17T01:00:00","guid":{"rendered":"http:\/\/inswwdev.azurewebsites.net\/au\/insights\/uncategorized\/making-awx-ssl-compliant\/"},"modified":"2024-12-13T02:23:43","modified_gmt":"2024-12-13T02:23:43","slug":"making-awx-ssl-compliant","status":"publish","type":"post","link":"https:\/\/www.insentragroup.com\/au\/insights\/geek-speak\/secure-workplace\/making-awx-ssl-compliant\/","title":{"rendered":"Making AWX SSL Compliant"},"content":{"rendered":"<p style=\"text-align: justify;\">Some time ago Red Hat acquired Ansible Inc \u2013 the company responsible for Ansible Tower.\u00a0 Being Red Hat \u2013 they promised to open the code of the Ansible Tower. The AWX project is the fulfillment of that promise.<\/p>\n<p style=\"text-align: justify;\">I created this blog for those who would like to use the marvels of the Ansible Tower without paying a penny and at the same time would like to have a modern and secure way to access the awx portal.<\/p>\n<p style=\"text-align: justify;\">I was recently doing some work for one of our customers who (as most customers) have the requirement to protect everything. Unfortunately, the AWX project does not come with the SSL protected GUI. After researching the topic for some time and going through several solutions that involved building proxies or redirecting encrypted traffic to the AWX, I decided to give it a crack and this is the outcome. It is not the most elegant way of hacking AWX, but it works and checks all the boxes.<\/p>\n<p style=\"text-align: justify;\"><strong>1. Follow the procedure to download awx from git (git clone https:\/\/github.com\/ansible\/awx.git)<\/strong><\/p>\n<p style=\"text-align: justify;\"><strong>2. Modify the inventory file as indicated below (only changes listed below):<\/strong><\/p>\n<p style=\"text-align: justify;\"><span><em>host_port=8080<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>awx_alternate_dns_servers=\u201d10.1.2.3,10.2.3.4,add_your_own\u201d<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><strong>3. Modify the standalone.yml playbook and replace the volumes configuration:<\/strong><\/p>\n<p style=\"text-align: justify;\"><span>vim +77 awx\/installer\/roles\/local_docker\/tasks\/standalone.yml<\/span><\/p>\n<p style=\"text-align: justify;\"><span>Modify volumes to:<\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>volumes:<\/em><\/span><br \/><span><em>\u2013 \u2018\/var\/lib\/awx\/projects:\/var\/lib\/awx\/projects:rw\u2019<\/em><\/span><br \/><span><em>\u2013 \u2018\/var\/lib\/awx-ssl:\/var\/lib\/awx-ssl:rw\u2019<\/em><\/span><\/p>\n<p style=\"text-align: justify;\">4. Create the directory for the volume on the host:<\/p>\n<p style=\"text-align: justify;\"><span><em>mkdir -p \/var\/lib\/awx-ssl<\/em><\/span><\/p>\n<p style=\"text-align: justify;\">5. Copy the certificates (key and crt) to \/var\/lib\/awx-ssl<\/p>\n<p style=\"text-align: justify;\">6. Copy the nginx.conf configuration file to \/var\/lib\/awx-ssl. The configuration file should look as follows:<\/p>\n<p style=\"text-align: justify;\"><span><em>#user awx;<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>worker_processes 1;<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>pid \/tmp\/nginx.pid;<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>events {<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0worker_connections 1024;<\/em><\/span><br \/><span><em>}<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>http {<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 include \/etc\/nginx\/mime.types;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0default_type application\/octet-stream;<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>\u00a0 \u00a0 \u00a0 \u00a0log_format main \u2018$remote_addr \u2013 $remote_user [$time_local] \u201c$request\u201d \u2018<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u2018$status $body_bytes_sent \u201c$http_referer\u201d \u2018<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u2018\u201d$http_user_agent\u201d \u201c$http_x_forwarded_for\u201d\u2018;<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>\u00a0 \u00a0 \u00a0 \u00a0map $http_upgrade $connection_upgrade {<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0default upgrade;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u201d close;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 }<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>\u00a0 \u00a0 \u00a0sendfile on;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0#tcp_nopush on;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0#gzip on;<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>\u00a0 \u00a0 \u00a0upstream uwsgi {<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0server 127.0.0.1:8050;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0}<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>\u00a0 \u00a0 \u00a0upstream daphne {<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 server 127.0.0.1:8051;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>\u00a0 \u00a0 \u00a0 server {<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0listen 8052 default_server;<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0# If you have a domain name, this is where to add it<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0server_name _;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0keepalive_timeout 65;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0ssl\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0on;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0ssl_certificate\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\/var\/lib\/awx-ssl\/nginx-selfsigned.crt;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0ssl_certificate_key\u00a0 \/var\/lib\/awx-ssl\/nginx-selfsigned.key;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0ssl_protocols\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 TLSv1.2;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0ssl_ciphers\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 HIGH:!aNULL:!MD5;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0add_header Strict-Transport-Security max-age=15768000;<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 location \/nginx_status {<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 stub_status on;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 access_log off;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 allow 127.0.0.1;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 deny all;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 }<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0location \/static\/ {<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0alias \/var\/lib\/awx\/public\/static\/;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0}<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 location \/favicon.ico { alias \/var\/lib\/awx\/public\/static\/favicon.ico; }<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 location ~ ^\/(websocket|network_ui\/topology\/) {<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # Pass request to the upstream alias<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 proxy_pass http:\/\/daphne;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # Require http version 1.1 to allow for upgrade requests<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # We want proxy_buffering off for proxying to websockets.<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 proxy_buffering off;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # http:\/\/en.wikipedia.org\/wiki\/X-Forwarded-For<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0# enable this if you use HTTPS:<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0proxy_set_header X-Forwarded-Proto https;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # pass the Host: header from the client for the sake of redirects<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 proxy_set_header Host $http_host;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0# We\u2019ve set the Host header, so we don\u2019t need Nginx to muddle<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0# about with redirects<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 proxy_redirect off;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0# Depending on the request value, set the Upgrade and<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0# connection headers<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 proxy_set_header Upgrade $http_upgrade;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 proxy_set_header Connection $connection_upgrade;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0}<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0location \/ {<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # Add trailing \/ if missing<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 rewrite ^(.*)$http_host(.*[^\/])$ $1$http_host$2\/ permanent;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 uwsgi_read_timeout 120s;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 uwsgi_pass uwsgi;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 include \/etc\/nginx\/uwsgi_params;<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }<\/em><\/span><br \/><span><em>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }<\/em><\/span><br \/><span><em>}<\/em><\/span><\/p>\n<p style=\"text-align: justify;\">7. Install the awx using ansible-playbook -i inventory install.yml<\/p>\n<p style=\"text-align: justify;\">8. Once the installation is finished verify if the docker containers are working as expected:<\/p>\n<p style=\"text-align: justify;\"><span><em>docker ps -a<\/em><\/span><\/p>\n<p style=\"text-align: justify;\">9. Verify if the volume (\/var\/lib\/awx-ssl) is mounted for awx_web container<\/p>\n<p style=\"text-align: justify;\"><span><em>docker inspect awx_web | grep awx-ssl<\/em><\/span><\/p>\n<p style=\"text-align: justify;\">10. If the volume is mounted, execute the following commands to modify the configuration and restart the container:<\/p>\n<p style=\"text-align: justify;\"><span><em>docker exec -it awx_web ln -fs \/var\/lib\/awx-ssl\/nginx.conf \/etc\/nginx\/nginx.conf<\/em><\/span><br \/><span><em>docker restart awx_web<\/em><\/span><br \/><span><em>docker ps -a<\/em><\/span><\/p>\n<p style=\"text-align: justify;\"><span class=\"SourceText\"><span>That\u2019s it. Watch out for my next blog\u2026. ?<\/span><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Some time ago Red Hat acquired Ansible Inc \u2013 the company responsible for Ansible Tower.\u00a0 Being Red Hat \u2013 they promised to open the code of the Ansible Tower. The AWX project is the fulfillment of that promise. I created this blog for those who would like to use the marvels of the Ansible Tower&hellip; <a class=\"more-link\" href=\"https:\/\/www.insentragroup.com\/au\/insights\/geek-speak\/secure-workplace\/making-awx-ssl-compliant\/\">Continue reading <span class=\"screen-reader-text\">Making AWX SSL Compliant<\/span><\/a><\/p>\n","protected":false},"author":67,"featured_media":1565,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"content-type":"","footnotes":""},"categories":[20],"tags":[],"class_list":["post-1564","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-secure-workplace","entry"],"_links":{"self":[{"href":"https:\/\/www.insentragroup.com\/au\/wp-json\/wp\/v2\/posts\/1564","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.insentragroup.com\/au\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.insentragroup.com\/au\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.insentragroup.com\/au\/wp-json\/wp\/v2\/users\/67"}],"replies":[{"embeddable":true,"href":"https:\/\/www.insentragroup.com\/au\/wp-json\/wp\/v2\/comments?post=1564"}],"version-history":[{"count":1,"href":"https:\/\/www.insentragroup.com\/au\/wp-json\/wp\/v2\/posts\/1564\/revisions"}],"predecessor-version":[{"id":23578,"href":"https:\/\/www.insentragroup.com\/au\/wp-json\/wp\/v2\/posts\/1564\/revisions\/23578"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.insentragroup.com\/au\/wp-json\/wp\/v2\/media\/1565"}],"wp:attachment":[{"href":"https:\/\/www.insentragroup.com\/au\/wp-json\/wp\/v2\/media?parent=1564"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.insentragroup.com\/au\/wp-json\/wp\/v2\/categories?post=1564"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.insentragroup.com\/au\/wp-json\/wp\/v2\/tags?post=1564"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}