├── roles ├── vpn │ └── tasks │ │ └── main.yml ├── common_fb_host │ ├── tasks │ │ ├── ntpd.yml │ │ ├── pf.yml │ │ └── main.yml │ ├── templates │ │ ├── pkg.conf.j2 │ │ ├── pf.conf.j2 │ │ ├── motd.j2 │ │ └── sshd_config.j2 │ ├── handlers │ │ └── main.yml │ └── files │ │ └── sudoers └── jails │ ├── templates │ ├── pkg.conf.j2 │ ├── network.j2 │ ├── rc.conf.j2 │ └── ezjail.conf.j2 │ ├── handlers │ └── ezjail.yml │ └── tasks │ ├── ezjail.yml │ ├── main.yml │ └── create_jails.yml ├── site.yml ├── jails_host.yml ├── apply.sh ├── group_vars ├── jails_host.example └── all.example ├── info.sh ├── .gitignore ├── host_vars └── jailhost.domain.example ├── ansible_hosts.example ├── Makefile ├── README.md ├── LICENSE └── library └── pkgng_chroot /roles/vpn/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- -------------------------------------------------------------------------------- /roles/common_fb_host/tasks/ntpd.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: jails_host.yml 3 | -------------------------------------------------------------------------------- /roles/jails/templates/pkg.conf.j2: -------------------------------------------------------------------------------- 1 | # Generated with Ansible 2 | PACKAGESITE: {{ pkgng_repository }} 3 | -------------------------------------------------------------------------------- /jails_host.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: jails_host 3 | roles: 4 | - common_fb_host 5 | - jails 6 | -------------------------------------------------------------------------------- /apply.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export ANSIBLE_KEEP_REMOTE_FILES=1 3 | ansible-playbook -i ansible_hosts site.yml -vv 4 | -------------------------------------------------------------------------------- /roles/common_fb_host/templates/pkg.conf.j2: -------------------------------------------------------------------------------- 1 | # Generated with Ansible 2 | PACKAGESITE: {{ pkgng_repository }} 3 | -------------------------------------------------------------------------------- /roles/jails/handlers/ezjail.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart ezjail 3 | service: name=ezjail state=restarted 4 | -------------------------------------------------------------------------------- /group_vars/jails_host.example: -------------------------------------------------------------------------------- 1 | --- 2 | jails_dir: /jails 3 | jails_zfs_root: tank/jails 4 | jails_netmask_lo1: 255.255.255.0 -------------------------------------------------------------------------------- /info.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export ANSIBLE_HOSTS=~/project/ansible-work/ansible_hosts 3 | ansible all -m ping -vv 4 | ansible all -m setup 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /lib/ 3 | /src/ 4 | /include/ 5 | /library/ezjail 6 | ansible_hosts 7 | group_vars 8 | !group_vars/*example 9 | host_vars/* 10 | !host_vars/*.example 11 | *~ 12 | .* 13 | !.gitignore 14 | -------------------------------------------------------------------------------- /roles/common_fb_host/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart sshd 3 | service: name=sshd state=restarted 4 | 5 | - name: restart network 6 | service: name=netif state=restarted 7 | 8 | - name: reload pf 9 | service: name=pf state=reloaded -------------------------------------------------------------------------------- /group_vars/all.example: -------------------------------------------------------------------------------- 1 | --- 2 | # SSH 3 | ansible_ssh_user: root 4 | ansible_ssh_private_key_file: ~/.ssh/id_dsa 5 | ssh_public_key_file: ~/.ssh/id_dsa.pub 6 | 7 | # FreeBSD 8 | ansible_python_interpreter: /usr/local/bin/python 9 | zfs_checksum: fletcher4 10 | 11 | # PF 12 | ipv4_whitelist: 13 | - ansiblehost.domain 14 | default_tcp_ports_authorized: 15 | - ssh 16 | -------------------------------------------------------------------------------- /host_vars/jailhost.domain.example: -------------------------------------------------------------------------------- 1 | --- 2 | jails_broadcast_lo1: 172.16.0.255 3 | jails_natted: 172.16.0.0/24 4 | jails_hosted: 5 | - poudriere.jailhost.domain 6 | - nginx.jailhost.domain 7 | default_tcp_ports_authorized: 8 | - ssh 9 | - http 10 | - https 11 | jails_in_nat_rules: 12 | - { in=80, host=nginx.jailhost.domain, out=80 } 13 | - { in=443, host=nginx.jailhost.domain, out=443 } 14 | -------------------------------------------------------------------------------- /roles/jails/templates/network.j2: -------------------------------------------------------------------------------- 1 | # Generated with Ansible 2 | cloned_interfaces="lo1" 3 | {% for jail in jails_hosted %} 4 | {% if loop.first %} 5 | ifconfig_lo1="{{ hostvars[jail]['ip'] }} netmask {{ jails_netmask_lo1 }} broadcast {{ jails_broadcast_lo1 }}" 6 | {% else %} 7 | ifconfig_lo1_alias{{ loop.index0 -1 }}="{{ hostvars[jail]['ip'] }} netmask {{ jails_netmask_lo1 }}" 8 | {% endif %} 9 | {% endfor %} 10 | -------------------------------------------------------------------------------- /ansible_hosts.example: -------------------------------------------------------------------------------- 1 | [jails_host] 2 | jailhost.domain 3 | 4 | [jail_poudriere] 5 | poudriere.jailhost.domain ip=172.16.0.1 ansible_ssh_host=jailhost.domain ansible_ssh_port=2000 name=poudriere 6 | 7 | [jail_nginx] 8 | nginx.jailhost.domain ip=172.16.0.2 ansible_ssh_host=jailhost.domain ansible_ssh_port=2001 name=nginx 9 | 10 | [jails:children] 11 | jail_poudriere 12 | jail_nginx 13 | 14 | [all:vars] 15 | pkgng_repository=https://pkg.cdn.pcbsd.org/9.1-RELEASE/amd64 16 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # ansible: src/ansible/hacking/env-setup 2 | # source src/ansible/hacking/env-setup 3 | 4 | bin/ansible: src/ansible/setup.py bin/pip 5 | bin/pip install -e src/ansible 6 | 7 | library/ezjail: src/ezjailansible/ezjail.py 8 | ln -s src/ezjailansible/ezjail.py library/ezjail 9 | 10 | src/ansible/setup.py: bin/buildout 11 | bin/buildout 12 | 13 | bin/buildout: bin/pip 14 | bin/pip install zc.buildout 15 | 16 | bin/python bin/pip: 17 | virtualenv . 18 | 19 | clean: 20 | git clean -fXd 21 | 22 | .PHONY: clean 23 | -------------------------------------------------------------------------------- /roles/jails/tasks/ezjail.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install ezjail 3 | pkgng: name=ezjail state=present 4 | 5 | - name: Base configuration of ezjail 6 | template: src=ezjail.conf.j2 dest=/usr/local/etc/ezjail.conf 7 | 8 | - name: Test if basejail folder exist 9 | shell: /bin/test -d {{ jails_dir }}/basejail/ 10 | register: basejail 11 | ignore_errors: True 12 | changed_when: "basejail.rc != 0" 13 | 14 | - name: Be sure ezjail basejail is installed 15 | command: /usr/local/bin/ezjail-admin install 16 | when: "basejail.rc != 0" 17 | 18 | - name: Be sure ezjail enabled on startup 19 | service: name=ezjail enabled=yes 20 | tags: ezjail -------------------------------------------------------------------------------- /roles/common_fb_host/tasks/pf.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Be sure pf.further-(params|set|nat|filter).conf and pf.ban exist 3 | copy: content="" dest=/etc/{{ item }} force=no owner=root group=wheel mode=0600 4 | with_items: 5 | - pf.further-params.conf 6 | - pf.further-set.conf 7 | - pf.further-nat.conf 8 | - pf.further-filter.conf 9 | - pf.further-pass.conf 10 | - pf.ban 11 | tags: pf 12 | 13 | - name: Create pf.conf 14 | template: src=pf.conf.j2 dest=/etc/pf.conf mode=0600 validate='pfctl -n -f %s' 15 | tags: pf 16 | 17 | - name: Be sure PF is running and enabled 18 | service: name=pf state=reloaded enabled=yes 19 | tags: pf 20 | 21 | -------------------------------------------------------------------------------- /roles/jails/templates/rc.conf.j2: -------------------------------------------------------------------------------- 1 | # Generated by Ansible 2 | hostname="{{ hostvars[item]['name'] }}" 3 | 4 | # No network interfaces in jails 5 | network_interfaces="" 6 | 7 | # Prevent rpc 8 | rpcbind_enable="NO" 9 | 10 | # Prevent loads of jails doing their cron jobs at the same time 11 | cron_flags="$cron_flags -J 15" 12 | 13 | # Prevent syslog to open sockets 14 | syslogd_flags="-ss" 15 | 16 | # Prevent sendmail to try to connect to localhost 17 | sendmail_enable="NO" 18 | sendmail_submit_enable="NO" 19 | sendmail_outbound_enable="NO" 20 | sendmail_msp_queue_enable="NO" 21 | 22 | # Bring up sshd, it takes some time and uses some entropy on first startup 23 | sshd_enable="YES" 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Playbooks for FreeBSD 2 | ===================== 3 | 4 | ## @jdauphant : I don't have time to manage anymore this role. Don't hesitate to fork and made your own version. 5 | 6 | Playbook example for FreeBSD 7 | 8 | ## Goals : 9 | - Create jails hosts 10 | - Create jail in each jail host 11 | - Configure each jails 12 | 13 | ## Needs : 14 | - pkgng repository (you can use the pcbsd repository) 15 | - ansible host requirement (sshd and python) 16 | 17 | ## You have to create : 18 | - ansible_host from ansible_host.example 19 | - group_vars/all from group_vars/all.example 20 | - a vars file for each jail host in host_vars from jailhost.domain.example 21 | 22 | ## Scripts : 23 | - apply.sh : launch ansible playbooks 24 | - info.sh : get variables from ansible node 25 | -------------------------------------------------------------------------------- /roles/common_fb_host/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Be sure of sshd configuration 3 | template: src=sshd_config.j2 dest=/etc/ssh/sshd_config 4 | notify: sshd restart 5 | tags: sshd 6 | 7 | # PF rules create quickly (before ssh bruteforce banish), if curent ip could be block if not present in the whitelist 8 | - include: pf.yml 9 | 10 | - name: Be sure security sysctl flags are configured 11 | sysctl: name={{ item.name }} value={{ item.value }} state=present checks=none reload=yes 12 | with_items: sysctl_flags 13 | 14 | - name: Be sure /etc/rc.conf.d exist 15 | file: path=/etc/rc.conf.d/ state=directory owner=root group=wheel mode=0655 16 | 17 | - name: Be sure Motd exist 18 | template: src=motd.j2 dest=/etc/motd 19 | 20 | - name: Be sure pkgng repository is configured 21 | template: src=pkg.conf.j2 dest=/usr/local/etc/pkg.conf 22 | 23 | - name: Be sure sudo is installed 24 | pkgng: name=sudo state=present 25 | 26 | - name: Be sure sudo is configured 27 | copy: src=sudoers dest=/usr/local/etc/sudoers validate='visudo -cf %s' 28 | 29 | - name: Be sure usefull tools are installed 30 | pkgng: name={{ item }} state=present 31 | with_items: 32 | - vim-lite 33 | - screen 34 | - nmap 35 | - zsh 36 | - git 37 | - mercurial 38 | - curl 39 | 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, DAUPHANT Julien 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /roles/common_fb_host/templates/pf.conf.j2: -------------------------------------------------------------------------------- 1 | # Generated by Ansible 2 | 3 | ### Params 4 | ## Interfaces 5 | local_if="lo0" 6 | ext_if="{{ ansible_default_ipv4.device }}" 7 | 8 | ## Address list 9 | server_addr="{{ ansible_default_ipv4.address }}" 10 | 11 | table { {% for ip in ipv4_whitelist %}{{ ip }} {% if loop.last == False %} , {% endif %}{% endfor %} } 12 | 13 | table persist file "/etc/pf.ban" 14 | table persist 15 | 16 | include "/etc/pf.further-params.conf" 17 | 18 | ## Ports 19 | tcp_ports_authorized="{ {% for port in default_tcp_ports_authorized %}{{ port }} {% endfor %}}" 20 | 21 | ### Rules 22 | # Set 23 | set optimization normal 24 | set block-policy return 25 | set require-order yes 26 | set loginterface $ext_if 27 | set skip on $local_if 28 | include "/etc/pf.further-set.conf" 29 | 30 | scrub in all 31 | 32 | ## Nat 33 | include "/etc/pf.further-nat.conf" 34 | 35 | ## Filter 36 | block in on $ext_if 37 | pass in inet proto { icmp } 38 | 39 | # Authorize out 40 | pass out quick inet proto { udp, icmp } from $ext_if to any keep state 41 | pass out quick inet proto tcp 42 | 43 | # Include filter ruleset 44 | include "/etc/pf.further-filter.conf" 45 | 46 | # Authorize defaults ports 47 | pass in on $ext_if inet proto tcp from any to any port $tcp_ports_authorized flags any keep state 48 | include "/etc/pf.further-pass.conf" 49 | 50 | # SSH Ban on badguys and ssh-bruteforce not whitelist 51 | block in quick on $ext_if from to any 52 | block in quick from to $server_addr 53 | pass in quick on $ext_if inet proto tcp from ! to any port ssh flags S/SA keep state \ 54 | ( max-src-conn-rate 12/50, overload flush global) 55 | -------------------------------------------------------------------------------- /roles/common_fb_host/templates/motd.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_distribution_version }} 2 | {% if ansible_distribution == "FreeBSD" %} 3 | _____ ____ ____ ____ 4 | | ___| _ __ ___ ___ | __ ) / ___| | _ \ 5 | | |_ | '__| / _ \ / _ \ | _ \ \___ \ | | | | , , 6 | | _| | | | __/ | __/ | |_) | ___) | | |_| | ,( ). 7 | | |_| |_| \___| \___| |____/ |____/ |____/ | \,--_ / | 8 | `-------------------------------- the power to serve /_ _ ` / 9 | /-.,-.` \ 10 | Welcome to FreeBSD {{ ansible_distribution_release }} | | \ \ 11 | ._____________________________________________\O|O | |__. 12 | | (___)`--'_ / | 13 | | THIS SYSTEM IS RESTRICTED TO `.______/` / | 14 | | AUTHORIZED USERS FOR AUTHORIZED `.__, ,/ | 15 | | USE ONLY, CHEERS. / \ | 16 | |____________________________________<----.______/ __ \____| 17 | <----|===)))==) \) /===== 18 | <----' `--' `.__,' | _ 19 | | | / \ 20 | \ _ /`-' \/ 21 | ,----` \ / 22 | \_,-----' \ 23 | \________/ 24 | {% endif %}Hostname : {{ ansible_hostname }} 25 | IP : {{ ansible_default_ipv4.address }} 26 | {% for processor in ansible_processor %}{% if loop.first %} {{ processor }} {% endif %} 27 | {% endfor %} 28 | 29 | -------------------------------------------------------------------------------- /roles/jails/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create ZFS partition for jails 3 | zfs: name={{ jails_zfs_root }} mountpoint={{ jails_dir }} checksum={{ zfs_checksum }} state=present 4 | 5 | - name: Configure network interface for jails 6 | template: src=network.j2 dest=/etc/rc.conf.d/network 7 | notify: restart network 8 | 9 | - name: Be sure jails params are in /etc/pf.futher-params.conf 10 | lineinfile: dest=/etc/pf.further-params.conf regexp="^{{ item.regexp }}" insertafter=EOF line="{{ item.line }}" 11 | with_items: 12 | - { regexp: 'jails_if=', line: 'jails_if=\"lo1\"' } 13 | - { regexp: 'table ', line: 'table { {{ jails_natted }} }' } 14 | - { regexp: 'jails_ssh_ports_authorized=', line: "jails_ssh_ports_authorized=\\\"{ {% for jail in jails_hosted %}{{ hostvars[jail]['ansible_ssh_port'] }} {% endfor %}}\\\"" } 15 | notify: reload pf 16 | 17 | - name: Be sure jails interface are skip in /etc/pf.futher-set.conf 18 | lineinfile: dest=/etc/pf.further-set.conf regexp="^set skip on .jails_if" insertafter=EOF line="set skip on $jails_if" 19 | notify: reload pf 20 | 21 | - name: Be sure jails nat rules are in /etc/pf.futher-nat.conf 22 | lineinfile: dest=/etc/pf.further-nat.conf regexp="^nat on .ext_if from to any" insertafter=EOF line="nat on $ext_if from to any -> ($ext_if)" 23 | notify: reload pf 24 | 25 | - name: Be sure rdr rules are in /etc/pf.futher-nat.conf 26 | lineinfile: dest=/etc/pf.further-nat.conf regexp="^rdr on .ext_if proto tcp from .* to .server_addr port {{ item.in }} -> {{ hostvars[item.host]['ip'] }} port {{ item.out }}" 27 | insertafter=EOF line="rdr on $ext_if proto tcp from any to $server_addr port {{ item.in }} -> {{ hostvars[item.host]['ip'] }} port {{ item.out }}" 28 | with_items: jails_in_nat_rules 29 | notify: reload pf 30 | 31 | - name: Be sure ssh authorized ports are in /etc/pf.futher-pass.conf 32 | lineinfile: dest=/etc/pf.further-pass.conf regexp="^pass in on .ext_if inet proto tcp from .* to .* port .jails_ssh_ports_authorized flags any keep state" 33 | insertafter=EOF line="pass in on $ext_if inet proto tcp from to $server_addr port $jails_ssh_ports_authorized flags any keep state" 34 | notify: reload pf 35 | 36 | - include: ezjail.yml 37 | 38 | - include: create_jails.yml 39 | -------------------------------------------------------------------------------- /roles/jails/templates/ezjail.conf.j2: -------------------------------------------------------------------------------- 1 | # Generated with Ansible 2 | 3 | # ezjail.conf - Example file, see ezjail.conf(5) 4 | # 5 | # Note: If you alter some of those variables AFTER creating your first 6 | # jail, you may have to adapt /etc/fstab.* and EZJAIL_PREFIX/etc/ezjail/* by 7 | # hand 8 | 9 | # Location of jail root directories 10 | # 11 | # Note: If you have spread your jails to multiple locations, use softlinks 12 | # to collect them in this directory 13 | ezjail_jaildir={{ jails_dir }} 14 | 15 | # Location of the tiny skeleton jail template 16 | # ezjail_jailtemplate=${ezjail_jaildir}/newjail 17 | 18 | # Location of the huge base jail 19 | # ezjail_jailbase=${ezjail_jaildir}/basejail 20 | 21 | # Location of your copy of FreeBSD's source tree 22 | # ezjail_sourcetree=/usr/src 23 | 24 | # In case you want to provide a copy of ports tree in base jail, set this to 25 | # a cvsroot near you 26 | # ezjail_portscvsroot=freebsdanoncvs@anoncvs.FreeBSD.org:/home/ncvs 27 | 28 | # This is where the install sub command defaults to fetch its packages from 29 | # ezjail_ftphost=ftp.freebsd.org 30 | 31 | # This is the command that is being executed by the console subcommand 32 | # ezjail_default_execute="/usr/bin/login -f root" 33 | 34 | # This is the flavour used by default when setting up a new jail 35 | # ezjail_default_flavour="" 36 | 37 | # This is the default location where ezjail archives its jails to 38 | # ezjail_archivedir="${ezjail_jaildir}/ezjail_archives" 39 | 40 | # base jail will provide a soft link from /usr/bin/perl to /usr/local/bin/perl 41 | # to accomodate all scripts using '#!/usr/bin/perl'... 42 | # ezjail_uglyperlhack="YES" 43 | 44 | # Default options for newly created jails 45 | # 46 | # Note: Be VERY careful about disabling ezjail_mount_enable. Mounting 47 | # basejail via nullfs depends on this. You will have to find other 48 | # ways to provide your jail with essential system files 49 | # ezjail_mount_enable="YES" 50 | # ezjail_devfs_enable="YES" 51 | # ezjail_devfs_ruleset="devfsrules_jail" 52 | ezjail_procfs_enable="NO" 53 | # ezjail_fdescfs_enable="YES" 54 | 55 | # Setting this to YES will start to manage the basejail and newjail in ZFS 56 | ezjail_use_zfs="YES" 57 | # The name of the ZFS ezjail should create jails on, it will be mounted at the ezjail_jaildir 58 | ezjail_jailzfs="{{ jails_zfs_root }}" 59 | # ADVANCED, be very careful! 60 | ezjail_zfs_properties="-o compression=lzjb -o atime=off" 61 | -------------------------------------------------------------------------------- /roles/jails/tasks/create_jails.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Be sure each Jail are created 3 | ezjail: name={{ hostvars[item]['name'] }} ip_addr={{ hostvars[item]['ip'] }} disktype=zfs 4 | with_items: jails_hosted 5 | 6 | - name: Be sure /usr/local/etc is present in each jail 7 | file: path={{ jails_dir }}/{{ hostvars[item]['name'] }}/usr/local/etc state=directory owner=root group=wheel 8 | with_items: jails_hosted 9 | 10 | - name: Be sure pkgng configuration is present in each jail 11 | template: src=pkg.conf.j2 dest={{ jails_dir }}/{{ hostvars[item]['name'] }}/usr/local/etc/pkg.conf 12 | with_items: jails_hosted 13 | 14 | - fetch: src=/etc/resolv.conf dest=/tmp/ansible 15 | 16 | - name: Be sure resolv.conf is present in each jail 17 | template: src=/tmp/ansible/{{ inventory_hostname }}/etc/resolv.conf dest={{ jails_dir }}/{{ hostvars[item]['name'] }}/etc/resolv.conf 18 | with_items: jails_hosted 19 | 20 | - name: Be sure rc.conf is configured in each jail 21 | template: src=rc.conf.j2 dest={{ jails_dir }}/{{ hostvars[item]['name'] }}/etc/rc.conf 22 | with_items: jails_hosted 23 | 24 | - name: Be sure sshd permit root login 25 | lineinfile: dest={{ jails_dir }}/{{ hostvars[item]['name'] }}/etc/ssh/sshd_config regexp="^#PermitRootLogin" line="PermitRootLogin yes" backrefs=yes 26 | with_items: jails_hosted 27 | 28 | - name: Be sure /root/.ssh is private 29 | file: path={{ jails_dir }}/{{ hostvars[item]['name'] }}/root/.ssh owner=root group=wheel mode=700 state=directory 30 | with_items: jails_hosted 31 | 32 | - name: Be sure public key is copy to root 33 | copy: src={{ ssh_public_key_file }} dest={{ jails_dir }}/{{ hostvars[item]['name'] }}/root/.ssh/authorized_keys owner=root group=wheel mode=600 34 | with_items: jails_hosted 35 | 36 | - name: Be sure ezjail is started 37 | service: name=ezjail state=restarted 38 | 39 | - name: Be sure pkgng is present in each jail 40 | pkgng_chroot: name=pkg chroot="{{ jails_dir }}/{{ hostvars[item]['name'] }}" state=present 41 | with_items: jails_hosted 42 | 43 | - name: Be sure python is present in each jail 44 | pkgng_chroot: name=python27 chroot="{{ jails_dir }}/{{ hostvars[item]['name'] }}" state=present 45 | with_items: jails_hosted 46 | 47 | - name: Be sure rdr rule are in /etc/pf.futher-nat.conf for each jail 48 | lineinfile: dest=/etc/pf.further-nat.conf regexp="^rdr on .ext_if proto tcp from .* to .server_addr port {{ hostvars[item]['ansible_ssh_port'] }} -> {{ hostvars[item]['ip'] }} port 22" 49 | insertafter=EOF line="rdr on $ext_if proto tcp from to $server_addr port {{ hostvars[item]['ansible_ssh_port'] }} -> {{ hostvars[item]['ip'] }} port 22" 50 | with_items: jails_hosted 51 | notify: reload pf 52 | -------------------------------------------------------------------------------- /roles/common_fb_host/files/sudoers: -------------------------------------------------------------------------------- 1 | ## sudoers file. 2 | ## 3 | ## This file MUST be edited with the 'visudo' command as root. 4 | ## Failure to use 'visudo' may result in syntax or file permission errors 5 | ## that prevent sudo from running. 6 | ## 7 | ## See the sudoers man page for the details on how to write a sudoers file. 8 | ## 9 | 10 | ## 11 | ## Host alias specification 12 | ## 13 | ## Groups of machines. These may include host names (optionally with wildcards), 14 | ## IP addresses, network numbers or netgroups. 15 | # Host_Alias WEBSERVERS = www1, www2, www3 16 | 17 | ## 18 | ## User alias specification 19 | ## 20 | ## Groups of users. These may consist of user names, uids, Unix groups, 21 | ## or netgroups. 22 | # User_Alias ADMINS = millert, dowdy, mikef 23 | 24 | ## 25 | ## Cmnd alias specification 26 | ## 27 | ## Groups of commands. Often used to group related commands together. 28 | # Cmnd_Alias PROCESSES = /usr/bin/nice, /bin/kill, /usr/bin/renice, \ 29 | # /usr/bin/pkill, /usr/bin/top 30 | 31 | ## 32 | ## Defaults specification 33 | ## 34 | ## Uncomment if needed to preserve environmental variables related to the 35 | ## FreeBSD pkg_* utilities and fetch. 36 | # Defaults env_keep += "PKG_PATH PKG_DBDIR PKG_TMPDIR TMPDIR PACKAGEROOT PACKAGESITE PKGDIR FTP_PASSIVE_MODE" 37 | ## 38 | ## Additionally uncomment if needed to preserve environmental variables 39 | ## related to portupgrade 40 | # Defaults env_keep += "PORTSDIR PORTS_INDEX PORTS_DBDIR PACKAGES PKGTOOLS_CONF" 41 | ## 42 | ## You may wish to keep some of the following environment variables 43 | ## when running commands via sudo. 44 | ## 45 | ## Locale settings 46 | # Defaults env_keep += "LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET" 47 | ## 48 | ## Run X applications through sudo; HOME is used to find the 49 | ## .Xauthority file. Note that other programs use HOME to find 50 | ## configuration files and this may lead to privilege escalation! 51 | Defaults env_keep += "HOME" 52 | ## 53 | ## X11 resource path settings 54 | # Defaults env_keep += "XAPPLRESDIR XFILESEARCHPATH XUSERFILESEARCHPATH" 55 | ## 56 | ## Desktop path settings 57 | # Defaults env_keep += "QTDIR KDEDIR" 58 | ## 59 | ## Allow sudo-run commands to inherit the callers' ConsoleKit session 60 | # Defaults env_keep += "XDG_SESSION_COOKIE" 61 | ## 62 | ## Uncomment to enable special input methods. Care should be taken as 63 | ## this may allow users to subvert the command being run via sudo. 64 | # Defaults env_keep += "XMODIFIERS GTK_IM_MODULE QT_IM_MODULE QT_IM_SWITCHER" 65 | ## 66 | ## Uncomment to enable logging of a command's output, except for 67 | ## sudoreplay and reboot. Use sudoreplay to play back logged sessions. 68 | Defaults log_output 69 | Defaults!/usr/bin/sudoreplay !log_output 70 | Defaults!/usr/local/bin/sudoreplay !log_output 71 | Defaults!/sbin/reboot !log_output 72 | 73 | ## 74 | ## Runas alias specification 75 | ## 76 | 77 | ## 78 | ## User privilege specification 79 | ## 80 | root ALL=(ALL) ALL 81 | 82 | ## Uncomment to allow members of group wheel to execute any command 83 | #%wheel ALL=(ALL) ALL 84 | 85 | ## Same thing without a password 86 | %wheel ALL=(ALL) NOPASSWD: ALL 87 | 88 | ## Uncomment to allow members of group sudo to execute any command 89 | #%sudo ALL=(ALL) ALL 90 | 91 | ## Uncomment to allow any user to run sudo if they know the password 92 | ## of the user they are running the command as (root by default). 93 | # Defaults targetpw # Ask for the password of the target user 94 | # ALL ALL=(ALL) ALL # WARNING: only use this together with 'Defaults targetpw' 95 | 96 | ## Read drop-in files from /usr/local/etc/sudoers.d 97 | ## (the '#' here does not indicate a comment) 98 | #includedir /usr/local/etc/sudoers.d 99 | -------------------------------------------------------------------------------- /roles/common_fb_host/templates/sshd_config.j2: -------------------------------------------------------------------------------- 1 | # Generated by ansible 2 | # $OpenBSD: sshd_config,v 1.82 2010/09/06 17:10:19 naddy Exp $ 3 | # $FreeBSD: release/9.1.0/crypto/openssh/sshd_config 224638 2011-08-03 19:14:22Z brooks $ 4 | 5 | # This is the sshd server system-wide configuration file. See 6 | # sshd_config(5) for more information. 7 | 8 | # This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin 9 | 10 | # The strategy used for options in the default sshd_config shipped with 11 | # OpenSSH is to specify options with their default value where 12 | # possible, but leave them commented. Uncommented options change a 13 | # default value. 14 | 15 | # Note that some of FreeBSD's defaults differ from OpenBSD's, and 16 | # FreeBSD has a few additional options. 17 | 18 | VersionAddendum 19 | 20 | #Port 22 21 | #AddressFamily any 22 | #ListenAddress 0.0.0.0 23 | #ListenAddress :: 24 | ListenAddress {{ ansible_default_ipv4.address }} 25 | 26 | # The default requires explicit activation of protocol 1 27 | #Protocol 2 28 | 29 | # HostKey for protocol version 1 30 | #HostKey /etc/ssh/ssh_host_key 31 | # HostKeys for protocol version 2 32 | #HostKey /etc/ssh/ssh_host_rsa_key 33 | #HostKey /etc/ssh/ssh_host_dsa_key 34 | #HostKey /etc/ssh/ssh_host_ecdsa_key 35 | 36 | # Lifetime and size of ephemeral version 1 server key 37 | #KeyRegenerationInterval 1h 38 | #ServerKeyBits 1024 39 | 40 | # Logging 41 | # obsoletes QuietMode and FascistLogging 42 | #SyslogFacility AUTH 43 | #LogLevel INFO 44 | 45 | # Authentication: 46 | 47 | #LoginGraceTime 2m 48 | PermitRootLogin yes 49 | #StrictModes yes 50 | #MaxAuthTries 6 51 | #MaxSessions 10 52 | 53 | #RSAAuthentication yes 54 | #PubkeyAuthentication yes 55 | #AuthorizedKeysFile .ssh/authorized_keys 56 | 57 | # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts 58 | #RhostsRSAAuthentication no 59 | # similar for protocol version 2 60 | #HostbasedAuthentication no 61 | # Change to yes if you don't trust ~/.ssh/known_hosts for 62 | # RhostsRSAAuthentication and HostbasedAuthentication 63 | #IgnoreUserKnownHosts no 64 | # Don't read the user's ~/.rhosts and ~/.shosts files 65 | #IgnoreRhosts yes 66 | 67 | # Change to yes to enable built-in password authentication. 68 | PasswordAuthentication no 69 | PermitEmptyPasswords no 70 | 71 | # Change to no to disable PAM authentication 72 | #ChallengeResponseAuthentication yes 73 | 74 | # Kerberos options 75 | #KerberosAuthentication no 76 | #KerberosOrLocalPasswd yes 77 | #KerberosTicketCleanup yes 78 | #KerberosGetAFSToken no 79 | 80 | # GSSAPI options 81 | #GSSAPIAuthentication no 82 | #GSSAPICleanupCredentials yes 83 | 84 | # Set this to 'no' to disable PAM authentication, account processing, 85 | # and session processing. If this is enabled, PAM authentication will 86 | # be allowed through the ChallengeResponseAuthentication and 87 | # PasswordAuthentication. Depending on your PAM configuration, 88 | # PAM authentication via ChallengeResponseAuthentication may bypass 89 | # the setting of "PermitRootLogin without-password". 90 | # If you just want the PAM account and session checks to run without 91 | # PAM authentication, then enable this but set PasswordAuthentication 92 | # and ChallengeResponseAuthentication to 'no'. 93 | #UsePAM yes 94 | 95 | #AllowAgentForwarding yes 96 | #AllowTcpForwarding yes 97 | #GatewayPorts no 98 | #X11Forwarding yes 99 | #X11DisplayOffset 10 100 | #X11UseLocalhost yes 101 | #PrintMotd yes 102 | #PrintLastLog yes 103 | #TCPKeepAlive yes 104 | #UseLogin no 105 | #UsePrivilegeSeparation yes 106 | #PermitUserEnvironment no 107 | #Compression delayed 108 | #ClientAliveInterval 0 109 | #ClientAliveCountMax 3 110 | #UseDNS yes 111 | #PidFile /var/run/sshd.pid 112 | #MaxStartups 10 113 | #PermitTunnel no 114 | #ChrootDirectory none 115 | 116 | # no default banner path 117 | #Banner none 118 | 119 | # override default of no subsystems 120 | Subsystem sftp /usr/libexec/sftp-server 121 | 122 | # Disable HPN tuning improvements. 123 | #HPNDisabled no 124 | 125 | # Buffer size for HPN to non-HPN connections. 126 | #HPNBufferSize 2048 127 | 128 | # TCP receive socket buffer polling for HPN. Disable on non autotuning kernels. 129 | #TcpRcvBufPoll yes 130 | 131 | # Allow the use of the NONE cipher. 132 | #NoneEnabled no 133 | 134 | # Example of overriding settings on a per-user basis 135 | #Match User anoncvs 136 | # X11Forwarding no 137 | # AllowTcpForwarding no 138 | # ForceCommand cvs server 139 | -------------------------------------------------------------------------------- /library/pkgng_chroot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Patch by julien DAUPHANT to support chroot 5 | 6 | # (c) 2013, bleader 7 | # Written by bleader 8 | # Based on pkgin module written by Shaun Zinck 9 | # that was based on pacman module written by Afterburn 10 | # that was based on apt module written by Matthew Williams 11 | # 12 | # This module is free software: you can redistribute it and/or modify 13 | # it under the terms of the GNU General Public License as published by 14 | # the Free Software Foundation, either version 3 of the License, or 15 | # (at your option) any later version. 16 | # 17 | # This software is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this software. If not, see . 24 | 25 | 26 | DOCUMENTATION = ''' 27 | --- 28 | module: pkgng 29 | short_description: Package manager for FreeBSD >= 9.0 30 | description: 31 | - Manage binary packages for FreeBSD using 'pkgng' which 32 | is available in versions after 9.0. 33 | version_added: "1.2" 34 | options: 35 | name: 36 | description: 37 | - name of package to install/remove 38 | required: true 39 | state: 40 | description: 41 | - state of the package 42 | choices: [ 'present', 'absent' ] 43 | required: false 44 | default: present 45 | cached: 46 | description: 47 | - use local package base or try to fetch an updated one 48 | choices: [ 'yes', 'no' ] 49 | required: false 50 | default: no 51 | pkgsite: 52 | description: 53 | - specify packagesite to use for downloading packages, if 54 | not specified, use settings from /usr/local/etc/pkg.conf 55 | required: false 56 | author: bleader 57 | notes: 58 | - When using pkgsite, be careful that already in cache packages won't be downloaded again. 59 | ''' 60 | 61 | EXAMPLES = ''' 62 | # Install package foo 63 | - pkgng: name=foo state=present 64 | 65 | # Remove packages foo and bar 66 | - pkgng: name=foo,bar state=absent 67 | ''' 68 | 69 | 70 | import json 71 | import shlex 72 | import os 73 | import sys 74 | 75 | def query_package(module, pkgin_path, name, chroot): 76 | 77 | rc, out, err = module.run_command("%s%s info -e %s" % (pkgin_path, chroot, name)) 78 | 79 | if rc == 0: 80 | return True 81 | 82 | return False 83 | 84 | 85 | def remove_packages(module, pkgin_path, packages, chroot): 86 | 87 | if chroot != "": 88 | chroot=" -c %s" % (chroot) 89 | 90 | remove_c = 0 91 | # Using a for loop incase of error, we can report the package that failed 92 | for package in packages: 93 | # Query the package first, to see if we even need to remove 94 | if not query_package(module, pkgin_path, package, chroot): 95 | continue 96 | 97 | rc, out, err = module.run_command("%s%s delete -y %s" % (pkgin_path, chroot, package)) 98 | 99 | if query_package(module, pkgin_path, package, chroot): 100 | module.fail_json(msg="failed to remove %s: %s" % (package, out)) 101 | 102 | remove_c += 1 103 | 104 | if remove_c > 0: 105 | 106 | module.exit_json(changed=True, msg="removed %s package(s)" % remove_c) 107 | 108 | module.exit_json(changed=False, msg="package(s) already absent") 109 | 110 | 111 | def install_packages(module, pkgin_path, packages, cached, pkgsite, chroot): 112 | 113 | install_c = 0 114 | 115 | if pkgsite != "": 116 | pkgsite="PACKAGESITE=%s" % (pkgsite) 117 | 118 | if chroot != "": 119 | chroot=" -c %s" % (chroot) 120 | 121 | if cached == "no": 122 | rc, out, err = module.run_command("%s %s%s update" % (pkgsite, pkgin_path, chroot)) 123 | if rc != 0: 124 | module.fail_json(msg="Could not update catalogue") 125 | 126 | for package in packages: 127 | if query_package(module, pkgin_path, package, chroot): 128 | continue 129 | 130 | rc, out, err = module.run_command("%s %s%s install -U -y %s" % (pkgsite, pkgin_path, chroot, package)) 131 | 132 | if not query_package(module, pkgin_path, package, chroot): 133 | module.fail_json(msg="failed to install %s: %s" % (package, out)) 134 | 135 | install_c += 1 136 | 137 | if install_c > 0: 138 | module.exit_json(changed=True, msg="present %s package(s)" % (install_c)) 139 | 140 | module.exit_json(changed=False, msg="package(s) already present") 141 | 142 | 143 | def main(): 144 | module = AnsibleModule( 145 | argument_spec = dict( 146 | state = dict(default="present", choices=["present","absent"]), 147 | name = dict(aliases=["pkg"], required=True), 148 | cached = dict(default="no", required=False, choices=["yes","no"]), 149 | chroot = dict(default="", required=False), 150 | pkgsite = dict(default="", required=False))) 151 | 152 | pkgin_path = module.get_bin_path('pkg', True) 153 | 154 | p = module.params 155 | 156 | pkgs = p["name"].split(",") 157 | 158 | if p["state"] == "present": 159 | install_packages(module, pkgin_path, pkgs, p["cached"], p["pkgsite"], p["chroot"]) 160 | 161 | elif p["state"] == "absent": 162 | remove_packages(module, pkgin_path, pkgs, p["chroot"]) 163 | 164 | # this is magic, see lib/ansible/module_common.py 165 | #<> 166 | 167 | main() 168 | --------------------------------------------------------------------------------