{"id":1106,"date":"2014-09-23T20:32:31","date_gmt":"2014-09-24T01:32:31","guid":{"rendered":"http:\/\/www.nathanhunstad.com\/blog\/?p=1106"},"modified":"2014-09-23T20:45:57","modified_gmt":"2014-09-24T01:45:57","slug":"installing-google-authenticator-on-centos","status":"publish","type":"post","link":"https:\/\/www.nathanhunstad.com\/blog\/2014\/09\/installing-google-authenticator-on-centos\/","title":{"rendered":"Installing Google Authenticator on CentOS"},"content":{"rendered":"<p>After a conversation at work about how easy it is to use Google Authenticator for two-factor authentication, I decided that installing Google Authenticator on my CentOS server would be my next project. After all, I had <a href=\"http:\/\/www.nathanhunstad.com\/blog\/2014\/09\/log-file-automation\/\" target=\"_blank\">recently automated<\/a> download of website log files, and I needed to find the next to-do at home. Installing Google Authenticator took a morning and was not instantaneous, but it was simple enough as you will see below.<\/p>\n<p><!--more--><\/p>\n<p>If you want to install Google Authenticator on Linux, there are many how-tos online. Most of them start by telling people to install the package using <span style=\"font-family: 'Courier New';\">apt-get<\/span> or <span style=\"font-family: 'Courier New';\">yum <\/span>if your repositories are set up properly. Sure, you can do this if you want, but there are problems if you go down this path: the biggest one is that the default packaged version does not support all options, including the use of \u201cnullok\u201d in your PAM file. Instead, build it from source the old-fashioned way. <a href=\"http:\/\/blog.remibergsma.com\/tag\/google-authenticator\/\" target=\"_blank\">Here<\/a> is one guide to doing so: the key is in these lines:<\/p>\n<p>[codesyntax lang=&#8221;bash&#8221; lines=&#8221;no&#8221; container=&#8221;div&#8221; capitalize=&#8221;no&#8221; strict=&#8221;yes&#8221; blockstate=&#8221;expanded&#8221; doclinks=&#8221;0&#8243;]<\/p>\n<pre>wget https:\/\/google-authenticator.googlecode.com\/files\/libpam-google-authenticator-1.0-source.tar.bz2 \r\ntar jvxf libpam-google-authenticator-1.0-source.tar.bz2 \r\ncd libpam-google-authenticator-1.0\/ \r\nmake \r\nmake install<\/pre>\n<p>[\/codesyntax]<\/p>\n<p>Once you have it installed, you need to run <span style=\"font-family: 'Courier New';\">google-authenticator<\/span> as the user you want to set up two-factor for. Since I wanted to set it up for my root account, I ran it as root, answering yes to all of the questions. It will create a <span style=\"font-family: 'Courier New';\">~\/.google_authenticator<\/span> file, output your secret key and emergency scratch codes, prompting you to write them down. You can use the link to create a QR code that you scan with your authenticator app, and once done, you will have the code generator ready to use on your mobile device.<\/p>\n<p>Next you\u2019ll have to configure PAM to ask for the authenticator code. Open up <span style=\"font-family: 'Courier New';\">\/etc\/pam.d\/ssdh<\/span> and add the line below to the top of the file:<\/p>\n<p><span style=\"font-family: 'Courier New';\">auth required pam_google_authenticator.so nullok<\/span><\/p>\n<p>The \u201cnullok\u201d at the end of the line will allow users that do not have Google Authenticator set up for them to still log in with their password; as stated before, if you install the package this option won\u2019t work (trust me, Iearned the hard way). I also learned the hard way that the above line needs to be at the top of the <span style=\"font-family: 'Courier New';\">sshd<\/span> file and not the end, otherwise PAM doesn\u2019t get down that far. You\u2019ll also need to edit <span style=\"font-family: 'Courier New';\">\/etc\/vim\/ssh\/ssdh_config<\/span> to set <span style=\"font-family: 'Courier New';\">ChallengeResponseAuthentication<\/span> to <span style=\"font-family: 'Courier New';\">yes<\/span> if not already done so. Finall, restart the sshd service, but before you do, either log on locally or keep another session open, because\u2026.<\/p>\n<p>If you have SELinux enabled, this won\u2019t work!<\/p>\n<p>The common answer to dealing with this problem with Google Authenticator is to turn off SELinux, but that\u2019s the easy, insecure way out. It\u2019s actually not that hard to configure SELinux to make this work, and this is what I did.<\/p>\n<p>The root of the problem is that SELinux prevents <span style=\"font-family: 'Courier New';\">sshd<\/span> from writing to the <span style=\"font-family: 'Courier New';\">.google_authenticator<\/span> file in your user\u2019s home directory. You can see the actual error log in the <span style=\"font-family: 'Courier New';\">\/var\/log\/audit<\/span> directory. For me, I had a bunch of lines like this:<\/p>\n<p><span style=\"font-family: 'Courier New';\">[codesyntax lang=&#8221;bash&#8221; lines=&#8221;no&#8221;]<\/span><\/p>\n<pre>type=AVC msg=audit(1411221199.631:102852): avc:\u00a0 denied\u00a0 { create } for\u00a0 pid=6102 comm=\"sshd\" name=\".google_authenticator~\" scontext=unconfined_u:system_r:sshd_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file<\/pre>\n<p><span style=\"font-family: 'Courier New';\">[\/codesyntax]<\/span><\/p>\n<p>I am no SELinux expert at all. So I went to <a href=\"https:\/\/access.redhat.com\/documentation\/en-US\/Red_Hat_Enterprise_Linux\/6\/html\/Security-Enhanced_Linux\/sect-Security-Enhanced_Linux-Fixing_Problems-Raw_Audit_Messages.html\" target=\"_blank\">this site<\/a> to learn a bit more about what the audit log was saying. It wasn\u2019t too hard to interpret: <span style=\"font-family: 'Courier New';\">sshd<\/span> was denied from creating the <span style=\"font-family: 'Courier New';\">.google_authenticator~<\/span> file (which then overwrites the <span style=\"font-family: 'Courier New';\">.google_authenticator<\/span> file). The reason is a bit trickier and you have <a href=\"https:\/\/fedoraproject.org\/wiki\/Security_context?rd=SELinux\/SecurityContext\" target=\"_blank\">to know a bit<\/a> about SELinux security contexts to understand, but the gist of it is that the <span style=\"font-family: 'Courier New';\">sshd_t<\/span> type is not allowed to access the <span style=\"font-family: 'Courier New';\">admin_home_t<\/span> type. Well, that\u2019s intuitive, isn\u2019t it?<\/p>\n<p>SELinux has the concept of policies that govern access controls for different types, and so the solution is to create a new policy to allow this interaction; I\u2019ll leave aside the real concerns about letting <span style=\"font-family: 'Courier New';\">sshd<\/span> access security-related things in your home directory, but feel free to <a href=\"https:\/\/bugzilla.redhat.com\/show_bug.cgi?format=multiple&amp;id=754978\" target=\"_blank\">read the lively debate<\/a> on the bug submission. Creating a new policy is not that hard, and <a href=\"http:\/\/blog.boa.nu\/2012\/11\/two-factor-ssh-login-google-authenticator-and-selinux.html\" target=\"_blank\">this<\/a> is the site I used to help me do it. You need to create two files, one ending in .te and one ending in .fc. This is my <span style=\"font-family: 'Courier New';\">google_authenticator.te<\/span> file, edited from the above link:<\/p>\n<p>[codesyntax lang=&#8221;text&#8221;]<\/p>\n<pre># Name and version, every module should have this. \r\npolicy_module(sshd_google_authenticator, 0.0.2)\r\n\r\n# List of the types, class and everything else you are going to use in your module that is not defined in this .te file. \r\n# If you are getting any errors when you compile your module that it is unable to find a type, you probably forgot to declare it here. \r\nrequire { \r\n\u00a0 type sshd_t; \r\n\u00a0 type user_home_dir_t; \r\n\u00a0 type admin_home_t; \r\n}\r\n\r\n# This is where we define our type. A good practise is to append _t for all types. \r\n# This is the type we are going to give our .google_authenticator file. \r\ntype sshd_google_authenticator_t;\r\n\r\n# What role our type should have. This is almost always going to be object_r \r\nrole object_r types sshd_google_authenticator_t;\r\n\r\n# What sshd_t (the context the ssh daemon runs as) should be able to do with our type (sshd_google_authenticator_t), \r\n# as a file. rename, create and unlink are base definitions, rw_file_perms is a set of rules. \r\n# The rw_file_perms group is defined in \/usr\/share\/selinux\/devel\/include\/support\/obj_perm_sets.spt with a lot of other \r\n# groups. Reading this files give you a good overview of what they allow. \r\nallow sshd_t sshd_google_authenticator_t:file { rename create unlink rw_file_perms };\r\n\r\n# Without this, SELinux will be way too strict as default, as it won't know what this type really is. \r\n# Remember that SELinux doesn\u2019t only deal with files, but sockets and other filetypes as well. \r\n# Leaving this out will still allow sshd_t to do its stuff, but you, in your shell will see a weird file. \r\n# The only thing you will see is the file name. Even permissions will be hidden from you. (a fun trick to pull on your friends.. :] ) \r\n# An overview of this is located at http:\/\/oss.tresys.com\/docs\/refpolicy\/api\/kernel_files.html. \r\nfiles_type(sshd_google_authenticator_t) \r\nfiletrans_pattern(sshd_t, user_home_dir_t, sshd_google_authenticator_t, file, \".google_authenticator\") \r\nfiletrans_pattern(sshd_t, admin_home_t, sshd_google_authenticator_t, file, \".google_authenticator\")<\/pre>\n<p>[\/codesyntax]<\/p>\n<p>You\u2019ll notice that I\u2019ve added a few things to the default. First, I\u2019ve added required types of <span style=\"font-family: 'Courier New';\">user_home_dir_t<\/span> and <span style=\"font-family: 'Courier New';\">admin_home_t<\/span> because I reference them at the bottom; without this you get an error. Second, I\u2019ve used the trick at the bottom of that blog post to set the context of any newly-created <span style=\"font-family: 'Courier New';\">.google_authenticator<\/span> file to the right type (the <span style=\"font-family: 'Courier New';\">sshd_google_authenticator_t<\/span> type) in both a normal user\u2019s home directory as well as the root home directory.<\/p>\n<p>The <span style=\"font-family: 'Courier New';\">google_authenticator.fc<\/span> file is, as you would expect, one line long:<\/p>\n<p><span style=\"font-family: 'Courier New';\">[codesyntax lang=&#8221;text&#8221;]<\/span><\/p>\n<pre>\/root\/.google_authenticator\u00a0\u00a0\u00a0\u00a0 --\u00a0 gen_context(system_u:object_r:sshd_google_authenticator_t,s0)<\/pre>\n<p><span style=\"font-family: 'Courier New';\">[\/codesyntax]<\/span><\/p>\n<p>I did it this way instead of using HOME_DIR\/ because for the root home directory, that variable was not expanding correctly so I had to use the actual path.<\/p>\n<p>I compiled the module as stated and used <span style=\"font-family: 'Courier New';\">semodule \u2013i<\/span> to load it, and lo and behold it worked! Not only that, but because I used the <span style=\"font-family: 'Courier New';\">nullok<\/span> option, when I log in as a normal user I don\u2019t get prompted for Google Authenticator, as expected.<\/p>\n<p>And that\u2019s it! I now have two-factor authentication enabled for my root account when I <span style=\"font-family: 'Courier New';\">ssh<\/span> in. Pretty neat. What\u2019s next? Well, I still want to get chef up and running\u2026<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After a conversation at work about how easy it is to use Google Authenticator for two-factor authentication, I decided that installing Google Authenticator on my CentOS server would be my next project. After all, I had recently automated download of website log files, and I needed to find the next to-do at home. Installing Google&hellip; <a class=\"more-link\" href=\"https:\/\/www.nathanhunstad.com\/blog\/2014\/09\/installing-google-authenticator-on-centos\/\">Continue reading <span class=\"screen-reader-text\">Installing Google Authenticator on CentOS<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[19],"tags":[152,247,262,261,263],"class_list":["post-1106","post","type-post","status-publish","format-standard","hentry","category-tech-2","tag-authentication","tag-centos","tag-google-authenticator","tag-selinux","tag-two-factor","entry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/posts\/1106","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/comments?post=1106"}],"version-history":[{"count":9,"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/posts\/1106\/revisions"}],"predecessor-version":[{"id":1116,"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/posts\/1106\/revisions\/1116"}],"wp:attachment":[{"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/media?parent=1106"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/categories?post=1106"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.nathanhunstad.com\/blog\/wp-json\/wp\/v2\/tags?post=1106"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}