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]
|
||||||
buildvm-01.phx2.fedoraproject.org
|
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