At my company we currently have a SSH jump server of sorts, through which our workers access our clients' server endpoints. We have setup a couple of Ansible playbooks that essentially create/remove/update users access to that Jump server, by creating user accounts and setting public-key based access to it.

I'm now trying to implement MFA using google-authenticator in that server. I've been through this tutorial that effectively covers the procedure of adding MFA keyboard-interactive protection to SSH access for a given user, but I was wondering how I could automate that procedure as to integrate it with our current workflow.

The points I'm struggling with are the following:

  • at some point in the tutorial's procedures, there's a 2D QR code output in the bash along with a bunch of safeguard access codes in case MFA borks up or fails. I understand it uses libqrencode for this purpose. I was wondering if there would be any way I could use Ansible to maybe place this output in an email and send it to the users being set-up.
  • also, for the above effect, I would require each user's email address. Currently, the users are managed only via their username/handle (ie, jdoe). Is there anyway I could add and maintain their email address info to the user account in Linux?

I know this question covers a lot of info, but rather than a canonical answer (that probably isn't even possible) I'm looking for solid pointers on where too look for information and hopefully that someone can also highlight any pitfalls with my idea/approach as this is all very new to me and I'm a bit lost.

EDIT: After investigating these topics for a while, I decided I should use a slightly different method/approach to this automation.

I'll still use the Google Authenticator PAM, but I decided to make the setup process easier by not notifying the users via email when their accounts are setup with MFA, but rather allow them access via RSA key on their first SSH access, but immediately force them to setup their own MFA as per the tutorial above. This is achieved by running a command on SSH access. All following accesses would then require MFA, and I can configure the SSH host to verify if a MFA config file is present in the user's home folder. If it's present, the user has configured MFA and may proceed if MFA checks out valid; else, the user's MFA access hasn't been configured and the user will be prompted to set it up when accessing via SSH.

I feel it's robust enough as I'm covering the MFA not being configured (ie, google_authenticator file missing in the user's home dir), or it being tampered with (the MFA validation will fail). If anyone knows any pitfalls on my approach it would be very helpful!


You can do whatever you like in Ansible, it just may take some shell scripts where there is not a module that does what you want.

Copying over a pre-existing ~/.google_authenticator file is easy.

If the user generates the first secret on the system in question, they have to authenticate first. The README.md explains how to allow auth if no secret exists for the user:

During the initial roll-out process, you might find that not all users have created a secret key yet. If you would still like them to be able to log in, you can pass the "nullok" option on the module's command line:

auth required pam_google_authenticator.so nullok

The qrcodes are not mysterious, they are otpauth URIs. With a known secret you can generate these yourself. (The neat ASCII color trick that google-authenticator uses will not translate well to email.)

For a user to email mapping, implment a directory server. Eventually you can't just tack one domain name to a user name, although that might work in simple environments. I suppose you could also set up aliases on the host such that user@jumpbox.example.net went to the correct person.

  • 1
    Can you share some thoughts on how the nullok bit might go back and forth with several users when some already have configured MFA for their account, but others haven't? Won't the setting impact everyone? – Joum Dec 5 '16 at 9:38
  • 1
    Also, I was wondering if the 5th GECOS field wouldn't be enough to store our users unique email address. We won't have that many users (even in the long run), and it would be (I think) quite easy to integrate with our current procedure. Do you have any argument on why not to do it? – Joum Dec 5 '16 at 9:40

You can use any BASE32 secret key for the seed. [2-7A-Z]

Use Google Charts to generate the QR


and you can put that file anywhere you want and owned by a different user.

auth required pam_google_authenticator.so user=root secret=/var/lib/google-authenticator/${USER}

if the domain is the same you can easily just append the domain name to the file, it does not matter.

auth required pam_google_authenticator.so user=root secret=/var/lib/google-authenticator/${USER}@domain.tld

As for the file name, you can use any env var, I'm not aware of one for email, since our users are via AD we use the userprincipalname, which is user@kerberosdomain.tld

Now the better answer would be to setup FreeIPA, which supports AD Trusts, User Management, Radius auth backend AND Google Auth 2FA...among the many other benefits.

  • I'm not sure I personally like passing my secrets to a different site, even the Google Charts API where it might get lost in the volume. Although it is convenient. – John Mahowald Dec 3 '16 at 12:47
  • it's a standard format, there's a plethora of generators on github, but if you're that paranoid be sure to audit the pam module code and the generator you select – Jacob Evans Dec 3 '16 at 15:40
  • Thank you both for your input! On this point in particular, I tend to agree with @JohnMahowald regarding having info going about with 3rd party services. But great tip on FreeIPA, I hadn't heard about it before. – Joum Dec 5 '16 at 9:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.