Salt Sesame - emergency sudoers access

Sysinfo: salt 2018.3.2 (Oxygen), Centos 7

Problem

sometimes non-sysadmin users need root level access to managed hosts. Need a good way to give users access temporary sudo access to a host, while also auditing who received access to the box

The following setup uses a custom Salt module, to inject a temporary password into a service user account and returns the password back to the user.

Users who can grant themselves this permission are controlled via Salt Master ACL, once they receive the password, they can login to target host as 'salt' user and then do 'sudo su'

Sequence

    1. user Joe is one of authorized users who can request sudo access to host named "Atlas"

    2. Joe SSHs into Salt Master (as his own account), and runs the command to grant himself temporary sudo access to "atlas"

    3. joe@saltmaster> salt atlas sesame.open

    4. Salt will generate a new password for the service account user called "salt" (this user has to be present on Atlas)

    5. atlas:

    6. your temporary password has been generated.

    7. SSH as 'salt@atlas'

    8. Password: uI_UcGAJQTPbglVMNNiNNxhdzV4I

    9. This password will expire in 1 day

    10. To secure SSH access now, run 'salt atlas sesame.close

    11. Joe then SSHs into Atlas using the generated password

    12. joe@joeMac> ssh salt@atlas

    13. salt@atlas password: <types in generated password>

    14. salt@atlas> sudo su

    15. root@atlas>

    16. Once Joe is done with work on Atlas, he logs out. He then secures access to it by running (this command removes the password from 'salt' user)

    17. joe@saltmaster> salt atlas sesame.close

    18. or the password will expire automatically in 1 day.

    19. Joe's request is audited and recorded using 'lascomm', showing all users who ran 'salt' command recently

    20. root@saltmaster> lastcomm salt

    21. salt S root pts/0 0.27 secs Fri Aug 24 17:49

    22. salt joe pts/2 0.19 secs Fri Aug 24 17:46

Prerequisites

make sure all your managed hosts have a 'salt' service account created, you can use the following state,

Add this to your user pillar,

/srv/salt/pillar/users/salt.sls

{% set user = 'salt' %}

{% set fullname = 'Salt Service Account' %}

{% set uid = '2001' %}

users:

{{ user }}:

status: present # present / absent

uid: {{ uid }}

groups:

- sysadmin

fullname: {{ fullname }}

home: /home/{{ user }}

shell: /bin/bash

createhome: True

now the State to create the user

/srv/salt/state/formula/users/init.sls

## Add Salt user to box

{% set args = salt['pillar.get']('users:salt') %}

salt:

group.present:

- gid: {{ args.uid }}

user.present:

- fullname: {{ args.fullname }}

- uid: {{ args.uid }}

- gid: {{ args.uid }}

- allow_uid_change: True

- allow_gid_change: True

- createhome: True

{% if 'shell' in args %}

- shell: {{ args.shell }}

{% endif %}

{% if 'home' in args %}

- home: {{ args.home }}

{% endif %}

{% if 'groups' in args %}

- groups: {{ args.groups }}

{% endif %}

add_custom_sudoers:

file.managed:

- name: /etc/sudoers.d/custom_sudo

- source: salt://formula/group/files/custom_sudo

- user: root

- group: root

- mode: 440

this will create a new 'salt' user on any managed host, add 'salt' to group called 'sysadmin' and add this group to Sudoers using a custom_sudo file,

/srv/salt/state/formula/group/files/custom_sudo

## Custom sudoers

## File Managed by Saltstack

%sysadmin ALL=(ALL) NOPASSWD:ALL

Run this on all your managed hosts

Also make sure your hosts /etc/ssh/sshd_config allows Password Authentication

Custom Execution Module - Sesame

to make Sesame module work, add this to your State directory (my file_roots is set to /srv/salt/state), my custom module path is /srv/salt/state/_modules

add a new file called sesame.py

cat /srv/salt/state/_modules/sesame.py

import salt

# Custom Execution Module

# gives temporary sudoers access to 'salt' service account

def open():

''' opens up Salt user account '''

pw = __salt__['random.get_str']('28')

hashed_pw = __salt__['shadow.gen_password'](pw)

target = __salt__['grains.get']('id')

__salt__['shadow.set_password']('salt', hashed_pw)

__salt__['cmd.run']('chage -M 1 salt')

return "your temporary password has been generated.\n\nSSH as 'salt@{0}'\nPassword: ".format(target) + pw + "\

\n\nThis password will expire in 1 day\n\nTo secure SSH access now, run 'salt {0} sesame.close".format(target)

def close():

__salt__['shadow.del_password']('salt')

return "'salt' user password has been removed. Target SSH access is secure."

this py module generates a random password, hashes it, injects it into the "salt" user account on the target box (with lifetime of 1 day)

Sync the new module across all managed nodes,

salt \* saltutil.sync_all

Salt Master Config

    1. To enable ACL-controlled users to grant sudo access, you need to add them to the "publisher_acl"

    2. edit /etc/salt/master

    3. add the user that you want to access your custom module

      1. publisher_acl:

      2. joe:

      3. - sesame.open

      4. - sesame.close

    4. This allows Joe to execute the following commands: sesame.open, sesame.close

    5. restart salt master service

    6. change /var/log/salt/master + /var/log/salt/minion log permissions to allow r/w by other users

    7. chgrp -R usergroup /var/log/salt

    8. chmod -R g+rw /var/log/salt

Grant Access to a minion

as Joe, run

salt minion1 sesame.open

minion1:

your temporary password has been generated.

SSH as 'salt@saltdev1'

Password: tVkBn5Il20vVo7Ti_N17UwYUSgd1

This password will expire in 1 day

To secure SSH access now, run 'salt minion1 sesame.close

Audit users

check for users who ran 'salt' command

lastcomm salt

root@saltmaster /srv# lastcomm salt

salt S root pts/0 0.27 secs Fri Aug 24 17:49

salt joe pts/2 0.19 secs Fri Aug 24 17:46