Add a fas-client setup task. Add a common-scripts task. Setup arm-releng/arm-qa groups to use them.
This commit is contained in:
parent
9259cadfc5
commit
89e3c725e4
11 changed files with 366 additions and 0 deletions
41
files/common-scripts/lock-wrapper.sh
Executable file
41
files/common-scripts/lock-wrapper.sh
Executable file
|
@ -0,0 +1,41 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
echo "Usage: $0 [name] [script]"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
NAME=$1
|
||||
SCRIPT=$2
|
||||
|
||||
LOCKDIR="/var/tmp/$NAME"
|
||||
PIDFILE="$LOCKDIR/pid"
|
||||
|
||||
function cleanup {
|
||||
rm -rf "$LOCKDIR"
|
||||
}
|
||||
|
||||
RESTORE_UMASK=$(umask -p)
|
||||
umask 0077
|
||||
if ! mkdir "$LOCKDIR"; then
|
||||
echo "$LOCKDIR already exists"
|
||||
PID=$(cat "$PIDFILE")
|
||||
if [ -n "$PID" ] && /bin/ps $PID > /dev/null
|
||||
then
|
||||
echo "$PID is still running"
|
||||
/bin/ps -o user,pid,start,time,comm $PID
|
||||
exit 1;
|
||||
else
|
||||
echo "$LOCKDIR exists but $PID is dead"
|
||||
echo "Removing lockdir and re-running"
|
||||
/bin/rm -rf $LOCKDIR
|
||||
mkdir $LOCKDIR || exit
|
||||
fi
|
||||
fi
|
||||
|
||||
trap cleanup EXIT SIGQUIT SIGHUP SIGTERM
|
||||
echo $$ > "$PIDFILE"
|
||||
|
||||
$RESTORE_UMASK
|
||||
eval "$SCRIPT"
|
||||
|
108
files/common-scripts/nag-once
Executable file
108
files/common-scripts/nag-once
Executable file
|
@ -0,0 +1,108 @@
|
|||
#!/usr/bin/python -tt
|
||||
# nag once
|
||||
# take stdin and arguments: commandid time-to-ignore-same-output
|
||||
# if we encounter any kind of error just output whatever we're given
|
||||
# and prepend our own errors
|
||||
# so we don't hurt things any worse :)
|
||||
# copyright (c) 2011 Red Hat, inc
|
||||
# gpl v2 blah blah
|
||||
# skvidal - skvidal@fedoraproject.org
|
||||
|
||||
import tempfile
|
||||
import sys
|
||||
import time
|
||||
import os
|
||||
import stat
|
||||
import glob
|
||||
|
||||
|
||||
def translate_tti(tti):
|
||||
# translate 1w, 2d, 3d, 1m, 2h, 55m etc to seconds here
|
||||
|
||||
if tti is None:
|
||||
return None
|
||||
|
||||
seconds_per_unit = {"s": 1, "m": 60, "h": 3600, "d": 86400, "w": 604800,}
|
||||
if tti.isdigit():# just seconds
|
||||
return int(tti)
|
||||
return int(tti[:-1]) * seconds_per_unit[tti[-1]]
|
||||
|
||||
|
||||
|
||||
def get_cmdid_dir(cmdid):
|
||||
"""return a path to a valid and safe cachedir"""
|
||||
tmpdir="/var/tmp"
|
||||
prefix = "nag-once:" + cmdid + "#"
|
||||
dirpath = '%s/%s*' % (tmpdir, prefix)
|
||||
cachedirs = sorted(glob.glob(dirpath))
|
||||
for thisdir in cachedirs:
|
||||
stats = os.lstat(thisdir)
|
||||
if stat.S_ISDIR(stats[0]) and stat.S_IMODE(stats[0]) == 448 and stats[4] == os.getuid():
|
||||
return thisdir
|
||||
|
||||
# make the dir (tempfile.mkdtemp())
|
||||
cachedir = tempfile.mkdtemp(prefix=prefix, dir=tmpdir)
|
||||
return cachedir
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
raise Exception("Usage: nag-once cmdid [time-to-ignore]")
|
||||
|
||||
cmdid = sys.argv[1]
|
||||
# go through and remove stupid shit from cmdid
|
||||
cmdid = cmdid.replace('/', '')
|
||||
cmdid = cmdid.replace('#', '')
|
||||
cmdid = cmdid.replace('..', '')
|
||||
cmdid = cmdid.replace(';', '')
|
||||
cmdid = cmdid.replace('|', '')
|
||||
cmdid = cmdid.replace('&', '')
|
||||
cmdid = cmdid.replace('\\', '')
|
||||
|
||||
now = time.time()
|
||||
tti = None
|
||||
if len(sys.argv) > 2:
|
||||
tti = sys.argv[2]
|
||||
|
||||
tti = translate_tti(tti)
|
||||
|
||||
# make up or find our tempdir
|
||||
mydir = get_cmdid_dir(cmdid)
|
||||
|
||||
old_output = None
|
||||
old_date = 0
|
||||
if os.path.exists(mydir + '/output'):
|
||||
old_output = open(mydir + '/output').read()
|
||||
old_date = os.lstat(mydir + '/output')[stat.ST_MTIME]
|
||||
|
||||
# take from stdin
|
||||
#
|
||||
theinput = sys.stdin.read()
|
||||
try:
|
||||
# at this point we have to handle any outputs more ourself b/c we've just read
|
||||
# out of sys.stdin :(
|
||||
|
||||
if theinput != old_output or (tti and now - old_date > tti):
|
||||
if theinput.strip(): # if there is nothing here, don't output and don't drop a \n on the end of it
|
||||
print theinput,
|
||||
fo = open(mydir + '/output', 'w')
|
||||
fo.write(theinput)
|
||||
fo.flush()
|
||||
fo.close()
|
||||
|
||||
|
||||
except Exception, e:
|
||||
print >> sys.stderr, e
|
||||
print >> sys.stderr, theinput
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
except Exception, e:
|
||||
print >> sys.stderr, e
|
||||
if not sys.stdin.isatty():
|
||||
print >> sys.stderr, sys.stdin.read()
|
||||
|
||||
|
1
files/fas-client/fas-client.cron
Normal file
1
files/fas-client/fas-client.cron
Normal file
|
@ -0,0 +1 @@
|
|||
*/10 * * * * root /usr/local/bin/lock-wrapper fasClient "/bin/sleep $(($RANDOM \% 180)); /usr/bin/fasClient -i | /usr/local/bin/nag-once fassync 1d 2>&1"
|
102
files/fas-client/fas.conf.j2
Normal file
102
files/fas-client/fas.conf.j2
Normal file
|
@ -0,0 +1,102 @@
|
|||
[global]
|
||||
; url - Location to fas server
|
||||
url = https://admin.fedoraproject.org/accounts/
|
||||
|
||||
; temp - Location to generate files while user creation process is happening
|
||||
temp = /var/db
|
||||
|
||||
{% if ansible_domain == 'qa.fedoraproject.org' %}
|
||||
; Eventually, no box should use systems user to fasClient. systems has access
|
||||
; to password hashes. But password hashes are needed for sudo unless the box
|
||||
; uses pam_url
|
||||
; login - username to contact fas
|
||||
login = systems
|
||||
|
||||
; password - password for login name
|
||||
password = {{ systemsUserPassword }}
|
||||
{% else %}
|
||||
; login - username to contact fas
|
||||
login = {{ fedorathirdpartyUser }}
|
||||
|
||||
; password - password for login name
|
||||
password = {{ fedorathirdpartyPassword }}
|
||||
{% endif %}
|
||||
; prefix - install to a location other than /
|
||||
prefix = /
|
||||
|
||||
; modefile - Location of a file containing saved home directory modes
|
||||
modefile = /var/lib/fas/client_dir_perms
|
||||
|
||||
; cla_group - Group for CLA requirements
|
||||
cla_group = cla_done
|
||||
|
||||
[host]
|
||||
; Group hierarchy is 1) groups, 2) restricted_groups 3) ssh_restricted_groups
|
||||
; so if someone is in all 3, the client behaves the same as if they were just
|
||||
; in 'groups'
|
||||
|
||||
; groups that should have a shell account on this system.
|
||||
{% if fas_client_groups %}
|
||||
groups = {{ fas_client_groups }}
|
||||
{% else %}
|
||||
groups = "sysadmin-main"
|
||||
{% endif %}
|
||||
|
||||
; groups that should have a restricted account on this system.
|
||||
; restricted accounts use the restricted_shell value in [users]
|
||||
restricted_groups =
|
||||
|
||||
; ssh_restricted_groups: groups that should be restricted by ssh key. You will
|
||||
; need to disable password based logins in order for this value to have any
|
||||
; security meaning. Group types can be placed here as well, for example
|
||||
; @hg,@git,@svn
|
||||
{% if fas_client_ssh_groups %}
|
||||
ssh_restricted_groups = {{ fas_client_ssh_groups }}
|
||||
{% else %}
|
||||
ssh_restricted_groups =
|
||||
{% endif %}
|
||||
|
||||
; aliases_template: Gets prepended to the aliases file when it is generated by
|
||||
; fasClient
|
||||
aliases_template = /etc/aliases.template
|
||||
|
||||
[users]
|
||||
; default shell given to people in [host] groups
|
||||
shell = /bin/bash
|
||||
|
||||
; home - the location for fas user home dirs
|
||||
home = /home/fedora
|
||||
|
||||
; home_backup_dir - Location home dirs should get moved to when a user is
|
||||
; deleted this location should be tmpwatched
|
||||
home_backup_dir = /home/fedora.bak
|
||||
|
||||
; ssh_restricted_app - This is the path to the restricted shell script. It
|
||||
; will not work automatically for most people though through alterations it
|
||||
; is a powerfull way to restrict access to a machine. An alternative example
|
||||
; could be given to people who should only have cvs access on the machine.
|
||||
; setting this value to "/usr/bin/cvs server" would do this.
|
||||
{% if fas_client_restricted_app %}
|
||||
ssh_restricted_app = {{ fas_client_restricted_app }}
|
||||
{% else %}
|
||||
ssh_restricted_app =
|
||||
{% endif %}
|
||||
|
||||
; ssh_admin_app - This is the path to an app that an admin is allowed to use.
|
||||
{% if fas_client_admin_app %}
|
||||
ssh_admin_app = {{ fas_client_admin_app }}
|
||||
{% else %}
|
||||
ssh_admin_app =
|
||||
{% endif %}
|
||||
|
||||
; restricted_shell - The shell given to users in the ssh_restricted_groups
|
||||
restricted_shell = /sbin/nologin
|
||||
|
||||
; ssh_restricted_shell - The shell given to users in the ssh_restricted_groups
|
||||
ssh_restricted_shell = /bin/bash
|
||||
|
||||
; ssh_key_options - Options to be appended to people ssh keys. Users in the
|
||||
; ssh_restricted_groups will have the keys they uploaded altered when they are
|
||||
; installed on this machine, appended with the options below.
|
||||
ssh_key_options = no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
|
||||
|
1
inventory/group_vars/arm-qa
Normal file
1
inventory/group_vars/arm-qa
Normal file
|
@ -0,0 +1 @@
|
|||
fas_client_groups: "sysadmin-main,sysadmin-qa"
|
1
inventory/group_vars/arm-releng
Normal file
1
inventory/group_vars/arm-releng
Normal file
|
@ -0,0 +1 @@
|
|||
fas_client_groups: "sysadmin-main,sysadmin-releng"
|
|
@ -1,3 +1,11 @@
|
|||
[arm-releng]
|
||||
arm03-releng01.arm.fedoraproject.org
|
||||
arm03-releng02.arm.fedoraproject.org
|
||||
arm03-releng03.arm.fedoraproject.org
|
||||
arm03-releng04.arm.fedoraproject.org
|
||||
|
||||
[arm-qa]
|
||||
arm03-builder05.arm.fedoraproject.org
|
||||
|
||||
[buildvm]
|
||||
buildvm-01.phx2.fedoraproject.org
|
||||
|
|
17
playbooks/groups/arm-qa.yml
Normal file
17
playbooks/groups/arm-qa.yml
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
- name: Setup arm-qa hosts
|
||||
hosts: arm-qa
|
||||
user: root
|
||||
gather_facts: False
|
||||
tags:
|
||||
- arm-qa
|
||||
|
||||
vars_files:
|
||||
- /srv/web/infra/ansible/vars/global.yml
|
||||
- ${private}/vars.yml
|
||||
|
||||
tasks:
|
||||
# This group uses fas_client for user management
|
||||
- include: $tasks/fas_client.yml
|
||||
# This group includes our common scripts
|
||||
- include: $tasks/common_scripts.yml
|
17
playbooks/groups/arm-releng.yml
Normal file
17
playbooks/groups/arm-releng.yml
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
- name: Setup arm-releng hosts
|
||||
hosts: arm-releng
|
||||
user: root
|
||||
gather_facts: False
|
||||
tags:
|
||||
- arm-releng
|
||||
|
||||
vars_files:
|
||||
- /srv/web/infra/ansible/vars/global.yml
|
||||
- ${private}/vars.yml
|
||||
|
||||
tasks:
|
||||
# This group uses fas_client for user management
|
||||
- include: $tasks/fas_client.yml
|
||||
# This group includes our common scripts
|
||||
- include: $tasks/common_scripts.yml
|
11
tasks/common_scripts.yml
Normal file
11
tasks/common_scripts.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
#
|
||||
# This task installs some common scripts to /usr/local/bin
|
||||
# scripts are under $files/common-scripts
|
||||
#
|
||||
|
||||
- name: Install common scripts
|
||||
action: copy src=$item dest=/usr/local/bin/
|
||||
with_fileglob: $files/common-scripts/*
|
||||
tags:
|
||||
- config
|
59
tasks/fas_client.yml
Normal file
59
tasks/fas_client.yml
Normal file
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
#
|
||||
# This task sets up fasClient on a machine.
|
||||
# It installs the fas-clients package, then the /etc/fas.conf and finally a cron job update.
|
||||
#
|
||||
|
||||
#
|
||||
# fas-clients is in the infrastructure repo.
|
||||
# nss_db is needed to store user/group info.
|
||||
#
|
||||
- name: install package needed for fas-client
|
||||
action: yum state=installed name=$item
|
||||
with_items:
|
||||
- fas-clients
|
||||
tags:
|
||||
- packages
|
||||
|
||||
- name: install nss_db on rhel hosts only
|
||||
action: yum state=installed name=nss_db
|
||||
only_if: "'${ansible_distribution}' == 'RedHat'"
|
||||
tags:
|
||||
- packages
|
||||
|
||||
#
|
||||
# fasClients needs a valid /etc/fas.conf.
|
||||
# There's vars used in this template:
|
||||
#
|
||||
# fas_client_groups = "sysadmin-main"
|
||||
# fas_client_restricted_app = ""
|
||||
# fas_client_admin_app = ""
|
||||
# fas_client_ssh_groups = ""
|
||||
#
|
||||
# if desired, set them on a per host/group basis.
|
||||
#
|
||||
# Currently the default template is used, but could be modified on a host basis.
|
||||
#
|
||||
- name: setup /etc/fas.conf for client use
|
||||
action: template src=$item dest=/etc/fas.conf owner=root mode=600
|
||||
with_first_found:
|
||||
- $files/fas-client/${ansible_fqdn}.fas.conf.j2
|
||||
- $files/fas-client/${ansible_hostname}.fas.conf.j2
|
||||
- $files/fas-client/${ansible_hostname}.fas.conf.j2
|
||||
- $files/fas-client/fas.conf.j2
|
||||
tags:
|
||||
- config
|
||||
|
||||
#
|
||||
# setup /etc/cron.d/ file to run sync every 10min
|
||||
# TODO: use cron module when it's fixed
|
||||
#
|
||||
#- name: fas_client cron job
|
||||
# cron: name="fas client" user=root cron_file=fas-client minute="*/10" job="/usr/bin/fasClient -i"
|
||||
# tags:
|
||||
# - config
|
||||
#
|
||||
- name: fas_client cron job
|
||||
action: copy src=$files/fas-client/fas-client.cron dest=/etc/cron.d/fas-client owner=root mode=700
|
||||
tags:
|
||||
- config
|
Loading…
Add table
Add a link
Reference in a new issue