Skip to content

Instantly share code, notes, and snippets.

@ev0rtex
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ev0rtex/a9a71c164140ef69449d to your computer and use it in GitHub Desktop.
Save ev0rtex/a9a71c164140ef69449d to your computer and use it in GitHub Desktop.
Fabric access control
from fabric.api import env, run, sudo, prompt, hide, warn_only, quiet
from fabric.contrib import files
from getpass import getpass
import os
import re
def login(user=None, passwd=None):
uname = user if user is not None else prompt("Remote username: ", default=env.user)
pword = passwd if passwd is not None else getpass("Remote password: ")
if uname:
env.user = uname
if pword:
env.password = pword
def hosts(hostfile=None, hostlist=None, bad=False):
if bad:
env.skip_bad_hosts = True
if not hostfile and not hostlist:
print("You need to provide either a list of hosts or a host file")
return False
if hostlist:
for host in hostlist.split(':'):
env.hosts.append(host)
print("Hosts list given")
if hostfile and os.path.isfile(hostfile):
with open(hostfile, 'r') as hf:
hlist = filter(None, hf.read().splitlines())
for host in hlist:
env.hosts.append(host)
print("Loaded hosts from '{}'".format(os.path.realpath(hostfile)))
for host in env.hosts:
print(" {}".format(host))
def test():
print("CWD: {}".format(run("pwd")))
def adduser(username, password=None, sudoer=False, key=None):
# If a keyfile is given, set the key
# Grant sudo privileges by either adding to the 'sudo' group or adding to /etc/sudoers
# Get existing user credentials
if not "userpasswd" in env:
env["userpasswd"] = getpass("Password for '{}': ".format(username))
# Check to see if user already exists
with warn_only():
uid = sudo("id {}".format(username))
# If user doesn't exist lets go for it
if uid.return_code == 1:
sudo("adduser {0} --disabled-password --gecos \"\"".format(username))
setpasswd(username, env.userpasswd)
else:
print("User '{}' already exists...skipping user creation".format(username))
# Additional tasks
if key:
addkey(username, key)
if sudoer:
addsudo(username, True)
def setpasswd(username, password=None):
if not env.userpasswd:
env.userpasswd = password if password is not None else getpass("Password for '{}': ".format(username))
with warn_only():
if sudo("id {}".format(username)).return_code == 0:
with quiet():
sudo("echo \"{user}:{passwd}\" | chpasswd".format(user=username, passwd=password))
else:
print("The user was not found on the system...skipping password change")
return False
return True
def addkey(username, key):
# Validate and get a proper key string
if os.path.isfile(os.path.expanduser(key)):
with open(os.path.expanduser(key), 'r') as kf:
key = kf.read()
b64 = re.search("ssh-[a-z]+ (?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})", key)
if b64 == None:
print("Invalid key string or invalid keyfile path, please double-check that you gave either a valid public key string or a valid public key file to read the key from")
return False
# Set up the authorized keys file and key entry
if not files.exists("/home/{user}/.ssh".format(user=username), True):
sudo("mkdir -pm 700 /home/{user}/.ssh".format(user=username))
files.append("/home/{user}/.ssh/authorized_keys".format(user=username), key, True)
sudo("chown -R {user}: /home/{user}/.ssh".format(user=username))
sudo("chmod 644 /home/{user}/.ssh/authorized_keys".format(user=username))
return True
def addsudo(username, use_sudoers=False):
# Explicit sudoers file grant
if use_sudoers:
# Check for existing entry
if files.contains("/etc/sudoers", "{user}\tALL=".format(user=username), use_sudo=True):
return True
# Let's do this (as safely as possible with validation)
matches = sudo("egrep -in \"^[a-z]+\s+ALL=\(ALL[^)]*\)\s+ALL\" /etc/sudoers | cut -d ':' -f 1")
last = int(matches.splitlines()[-1]) if matches else False
if last:
sudo("awk 'NR=={line}{{print \"{user}\\tALL=(ALL) ALL\"}}1' /etc/sudoers > /tmp/sudoers.tmp".format(
user = username,
line = last + 1
))
sudo("visudo -cf /tmp/sudoers.tmp")
sudo("cp /etc/sudoers /etc/sudoers.bak")
sudo("cat /tmp/sudoers.tmp > /etc/sudoers")
if files.contains("/etc/sudoers", "{user}\tALL=".format(user=username), use_sudo=True):
sudo("rm /etc/sudoers.bak")
else:
sudo("mv /etc/sudoers.bak /etc/sudoers")
print("Something went wrong while editing /etc/sudoers ...backing out")
sudo("rm -f /tmp/sudoers.tmp")
return True
else:
print("Could not locate existing users in /etc/sudoers please check the file first")
return False
# Group method
else:
sudo("usermod -a -G sudo {user}".format(user=username))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment