├── .gitignore ├── LICENSE ├── README.md ├── _snippets └── localrepo.yml ├── group_vars ├── all ├── database ├── ipaclients ├── ipaservers ├── openstacknodes ├── proxmox ├── services └── workstations ├── host_vars ├── compute.lan.nathancurry.com ├── db1.lan.nathancurry.com ├── db2.lan.nathancurry.com ├── infra.lan.nathancurry.com ├── ipa1.lan.nathancurry.com ├── ipa2.lan.nathancurry.com ├── mass.lan.nathancurry.com ├── ns1.lan.nathancurry.com ├── ns2.lan.nathancurry.com ├── repo.lan.nathancurry.com ├── share.lan.nathancurry.com ├── storage.lan.nathancurry.com └── tiny.lan.nathancurry.com ├── hypervisors.yml ├── install-ipaclient-debian.yml ├── install-ipaclient.yml ├── inventory ├── ipareplica.yml ├── ipaserver.yml ├── library ├── deploy_machines.yml ├── generate_kickstarts.yml ├── init-server.yml └── install-freeipa-cluster.yml ├── module_utils ├── ansible_ipa_client.py ├── ansible_ipa_replica.py └── ansible_ipa_server.py ├── nameservers.yml ├── osa-init.yml ├── osa-networking.yml ├── reposerver.yml ├── rmipaserver.yml ├── roles ├── bind │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ │ ├── db.forward.j2 │ │ ├── db.reverse.j2 │ │ ├── named.conf.j2 │ │ ├── named.conf.local.j2 │ │ └── rndc.key.j2 │ └── vars │ │ └── main.yml ├── chronyclient │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ │ ├── chrony.conf.j2 │ │ └── chrony.keys.j2 │ └── vars │ │ └── main.yml ├── chronyserver │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ │ ├── chrony-server.conf.j2 │ │ └── chrony.keys.j2 │ └── vars │ │ └── main.yml ├── deployvms │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ ├── deploy_containers.yml │ │ ├── deploy_vms.yml │ │ ├── install_pip.yml │ │ └── main.yml │ ├── templates │ │ ├── deploy-args-centos.j2 │ │ ├── deploy-args-ubuntu.j2 │ │ └── kernel.j2 │ └── vars │ │ └── main.yml ├── dhcpd │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ │ ├── dhcpd.conf.j2 │ │ ├── omapi.key.j2 │ │ └── rndc.key.j2 │ └── vars │ │ └── main.yml ├── ipa-krb5 │ ├── defaults │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ │ └── krb5.conf.j2 │ └── vars │ │ └── default.yml ├── ipa-sssd │ ├── defaults │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ │ └── sssd.conf.j2 │ └── vars │ │ └── default.yml ├── ipaclient │ ├── action_plugins │ │ ├── ipahost.py │ │ └── ipahost.pyc │ ├── defaults │ │ └── main.yml │ ├── files │ │ └── py3test.py │ ├── library │ │ ├── ipa_facts.py │ │ ├── ipaapi.py │ │ ├── ipaclient_set_hostname.py │ │ ├── ipadiscovery.py │ │ ├── ipaextras.py │ │ ├── ipafixca.py │ │ ├── ipafstore.py │ │ ├── ipahost.py │ │ ├── ipajoin.py │ │ ├── ipanss.py │ │ ├── ipasssd.py │ │ └── ipatest.py │ ├── meta │ │ └── main.yml │ ├── tasks │ │ ├── install.yml │ │ ├── main.yml │ │ ├── python_2_3_test.yml │ │ └── uninstall.yml │ └── vars │ │ ├── CentOS-7.yml │ │ ├── Fedora-25.yml │ │ ├── Fedora-26.yml │ │ ├── RedHat-7.3.yml │ │ ├── RedHat-7.yml │ │ ├── Ubuntu.yml │ │ └── default.yml ├── ipaconf │ ├── defaults │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ │ └── default.conf.j2 │ └── vars │ │ └── default.yml ├── ipareplica │ ├── defaults │ │ └── main.yml │ ├── files │ │ └── py3test.py │ ├── library │ │ ├── ipareplica_add_to_ipaservers.py │ │ ├── ipareplica_create_ipa_conf.py │ │ ├── ipareplica_custodia_import_dm_password.py │ │ ├── ipareplica_ds_apply_updates.py │ │ ├── ipareplica_ds_enable_ssl.py │ │ ├── ipareplica_install_ca_certs.py │ │ ├── ipareplica_krb_enable_ssl.py │ │ ├── ipareplica_prepare.py │ │ ├── ipareplica_promote_openldap_conf.py │ │ ├── ipareplica_promote_sssd.py │ │ ├── ipareplica_restart_kdc.py │ │ ├── ipareplica_setup_adtrust.py │ │ ├── ipareplica_setup_ca.py │ │ ├── ipareplica_setup_certmonger.py │ │ ├── ipareplica_setup_custodia.py │ │ ├── ipareplica_setup_dns.py │ │ ├── ipareplica_setup_ds.py │ │ ├── ipareplica_setup_http.py │ │ ├── ipareplica_setup_kra.py │ │ ├── ipareplica_setup_krb.py │ │ ├── ipareplica_setup_otpd.py │ │ ├── ipareplica_test.py │ │ ├── ipaserver_enable_ipa.py │ │ ├── ipaserver_master_password.py │ │ └── ipaserver_setup_ntp.py │ ├── meta │ │ └── main.yml │ ├── tasks │ │ ├── install.yml │ │ ├── main.yml │ │ ├── python_2_3_test.yml │ │ └── uninstall.yml │ └── vars │ │ ├── CentOS-7.yml │ │ ├── Fedora-25.yml │ │ ├── Fedora-26.yml │ │ ├── Fedora-27.yml │ │ ├── Fedora.yml │ │ ├── RedHat-7.3.yml │ │ ├── RedHat-7.yml │ │ ├── Ubuntu.yml │ │ └── default.yml ├── ipaserver │ ├── defaults │ │ └── main.yml │ ├── files │ │ └── py3test.py │ ├── library │ │ ├── ansible_ipa_server.py │ │ ├── ipaserver.py │ │ ├── ipaserver_enable_ipa.py │ │ ├── ipaserver_load_cache.py │ │ ├── ipaserver_master_password.py │ │ ├── ipaserver_prepare.py │ │ ├── ipaserver_set_ds_password.py │ │ ├── ipaserver_setup_adtrust.py │ │ ├── ipaserver_setup_ca.py │ │ ├── ipaserver_setup_custodia.py │ │ ├── ipaserver_setup_dns.py │ │ ├── ipaserver_setup_ds.py │ │ ├── ipaserver_setup_http.py │ │ ├── ipaserver_setup_kra.py │ │ ├── ipaserver_setup_krb.py │ │ ├── ipaserver_setup_ntp.py │ │ ├── ipaserver_setup_otpd.py │ │ └── ipaserver_test.py │ ├── meta │ │ └── main.yml │ ├── tasks │ │ ├── install.yml │ │ ├── main.yml │ │ ├── python_2_3_test.yml │ │ └── uninstall.yml │ └── vars │ │ ├── CentOS-7.yml │ │ ├── Fedora-25.yml │ │ ├── Fedora-26.yml │ │ ├── Fedora-27.yml │ │ ├── Fedora.yml │ │ ├── RedHat-7.3.yml │ │ ├── RedHat-7.yml │ │ ├── Ubuntu.yml │ │ └── default.yml ├── kickstart │ ├── LICENSE-sergev.md │ ├── tasks │ │ └── main.yml │ ├── templates │ │ ├── host_default.j2 │ │ ├── kickstart-fc28.j2 │ │ ├── kickstart.j2 │ │ └── pxe.j2 │ └── vars │ │ └── main.yml ├── osapreparenetwork-broken │ ├── tasks │ │ └── main.yml │ └── vars │ │ └── main.yml ├── osapreparenetwork │ ├── files │ │ └── ifcfg-lo │ ├── tasks │ │ └── main.yml │ ├── templates │ │ ├── ifcfg-br-mgmt.j2 │ │ ├── ifcfg-br-storage.j2 │ │ ├── ifcfg-br-vlan.j2 │ │ ├── ifcfg-br-vxlan.j2 │ │ ├── ifcfg-bridge.j2 │ │ ├── ifcfg-netdev.j2 │ │ └── ifcfg-vlan.j2 │ ├── test.yml │ └── vars │ │ └── main.yml ├── osapreparenode │ ├── files │ │ └── openstack-ansible.conf │ ├── tasks │ │ ├── deployhost.yml │ │ └── main.yml │ └── vars │ │ └── main.yml ├── preparestorage │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── repoclient │ ├── files │ │ └── local.repo │ └── tasks │ │ └── main.yml ├── reposerver │ ├── files │ │ ├── local.repo │ │ ├── reposync.conf │ │ └── reposync.repo │ ├── tasks │ │ └── main.yml │ └── vars │ │ └── main.yml ├── sshdisableroot │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml ├── sshenableuser │ ├── tasks │ │ └── main.yml │ └── vars │ │ ├── Debian.yml │ │ ├── default.yml │ │ └── main.yml └── tftpserver │ ├── files │ ├── chain.c32 │ ├── mboot.c32 │ ├── memdisk │ └── menu.c32 │ ├── tasks │ ├── main.yml │ ├── start.yml │ └── stop.yml │ └── vars │ └── main.yml ├── site.yml └── sitevars.yml /.gitignore: -------------------------------------------------------------------------------- 1 | ansible.cfg 2 | *.retry 3 | _* 4 | *vmlinuz 5 | *initrd.img 6 | *pxelinux.0 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # homelab.ansible 2 | 3 | Ansible infrastructure for my home lab. 4 | 5 | I am deploying enterprise infrastructure. Starting with nothing, and pulling myself up by my tiny little bootstraps. Follow a body at http://www.nathancurry.com 6 | -------------------------------------------------------------------------------- /_snippets/localrepo.yml: -------------------------------------------------------------------------------- 1 | - name: disable CENTOS repos(CentOS only) 2 | ini_file: 3 | dest: /etc/yum.repos.d/CentOS-Base.repo 4 | section: "{{ item }}" 5 | option: enabled 6 | value: 0 7 | with_items: 8 | - base 9 | - updates 10 | - extras 11 | - centosplus 12 | 13 | - name: Add Local Base repo 14 | yum_repository: 15 | name: base-local 16 | description: Local Base repo 17 | file: local 18 | baseurl: http://repo.lan.nathancurry.com/repo/centos7/base/ 19 | gpgcheck: yes 20 | gpgkey: http://mirror.centos.org/centos/RPM-GPG-KEY-centos4 21 | 22 | - name: Add Local Updates repo 23 | yum_repository: 24 | name: updates-local 25 | description: Local Updates repo 26 | file: local 27 | baseurl: http://repo.lan.nathancurry.com/repo/centos7/updates/ 28 | gpgcheck: yes 29 | gpgkey: http://mirror.centos.org/centos/RPM-GPG-KEY-centos4 30 | 31 | - name: Add Local Extras repo 32 | yum_repository: 33 | name: extras-local 34 | description: Local Extras repo 35 | file: local 36 | baseurl: http://repo.lan.nathancurry.com/repo/centos7/extras/ 37 | gpgcheck: yes 38 | gpgkey: http://mirror.centos.org/centos/RPM-GPG-KEY-centos4 39 | 40 | - name: Add Local EPEL repo 41 | yum_repository: 42 | name: epel-local 43 | description: Local EPEL repo 44 | file: local 45 | baseurl: http://repo.lan.nathancurry.com/repo/centos7/epel/ 46 | gpgcheck: yes 47 | gpgkey: http://mirror.grid.uchicago.edu/pub/linux/epel/RPM-GPG-KEY-EPEL-7 48 | -------------------------------------------------------------------------------- /group_vars/all: -------------------------------------------------------------------------------- 1 | --- 2 | searchdomain: 'lan.nathancurry.com' 3 | 4 | ipaserver_domain: 'lan.nathancurry.com' 5 | ipaserver_realm: 'LAN.NATHANCURRY.COM' 6 | ipaserver_forwarders: 7 | - 10.3.3.2 8 | - 10.3.3.3 9 | ipaserver_no_reverse: false 10 | ipaserver_setup_dns: yes 11 | 12 | ipaclient_domain: 'lan.nathancurry.com' 13 | ipaclient_no_ntp: 'yes' 14 | 15 | freeipa_server: 'ipa1.lan.nathancurry.com' 16 | 17 | user: nc 18 | -------------------------------------------------------------------------------- /group_vars/database: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathancurry/homelab.ansible/fba05a5e8931fc3982dcb1bb4143e73bef888080/group_vars/database -------------------------------------------------------------------------------- /group_vars/ipaclients: -------------------------------------------------------------------------------- 1 | --- 2 | ipaclient_domain: lan.nathancurry.com 3 | ipaclient_realm: LAN.NATHANCURRY.COM 4 | ipaclient_no_ntp: true 5 | ipaclient_allow_repair: true 6 | ipaclient_force_join: true 7 | 8 | ipaservers: 9 | - ipa1.lan.nathancurry.com 10 | 11 | ipacelient_servers: 12 | - ipa1.lan.nathancurry.com 13 | -------------------------------------------------------------------------------- /group_vars/ipaservers: -------------------------------------------------------------------------------- 1 | --- 2 | virtio: '{"virtio0":"gluster:15,cache=none,discard=on,format=qcow2"}' 3 | swap: 2048 4 | memory: 4096 5 | 6 | #distro: fc28 7 | #install_url: 'http://download.fedoraproject.org/pub/fedora/linux/releases/28/Server/x86_64/os' 8 | -------------------------------------------------------------------------------- /group_vars/openstacknodes: -------------------------------------------------------------------------------- 1 | --- 2 | user: stack 3 | # freeipa_client: True 4 | # freeipa_servers: [ 'ipa1.{{ ansible_domain }}' ] 5 | # auth_cracklib: False 6 | # auth_nsswitch: [ 'compat', 'sss' ] 7 | # sshd_authorized_keys_lookup: True 8 | # sshd_authorized_keys_lookup_type: [ 'sss' ] 9 | -------------------------------------------------------------------------------- /group_vars/proxmox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathancurry/homelab.ansible/fba05a5e8931fc3982dcb1bb4143e73bef888080/group_vars/proxmox -------------------------------------------------------------------------------- /group_vars/services: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathancurry/homelab.ansible/fba05a5e8931fc3982dcb1bb4143e73bef888080/group_vars/services -------------------------------------------------------------------------------- /group_vars/workstations: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathancurry/homelab.ansible/fba05a5e8931fc3982dcb1bb4143e73bef888080/group_vars/workstations -------------------------------------------------------------------------------- /host_vars/compute.lan.nathancurry.com: -------------------------------------------------------------------------------- 1 | --- 2 | ansible_host: '10.3.3.12' 3 | mac_address: '48:0f:cf:44:1c:d6' 4 | netdev: 5 | - 'eno1' 6 | - 'enp0s20u2' 7 | 8 | # openstack-ansible 9 | osa_host_id: 12 10 | -------------------------------------------------------------------------------- /host_vars/db1.lan.nathancurry.com: -------------------------------------------------------------------------------- 1 | ansible_host: '10.3.3.41' 2 | mac_address: '52:54:00:5e:8c:8c' 3 | -------------------------------------------------------------------------------- /host_vars/db2.lan.nathancurry.com: -------------------------------------------------------------------------------- 1 | ansible_host: '10.3.3.42' 2 | mac_address: '52:54:00:1f:b8:5d' 3 | -------------------------------------------------------------------------------- /host_vars/infra.lan.nathancurry.com: -------------------------------------------------------------------------------- 1 | --- 2 | ansible_host: '10.3.3.11' 3 | mac_address: '18:66:da:14:22:6e' 4 | netdev: 5 | - 'em1' 6 | - 'enp0s20u2' 7 | 8 | 9 | # openstack-ansible 10 | osa_deployhost: true 11 | osa_host_id: 11 12 | -------------------------------------------------------------------------------- /host_vars/ipa1.lan.nathancurry.com: -------------------------------------------------------------------------------- 1 | ansible_host: '10.3.3.11' 2 | mac_address: '52:54:00:81:8b:e9' 3 | vmid: '204' 4 | proxmox_node: 'bronze' 5 | -------------------------------------------------------------------------------- /host_vars/ipa2.lan.nathancurry.com: -------------------------------------------------------------------------------- 1 | ansible_host: '10.3.3.12' 2 | mac_address: '52:54:00:bc:4a:48' 3 | vmid: '205' 4 | proxmox_node: 'silver' 5 | -------------------------------------------------------------------------------- /host_vars/mass.lan.nathancurry.com: -------------------------------------------------------------------------------- 1 | ansible_host: '10.3.3.43' 2 | mac_address: '52:54:00:a2:f8:25' 3 | node: gold 4 | -------------------------------------------------------------------------------- /host_vars/ns1.lan.nathancurry.com: -------------------------------------------------------------------------------- 1 | ansible_host: '10.3.3.2' 2 | mac_address: '52:54:00:07:60:08' 3 | services: [ 'dns', 'dhcp' ] 4 | vmid: '201' 5 | proxmox_node: 'gold' 6 | -------------------------------------------------------------------------------- /host_vars/ns2.lan.nathancurry.com: -------------------------------------------------------------------------------- 1 | ansible_host: '10.3.3.3' 2 | mac_address: '52:54:00:5b:cb:ea' 3 | services: [ 'dns', 'dhcp' ] 4 | vmid: '202' 5 | proxmox_node: 'bronze' 6 | -------------------------------------------------------------------------------- /host_vars/repo.lan.nathancurry.com: -------------------------------------------------------------------------------- 1 | ansible_host: '10.3.3.45' 2 | mac_address: '52:54:00:e0:97:d4' 3 | vmid: '203' 4 | proxmox_node: 'bronze' 5 | proxmox_mount: '' 6 | -------------------------------------------------------------------------------- /host_vars/share.lan.nathancurry.com: -------------------------------------------------------------------------------- 1 | ansible_host: '10.3.3.44' 2 | mac_address: '52:54:00:6f:08:6a' 3 | -------------------------------------------------------------------------------- /host_vars/storage.lan.nathancurry.com: -------------------------------------------------------------------------------- 1 | --- 2 | ansible_host: '10.3.3.13' 3 | mac_address: '00:23:24:6a:d8:09' 4 | netdev: 5 | - 'eno1' 6 | - 'enp0s20u2' 7 | 8 | 9 | # storage_uuid: '22d8ad98-9571-40ef-b816-9e05f7e20152' 10 | # storage_guest_vmid: '203' 11 | 12 | # openstack-ansible 13 | osa_host_id: 13 14 | -------------------------------------------------------------------------------- /host_vars/tiny.lan.nathancurry.com: -------------------------------------------------------------------------------- 1 | ansible_host: 10.3.3.77 2 | mac_address: '7c:5c:f8:1a:0d:88' 3 | -------------------------------------------------------------------------------- /hypervisors.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Configure Hypervisors 3 | hosts: hypervisors 4 | become: true 5 | 6 | roles: 7 | - chronyserver 8 | -------------------------------------------------------------------------------- /install-ipaclient-debian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Playbook to configure IPA clients with username/password 3 | hosts: hypervisors 4 | become: true 5 | vars_files: 6 | - ~/0/vault/secrets.yml 7 | 8 | roles: 9 | - role: ipaclientdebian 10 | -------------------------------------------------------------------------------- /install-ipaclient.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Playbook to configure IPA clients with username/password 3 | hosts: repo.lan.nathancurry.com 4 | become: true 5 | vars_files: 6 | - ~/0/vault/secrets.yml 7 | 8 | 9 | tasks: 10 | - name: resolv 11 | lineinfile: 12 | path: /etc/resolv.conf 13 | state: present 14 | line: nameserver 10.3.3.11 15 | insertbefore: 'BOF' 16 | 17 | roles: 18 | - role: ipaclient 19 | state: present 20 | -------------------------------------------------------------------------------- /inventory: -------------------------------------------------------------------------------- 1 | [all] 2 | 3 | [openstacknodes] 4 | infra.lan.nathancurry.com 5 | compute.lan.nathancurry.com 6 | storage.lan.nathancurry.com 7 | 8 | [timeservers:children] 9 | openstacknodes 10 | 11 | [nsmasters] 12 | ns1.lan.nathancurry.com 13 | 14 | [nsslaves] 15 | ns2.lan.nathancurry.com 16 | 17 | [ns:children] 18 | nsmasters 19 | nsslaves 20 | 21 | [kickstart] 22 | repo.lan.nathancurry.com 23 | 24 | [storage] 25 | share.lan.nathancurry.com 26 | 27 | [dbservers] 28 | db1.lan.nathancurry.com 29 | db2.lan.nathancurry.com 30 | 31 | [ipaserver] 32 | ipa1.lan.nathancurry.com 33 | 34 | [ipareplicas] 35 | ipa2.lan.nathancurry.com 36 | 37 | [ipaservers:children] 38 | ipaserver 39 | 40 | 41 | [workstations] 42 | tiny.lan.nathancurry.com 43 | 44 | [timeclients:children] 45 | ipaservers 46 | dbservers 47 | workstations 48 | ns 49 | storage 50 | kickstart 51 | 52 | [ipaclients:children] 53 | ns 54 | storage 55 | ipareplicas 56 | kickstart 57 | -------------------------------------------------------------------------------- /ipareplica.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Playbook to configure IPA servers 3 | hosts: ipareplicas 4 | become: true 5 | vars_files: 6 | - ~/0/vault/secrets.yml 7 | 8 | roles: 9 | - role: ipareplica 10 | state: present 11 | -------------------------------------------------------------------------------- /ipaserver.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Playbook to configure IPA servers 3 | hosts: ipaserver 4 | become: true 5 | vars_files: 6 | - ~/0/vault/secrets.yml 7 | 8 | roles: 9 | - role: ipaserver 10 | state: present 11 | -------------------------------------------------------------------------------- /library/deploy_machines.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # - hosts: repo.lan.nathancurry.com 3 | # tasks: 4 | # - include_tasks: ../roles/tftpserver/tasks/start.yml 5 | 6 | - hosts: gold.lan.nathancurry.com 7 | roles: 8 | - deployvms 9 | # - hosts: repo.lan.nathancurry.com 10 | # tasks: 11 | # - include_tasks: ../roles/tftpserver/tasks/stop.yml 12 | -------------------------------------------------------------------------------- /library/generate_kickstarts.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: generate kickstarts 3 | hosts: repo.lan.nathancurry.com 4 | become: true 5 | 6 | roles: 7 | - kickstart 8 | -------------------------------------------------------------------------------- /library/init-server.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: enable SSH user 3 | hosts: ipareplicas 4 | # user: root 5 | become: true 6 | 7 | roles: 8 | - sshenableuser 9 | 10 | - name: disable SSH root 11 | hosts: ipareplicas 12 | become: true 13 | 14 | # tasks: 15 | # - name: Install python 16 | #raw: "yum -y install python2 python3" 17 | 18 | roles: 19 | - sshdisableroot 20 | - repoclient 21 | -------------------------------------------------------------------------------- /library/install-freeipa-cluster.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install IPA servers 3 | hosts: ipaserver 4 | become: true 5 | 6 | roles: 7 | - role: ipaserver 8 | state: present 9 | 10 | - name: Install IPA replicas 11 | hosts: ipareplicas 12 | become: true 13 | 14 | roles: 15 | - role: ipareplica 16 | state: present 17 | 18 | - name: Install IPA clients 19 | hosts: ipaclients 20 | become: true 21 | 22 | roles: 23 | - role: ipaclient 24 | state: present 25 | -------------------------------------------------------------------------------- /nameservers.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: configure nameservers 3 | hosts: ns 4 | gather_facts: true 5 | become: true 6 | 7 | vars_files: 8 | - ~/0/vault/proxmox.yml 9 | 10 | roles: 11 | - chronyclient 12 | - dhcpd 13 | - bind 14 | - repoclient 15 | -------------------------------------------------------------------------------- /osa-init.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: set up user ssh 3 | hosts: openstacknodes 4 | user: root 5 | become: true 6 | 7 | vars_files: 8 | - ~/0/vault/secrets.yml 9 | 10 | roles: 11 | - sshenableuser 12 | 13 | - name: init OpenStack Ansible hosts 14 | hosts: openstacknodes 15 | user: stack 16 | become: true 17 | 18 | vars_files: 19 | - ~/0/vault/secrets.yml 20 | 21 | roles: 22 | # - chronyserver 23 | - osapreparenode 24 | -------------------------------------------------------------------------------- /osa-networking.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: configure OpenStack Ansible networking 3 | hosts: openstacknodes 4 | user: stack 5 | become: true 6 | 7 | roles: 8 | - osapreparenetwork 9 | -------------------------------------------------------------------------------- /reposerver.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # - name: Prepare storage 3 | # hosts: bronze.lan.nathancurry.com 4 | # gather_facts: true 5 | # become: true 6 | # 7 | # roles: 8 | # - preparestorage 9 | 10 | # Allow container to reboot if necessary. 11 | # tasks: 12 | # - name: sleep 13 | # pause: 14 | # seconds: 15 15 | 16 | - name: Configure local repo server 17 | hosts: repo.lan.nathancurry.com 18 | gather_facts: true 19 | become: true 20 | 21 | roles: 22 | # - chronyclient 23 | - kickstart 24 | - reposerver 25 | - tftpserver 26 | -------------------------------------------------------------------------------- /rmipaserver.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Playbook to configure IPA servers 3 | hosts: ipaserver 4 | become: true 5 | vars_files: 6 | - ~/0/vault/secrets.yml 7 | 8 | roles: 9 | - role: ipaserver 10 | state: absent 11 | -------------------------------------------------------------------------------- /roles/bind/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for Bind setup 3 | - name: restart named 4 | service: 5 | name: named 6 | state: restarted 7 | -------------------------------------------------------------------------------- /roles/bind/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for Bind setup 3 | - name: Install bind 4 | yum: 5 | pkg: bind 6 | state: installed 7 | 8 | - name: Create logging directory 9 | file: 10 | path: '/var/log/named' 11 | owner: 'named' 12 | group: 'named' 13 | mode: '0700' 14 | state: 'directory' 15 | 16 | - name: Copy named conf file 17 | template: 18 | src: named.conf.j2 19 | dest: /etc/named.conf 20 | owner: root 21 | group: named 22 | mode: 0660 23 | notify: restart named 24 | 25 | - name: Make named directory 26 | file: 27 | path: /etc/named 28 | state: directory 29 | owner: root 30 | group: named 31 | mode: 0770 32 | 33 | - name: Copy conf local file 34 | template: 35 | src: named.conf.local.j2 36 | dest: /etc/named/named.conf.local 37 | owner: root 38 | group: named 39 | mode: 0640 40 | notify: restart named 41 | 42 | - name: Make zones Directory 43 | file: 44 | path: /etc/named/zones 45 | state: directory 46 | owner: root 47 | group: named 48 | mode: 0770 #named needs write permissions for zone updates 49 | 50 | - name: Copy forward file 51 | template: 52 | src: db.forward.j2 53 | dest: /etc/named/zones/db.{{ domain }} 54 | owner: root 55 | group: named 56 | mode: 0640 57 | notify: restart named 58 | 59 | - name: Copy reverse file 60 | template: 61 | src: db.reverse.j2 62 | dest: /etc/named/zones/db.{{ rev_domain }} 63 | owner: root 64 | group: named 65 | mode: 0640 66 | notify: restart named 67 | 68 | - name: install dns updater key 69 | template: 70 | src: rndc.key.j2 71 | dest: /etc/rndc.key 72 | owner: root 73 | group: named 74 | mode: 0640 75 | notify: restart named 76 | -------------------------------------------------------------------------------- /roles/bind/templates/db.forward.j2: -------------------------------------------------------------------------------- 1 | $ORIGIN . 2 | $TTL 604800 ; 1 week 3 | {{ domain }} IN SOA {{ ansible_fqdn }}. admin.{{ domain }}. ( 4 | 8 ; serial 5 | 604800 ; refresh (1 week) 6 | 86400 ; retry (1 day) 7 | 2419200 ; expire (4 weeks) 8 | 604800 ; minimum (1 week) 9 | ) 10 | NS {{ ansible_fqdn }}. 11 | {% for host in hostlist %} 12 | {{ host }} IN A {{ hostvars[host].ansible_host }} 13 | {% endfor %} 14 | -------------------------------------------------------------------------------- /roles/bind/templates/db.reverse.j2: -------------------------------------------------------------------------------- 1 | $ORIGIN . 2 | $TTL 604800 ; 1 week 3 | {{ rev_domain }} IN SOA {{ ansible_fqdn }}. admin.{{ domain }}. ( 4 | 7 ; serial 5 | 604800 ; refresh (1 week) 6 | 86400 ; retry (1 day) 7 | 2419200 ; expire (4 weeks) 8 | 604800 ; minimum (1 week) 9 | ) 10 | NS {{ ansible_fqdn }}. 11 | $ORIGIN {{ rev_domain }}. 12 | $TTL 604800 ; 1 week 13 | 14 | {% for host in hostlist %} 15 | {{ hostvars[host].ansible_host|regex_replace('10.3.3.') }} IN PTR {{ host }}. 16 | {% endfor %} 17 | -------------------------------------------------------------------------------- /roles/bind/templates/named.conf.j2: -------------------------------------------------------------------------------- 1 | // 2 | // named.conf 3 | // 4 | // Configured with Ansible 5 | // 6 | // See /usr/share/doc/bind*/sample/ for example named configuration files. 7 | // 8 | 9 | include "/etc/rndc.key"; 10 | 11 | acl "lan" { 12 | 127.0.0.0/8; 13 | 10.3.3.0/24; 14 | }; 15 | 16 | 17 | options { 18 | listen-on port 53 { 127.0.0.1; {{ ansible_eth0.ipv4.address }}; }; 19 | # listen-on-v6 port 53 { ::1; }; 20 | directory "/var/named"; 21 | dump-file "/var/named/data/cache_dump.db"; 22 | statistics-file "/var/named/data/named_stats.txt"; 23 | memstatistics-file "/var/named/data/named_mem_stats.txt"; 24 | 25 | # Disable built-in server information zones 26 | version none; 27 | hostname none; 28 | server-id none; 29 | 30 | 31 | recursion yes; 32 | allow-recursion{ lan; }; 33 | allow-query { lan; }; 34 | {% if inventory_hostname in groups['nsmasters'] %} 35 | allow-transfer { localhost; 10.3.3.3; }; 36 | {% else %} 37 | allow-transfer { none; }; 38 | {% endif %} 39 | 40 | dnssec-enable yes; 41 | dnssec-validation yes; 42 | 43 | forwarders { 44 | 75.75.75.75; 45 | 8.8.8.8; 46 | }; 47 | 48 | /* Path to ISC DLV key */ 49 | bindkeys-file "/etc/named.iscdlv.key"; 50 | managed-keys-directory "/var/named/dynamic"; 51 | pid-file "/run/named/named.pid"; 52 | session-keyfile "/run/named/session.key"; 53 | }; 54 | 55 | logging { 56 | channel "common_log" { 57 | file "/var/log/named/named.log" versions 10 size 5m; 58 | severity dynamic; 59 | print-category yes; 60 | print-severity yes; 61 | print-time yes; 62 | }; 63 | category default { "common_log"; }; 64 | category general { "common_log"; }; 65 | category queries { "common_log"; }; 66 | category client { "common_log"; }; 67 | category security { "common_log"; }; 68 | category query-errors { "common_log"; }; 69 | category lame-servers { null; }; 70 | channel update_log { 71 | file "/var/log/named/update.log"; 72 | severity info; 73 | print-time yes; 74 | }; 75 | category update { update_log; }; 76 | }; 77 | 78 | 79 | zone "." IN { 80 | type hint; 81 | file "named.ca"; 82 | }; 83 | 84 | include "/etc/named/named.conf.local"; 85 | -------------------------------------------------------------------------------- /roles/bind/templates/named.conf.local.j2: -------------------------------------------------------------------------------- 1 | {% if inventory_hostname in groups['nsmasters'] %} 2 | zone "{{ domain }}" IN { 3 | type master; 4 | file "/etc/named/zones/db.{{ domain }}"; 5 | allow-update { key rndc-key; }; 6 | # notify yes; 7 | }; 8 | 9 | zone "{{ rev_domain }}" IN { 10 | type master; 11 | file "/etc/named/zones/db.{{ rev_domain }}"; 12 | allow-update {key rndc-key; }; 13 | # notify yes; 14 | }; 15 | {% else %} 16 | zone "{{ domain }}" IN { 17 | type slave; 18 | file "/etc/named/zones/db.{{ domain }}"; 19 | masters { 10.3.3.3; }; 20 | # allow-notify { 10.3.3.3; }; 21 | }; 22 | 23 | zone "{{ rev_domain }}" IN { 24 | type slave; 25 | file "/etc/named/zones/db.{{ domain }}"; 26 | masters { 10.3.3.3; }; 27 | # allow-notify { 10.3.3.3; }; 28 | }; 29 | {% endif %} 30 | 31 | controls { 32 | inet 127.0.0.1 port 953 33 | allow { 127.0.0.1; } keys { "rndc-key"; }; 34 | }; 35 | -------------------------------------------------------------------------------- /roles/bind/templates/rndc.key.j2: -------------------------------------------------------------------------------- 1 | key "rndc-key" { 2 | algorithm hmac-md5; 3 | secret "{{ rndc_key }}"; 4 | }; 5 | -------------------------------------------------------------------------------- /roles/bind/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for Bind setup 3 | domain: lan.nathancurry.com 4 | rev_domain: 3.3.10.in-addr.arpa 5 | 6 | hostlist: "{{ groups['all'] }}" 7 | 8 | # set_fact: 9 | # records: "{{ records|default([]) + [ 10 | # hostname': item, 11 | # forward': hostvars[item].ansible_host 12 | # type: 'A'] 13 | # last': hostvars[item].ansible_host|regex_replace('10.3.3.') 14 | # rev': '3.3.10.in-addr.arpa. 15 | # with_items: "{{ groups['all'] }}" 16 | -------------------------------------------------------------------------------- /roles/chronyclient/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for chrony setup 3 | - name: restart crond 4 | service: 5 | name: crond 6 | state: restarted 7 | 8 | - name: restart chronyd 9 | service: 10 | name: chronyd 11 | state: restarted 12 | -------------------------------------------------------------------------------- /roles/chronyclient/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Include secrets 3 | include_vars: ~/0/vault/secrets.yml 4 | 5 | - name: Set timezone to America/Denver 6 | timezone: 7 | name: America/Denver 8 | notify: restart crond 9 | 10 | - name: ensure ntpdate isn't installed 11 | package: 12 | name: 'ntpdate' 13 | state: absent 14 | 15 | - name: Mask NTP service 16 | systemd: 17 | name: ntpd 18 | enabled: no 19 | masked: yes 20 | state: stopped 21 | ignore_errors: yes 22 | 23 | - name: install chrony 24 | package: 25 | name: 'chrony' 26 | state: present 27 | 28 | - name: Ensure chronyd is active 29 | service: 30 | name: chronyd 31 | state: started 32 | 33 | - name: install chrony.conf 34 | template: 35 | src: ../templates/chrony.conf.j2 36 | dest: /etc/chrony.conf 37 | owner: root 38 | group: root 39 | mode: 0644 40 | notify: restart chronyd 41 | 42 | - name: install chrony.keys 43 | template: 44 | src: ../templates/chrony.keys.j2 45 | dest: /etc/chrony.keys 46 | owner: root 47 | group: chrony 48 | mode: 0640 49 | notify: restart chronyd 50 | -------------------------------------------------------------------------------- /roles/chronyclient/templates/chrony.conf.j2: -------------------------------------------------------------------------------- 1 | # Use public servers from the pool.ntp.org project. 2 | # Please consider joining the pool (http://www.pool.ntp.org/join.html). 3 | {% for host in groups['hypervisors'] %} 4 | server {{ hostvars[host].ansible_host }} iburst xleave 5 | {% endfor %} 6 | 7 | # Record the rate at which the system clock gains/losses time. 8 | driftfile /var/lib/chrony/drift 9 | 10 | # Allow the system clock to be stepped in the first three updates 11 | # if its offset is larger than 1 second. 12 | makestep 1.0 3 13 | 14 | # Specify file containing keys for NTP authentication. 15 | keyfile /etc/chrony.keys 16 | 17 | # Specify directory for log files. 18 | logdir /var/log/chrony 19 | 20 | # Select which information is logged. 21 | #log measurements statistics tracking 22 | -------------------------------------------------------------------------------- /roles/chronyclient/templates/chrony.keys.j2: -------------------------------------------------------------------------------- 1 | {{ chrony_key }} 2 | -------------------------------------------------------------------------------- /roles/chronyclient/vars/main.yml: -------------------------------------------------------------------------------- 1 | network: "10.3.3.0/24" 2 | -------------------------------------------------------------------------------- /roles/chronyserver/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for chrony setup 3 | - name: restart crond 4 | service: 5 | name: crond 6 | state: restarted 7 | 8 | - name: restart chronyd 9 | service: 10 | name: chronyd 11 | state: restarted 12 | -------------------------------------------------------------------------------- /roles/chronyserver/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Include secrets 3 | include_vars: ~/0/vault/secrets.yml 4 | 5 | - name: Set timezone to America/Denver 6 | timezone: 7 | name: America/Denver 8 | notify: restart crond 9 | 10 | - name: ensure ntpdate isn't installed 11 | package: 12 | name: 'ntpdate' 13 | state: absent 14 | 15 | - name: install chrony 16 | package: 17 | name: chrony 18 | state: present 19 | 20 | - name: Mask NTP service 21 | systemd: 22 | name: ntpd 23 | enabled: no 24 | masked: yes 25 | state: stopped 26 | ignore_errors: yes 27 | 28 | - name: Ensure chronyd is active 29 | service: 30 | name: chronyd 31 | state: started 32 | 33 | # timeservers, CentOS 34 | 35 | - name: install chrony.conf 36 | template: 37 | src: chrony-server.conf.j2 38 | dest: /etc/chrony.conf 39 | owner: root 40 | group: root 41 | mode: 0644 42 | notify: restart chronyd 43 | 44 | - name: install chrony.keys 45 | template: 46 | src: chrony.keys.j2 47 | dest: /etc/chrony.keys 48 | owner: root 49 | group: root 50 | mode: 0640 51 | notify: restart chronyd 52 | -------------------------------------------------------------------------------- /roles/chronyserver/templates/chrony-server.conf.j2: -------------------------------------------------------------------------------- 1 | # Use public servers from the pool.ntp.org project. 2 | # Please consider joining the pool (http://www.pool.ntp.org/join.html). 3 | server 0.debian.pool.ntp.org iburst xleave 4 | server 1.debian.pool.ntp.org iburst xleave 5 | server 2.debian.pool.ntp.org iburst xleave 6 | {% for host in groups['timeservers'] | difference([inventory_hostname]) %} 7 | peer {{ hostvars[host].ansible_host }} iburst xleave 8 | {% endfor %} 9 | 10 | # Record the rate at which the system clock gains/losses time. 11 | driftfile /var/lib/chrony/drift 12 | 13 | # Allow the system clock to be stepped in the first three updates 14 | # if its offset is larger than 1 second. 15 | makestep 1.0 3 16 | 17 | # Enable kernel synchronization of the real-time clock (RTC). 18 | rtcsync 19 | 20 | # Enable hardware timestamping on all interfaces that support it. 21 | hwtimestamp * 22 | 23 | # Increase the minimum number of selectable sources required to adjust 24 | # the system clock. 25 | #minsources 2 26 | 27 | # Allow NTP client access from local network. 28 | allow {{ network }} 29 | allow fe80::/64 30 | 31 | # Serve time even if not synchronized to a time source. 32 | local stratum 10 33 | 34 | # Specify file containing keys for NTP authentication. 35 | keyfile /etc/chrony/chrony.keys 36 | 37 | # Specify directory for log files. 38 | logdir /var/log/chrony 39 | 40 | # Select which information is logged. 41 | #log measurements statistics tracking 42 | -------------------------------------------------------------------------------- /roles/chronyserver/templates/chrony.keys.j2: -------------------------------------------------------------------------------- 1 | {{ chrony_key }} 2 | -------------------------------------------------------------------------------- /roles/chronyserver/vars/main.yml: -------------------------------------------------------------------------------- 1 | network: "10.3.3.0/24" 2 | -------------------------------------------------------------------------------- /roles/deployvms/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: 'sleep' 3 | pause: 4 | seconds: 5 5 | -------------------------------------------------------------------------------- /roles/deployvms/tasks/deploy_containers.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Load relevant secrets 3 | include_vars: "~/0/vault/proxmox.yml" 4 | no_log: false 5 | 6 | - name: 'include vars' 7 | include_vars: '../vars/main.yml' 8 | 9 | - name: 'create containers' 10 | proxmox: 11 | password: '{{ root_password }}' 12 | vmid: '{{ hostvars[item].vmid | default([])}}' 13 | api_user: "{{ api_user }}" 14 | api_password: "{{ api_password }}" 15 | api_host: "{{ api_host }}" 16 | hostname: '{{ hostvars[item].inventory_hostname }}' 17 | node: '{{ hostvars[item].proxmox_node }}' 18 | cores: '{{ hostvars[item].cores | default(defaults.cores) }}' 19 | cpus: '{{ hostvars[item].cpus | default(defaults.cpus) }}' 20 | netif: "{{ '{\"net0\":\"name=eth0,type=veth,bridge=vmbr0,ip6=auto,gw=10.3.3.1,hwaddr=' + hostvars[item].mac_address + ',ip=' + hostvars[item].ansible_host + '/25\"}' | default(defaults.netif) }}" 21 | memory: '{{ hostvars[item].memory | default(defaults.memory.ct) }}' 22 | swap: '{{ hostvars[item].swap | default(defaults.swap.ct) }}' 23 | disk: '{{ hostvars[item].disk | default(defaults.disk.ct) }}' 24 | storage: '{{ hostvars[item].storage | default(defaults.storage.lvm) }}' 25 | onboot: '{{ hostvars[item].onboot | default(defaults.onboot) }}' 26 | pubkey: '{{ id_ed25519_pub }}' 27 | searchdomain: '{{ hostvars[item].searchdomain | default(defaults.searchdomain) }}' 28 | nameserver: '{{ hostvars[item].nameserver | default(defaults.nameserver) }}' 29 | ostemplate: '{{ ostemplate }}' 30 | state: 'present' 31 | with_items: "{{ deploy_cts }}" 32 | loop_control: 33 | pause: 5 34 | notify: 35 | - 'sleep' 36 | register: 'created_cts_pve' 37 | 38 | 39 | - meta: 'flush_handlers' 40 | when: 'created_cts_pve.changed' 41 | 42 | - name: 'start containers' 43 | proxmox: 44 | api_user: "{{ api_user }}" 45 | api_password: "{{ api_password }}" 46 | api_host: "{{ api_host }}" 47 | node: "{{ item['invocation']['module_args']['node'] }}" 48 | hostname: "{{ item['item'] }}" 49 | state: 'started' 50 | with_items: "{{ created_cts_pve.results }}" 51 | notify: 52 | - 'sleep' 53 | #when: 'item.changed' 54 | 55 | - meta: 'flush_handlers' 56 | when: 'created_cts_pve.changed' 57 | -------------------------------------------------------------------------------- /roles/deployvms/tasks/deploy_vms.yml: -------------------------------------------------------------------------------- 1 | - name: Load relevant secrets 2 | include_vars: "~/0/vault/proxmox.yml" 3 | no_log: false 4 | 5 | 6 | - name: 'create vms' 7 | proxmox_kvm: 8 | api_user: "{{ api_user }}" 9 | api_password: "{{ api_password }}" 10 | api_host: "{{ api_host }}" 11 | vmid: '{{ hostvars[item].vmid }}' 12 | node: '{{ hostvars[item].proxmox_node }}' 13 | name: '{{ hostvars[item].inventory_hostname }}' 14 | cores: '{{ hostvars[item].cores | default(defaults.cores) }}' 15 | net: "{{ '{\"net0\":\"virtio=' + hostvars[item].mac_address + ',bridge=vmbr0\"}' | default(defaults.netif) }}" 16 | virtio: '{{ hostvars[item].virtio | default(defaults.virtio) }}' 17 | vga: 'qxl' 18 | memory: '{{ hostvars[item].memory | default(defaults.memory.vm) }}' 19 | storage: '{{ hostvars[item].storage | default(defaults.storage.gluster) }}' 20 | onboot: '{{ hostvars[item].onboot | default(defaults.onboot) }}' 21 | #args: '-device virtio-rng-pci,id=rng0,bus=pci.0,addr=0x17' 22 | state: 'present' 23 | when: hostvars[item].mac_address is defined 24 | with_items: "{{ deploy_vms }}" 25 | loop_control: 26 | pause: 5 27 | notify: 28 | - 'sleep' 29 | register: 'created_vms_pve' 30 | 31 | 32 | - meta: 'flush_handlers' 33 | when: 'created_vms_pve.changed' 34 | 35 | - name: 'start VMs' 36 | proxmox_kvm: 37 | api_user: "{{ api_user }}" 38 | api_password: "{{ api_password }}" 39 | api_host: "{{ api_host }}" 40 | node: "{{ item['invocation']['module_args']['node'] }}" 41 | name: "{{ item['item'] }}" 42 | state: 'started' 43 | with_items: "{{ created_vms_pve.results }}" 44 | notify: 45 | - 'sleep' 46 | #when: 'item.changed' 47 | 48 | 49 | - meta: 'flush_handlers' 50 | when: 'created_vms_pve.changed' 51 | -------------------------------------------------------------------------------- /roles/deployvms/tasks/install_pip.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: 'prep proxmox hosts for automation' 4 | hosts: 'proxmox' 5 | gather_facts: false 6 | vars: 7 | packages: 8 | - 'python-pip' 9 | - 'python-dev' 10 | - 'build-essential' 11 | 12 | tasks: 13 | - name: 'install python-apt so native apt plugins work' 14 | package: 15 | name: 'python-apt' 16 | state: 'present' 17 | - name: 'switch to community repos' 18 | apt_repository: 19 | repo: 'deb https://enterprise.proxmox.com/debian/pve stretch pve-enterprise' 20 | state: 'absent' 21 | apt_repository: 22 | repo: 'deb http://download.proxmox.com/debian/pve stretch pve-no-subscription' 23 | state: 'present' 24 | - name: 'Update all packages to the latest version' 25 | apt: 26 | upgrade: 'dist' 27 | - name: 'Install pip packages' 28 | apt: 29 | name: "{{ packages }}" 30 | - name: 'pip update pip' 31 | pip: 32 | name: 'pip' 33 | state: 'latest' 34 | - name: 'Install dependencies' 35 | pip: 36 | name: 'virtualenv' 37 | state: 'latest' 38 | pip: 39 | name: 'proxmoxer' 40 | state: 'latest' 41 | -------------------------------------------------------------------------------- /roles/deployvms/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - import_tasks: deploy_vms.yml 3 | #- import_tasks: deploy_containers.yml 4 | -------------------------------------------------------------------------------- /roles/deployvms/templates/deploy-args-centos.j2: -------------------------------------------------------------------------------- 1 | {% include 'kernel.j2' %} 2 | -append "inst.stage2={{ hostvars[item].value.stage2 | default(deployments[hostvars[item].value.type].stage2) }} 3 | inst.repo={{ hostvars[item].value.repo | default(deployments[item.value.type].repo) }} 4 | inst.ks={{ item.value.ks | default(deployments[item.value.type].ks) }} 5 | rd.noverifyssl net_cfg=#network --device=link --bootproto= 6 | {% if item.value.network is defined %} 7 | {% if ( item.value.network.ip is defined and item.value.network.netmask is defined ) %}static 8 | --ip={{ item.value.network.ip}} --netmask={{ item.value.network.netmask }} 9 | {% if item.value.network.gateway is defined %} 10 | --gateway={{ item.value.network.gateway }} 11 | {% endif %} 12 | {% if item.value.network.nameserver is defined %} 13 | --nameserver={{ item.value.network.nameserver }} 14 | {% endif %} 15 | {% endif %} 16 | {% else %} 17 | dhcp 18 | {% endif %} 19 | --noipv6 20 | --onboot yes 21 | --hostname={{ item.key }}#" 22 | -------------------------------------------------------------------------------- /roles/deployvms/templates/deploy-args-ubuntu.j2: -------------------------------------------------------------------------------- 1 | {% include 'kernel.j2' %} 2 | -append "preseed/url={{ item.value.preseed | default(deployments[item.value.type].preseed) }} 3 | debian-installer/allow_unauthenticated_ssl=true 4 | locale=de_DE.UTF-8 5 | debian/priority=critical 6 | vga=normal debian-installer/keymap=de 7 | console-keymaps-at/keymap=de 8 | console-setup/layoutcode=de_DE 9 | netcfg/choose_interface=auto 10 | localechooser/translation/warn-light=true 11 | localechooser/translation/warn-severe=true 12 | console-setup/ask_detect=false 13 | netcfg/get_hostname={{ item.key }} 14 | {% if item.value.network is defined %} 15 | {% if item.value.network.domainname is defined %} 16 | netcfg/get_domain={{ item.value.network.domainname }} 17 | {% endif %} 18 | {% if ( item.value.network.ip is defined and item.value.network.netmask is defined ) %} 19 | netcfg/confirm_static=true 20 | netcfg/disable_dhcp=true 21 | netcfg/get_ipaddress={{ item.value.network.ip }} 22 | netcfg/get_netmask={{ item.value.network.netmask }} 23 | {% if item.value.network.gateway is defined %} 24 | netcfg/get_gateway={{ item.value.network.gateway }} 25 | {% endif %} 26 | {% if item.value.network.nameserver is defined %} 27 | netcfg/get_nameservers={{ item.value.network.nameserver }} 28 | {% endif %} 29 | {% endif %} 30 | {% else %} 31 | netcfg/get_domain=localdomain 32 | {% endif %} 33 | FRONTEND_BACKGROUND=original" 34 | -------------------------------------------------------------------------------- /roles/deployvms/templates/kernel.j2: -------------------------------------------------------------------------------- 1 | -kernel /tmp/{{ item.value.type }}-{{ deployments[item.value.type].kernel | basename }} 2 | -initrd /tmp/{{ item.value.type }}-{{ deployments[item.value.type].initrd | basename }} 3 | -------------------------------------------------------------------------------- /roles/deployvms/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # proxmox and proxmox_kvm options 3 | api_user: 'root@pam' 4 | #api_password: 'vault' 5 | api_host: 'gold' 6 | 7 | deploy_vms: "{{ groups['ipaserver'] }}" 8 | deploy_cts: "{{ groups['none'] }}" 9 | 10 | 11 | ostemplate: 'gluster:vztmpl/centos-7-ssh-sudo_20180909.tar.gz' 12 | proxmox_node: 'gold' 13 | tftp_server: 'repo.lan.nathancurry.com' 14 | 15 | defaults: 16 | balloon: '1024' 17 | cores: '1' 18 | cpus: '1' 19 | disk: 20 | ct: '2' 21 | vm: '10' 22 | format: 'qcow2' 23 | memory: 24 | ct: '1024' 25 | vm: '2048' 26 | nameserver: '10.3.3.2' 27 | net: '{"net0":"virtio,bridge=vmbr0"}' 28 | netif: '{"net0":"name=eth0,ip=dhcp,ip6=dhcp,bridge=vmbr0"}' 29 | node: 'gold' 30 | onboot: true 31 | ostype: 'l26' 32 | pubkey: '' 33 | scsihw: 'virtio-scsi-pci' 34 | searchdomain: 'lan.nathancurry.com' 35 | storage: 36 | gluster: 'gluster' 37 | lvm: 'local-lvm' 38 | swap: 39 | ct: '0' 40 | vm: '4' 41 | type: centos 42 | virtio: '{"virtio0":"gluster:10,cache=none,discard=on,format=qcow2"}' 43 | -------------------------------------------------------------------------------- /roles/dhcpd/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for DHCP setup 3 | 4 | - name: restart dhcpd 5 | service: 6 | name: dhcpd 7 | state: restarted 8 | -------------------------------------------------------------------------------- /roles/dhcpd/tasks/main.yml: -------------------------------------------------------------------------------- 1 | # roles/dhcp/tasks/main.yml 2 | --- 3 | 4 | - name: Install packages 5 | package: 6 | pkg: "dhcp" 7 | state: "present" 8 | 9 | - name: Set config directory perms 10 | file: 11 | path: "/etc/dhcp" 12 | state: directory 13 | mode: 0750 14 | 15 | - name: install dns updater key 16 | template: 17 | src: rndc.key.j2 18 | dest: /etc/dhcp/rndc.key 19 | owner: root 20 | group: dhcpd 21 | mode: 0640 22 | notify: restart dhcpd 23 | 24 | - name: install dhcp failover key 25 | template: 26 | src: omapi.key.j2 27 | dest: /etc/dhcp/omapi.key 28 | owner: root 29 | group: dhcpd 30 | mode: 0640 31 | notify: restart dhcpd 32 | 33 | - name: Install config file 34 | template: 35 | src: dhcpd.conf.j2 36 | dest: /etc/dhcp/dhcpd.conf 37 | owner: root 38 | group: root 39 | mode: 0640 40 | force: yes 41 | notify: restart dhcpd 42 | 43 | - name: Ensure service is started 44 | service: 45 | name: "dhcpd" 46 | state: started 47 | enabled: true 48 | -------------------------------------------------------------------------------- /roles/dhcpd/templates/dhcpd.conf.j2: -------------------------------------------------------------------------------- 1 | failover peer "failover-dhcp" { 2 | {% if ansible_hostname in groups['nsmasters'] %} 3 | primary; 4 | address {{ hostvars['ns1.lan.nathancurry.com'].ansible_host }}; 5 | peer address {{ hostvars['ns2.lan.nathancurry.com'].ansible_host }}; 6 | mclt 3600; 7 | split 128; 8 | {% else %} 9 | secondary; 10 | address {{ hostvars['ns2.lan.nathancurry.com'].ansible_host }}; 11 | peer address {{ hostvars['ns1.lan.nathancurry.com'].ansible_host }}; 12 | {% endif %} 13 | port 647; 14 | peer port 647; 15 | max-response-delay 30; 16 | max-unacked-updates 10; 17 | load balance max seconds 3; 18 | } 19 | 20 | omapi-port 7911; 21 | omapi-key omapi_key; 22 | 23 | # Failover key 24 | include "/etc/dhcp/omapi.key"; 25 | 26 | # DNS update key 27 | include "/etc/dhcp/rndc.key"; 28 | 29 | 30 | authoritative; 31 | allow booting; 32 | allow bootp; 33 | next-server 10.3.3.45; 34 | filename "pxelinux.0"; 35 | default-lease-time 43000; 36 | max-lease-time 43000; # about 12hrs 37 | 38 | ddns-updates on; 39 | ddns-update-style interim; 40 | allow unknown-clients; 41 | update-static-leases on; 42 | use-host-decl-names on; 43 | 44 | update-static-leases on; 45 | 46 | option domain-name "{{ search_domain }}"; 47 | 48 | 49 | 50 | 51 | # DNS Zones 52 | zone {{ reverse_zone }}{ 53 | primary {{ hostvars['ns1.lan.nathancurry.com'].ansible_host }}; 54 | key "rndc-key"; 55 | } 56 | zone {{ search_domain }} { 57 | primary {{ hostvars['ns1.lan.nathancurry.com'].ansible_host }}; 58 | key "rndc-key"; 59 | } 60 | 61 | subnet {{ dhcp_subnet }} netmask {{ dhcp_netmask }} { 62 | option subnet-mask {{ dhcp_netmask }}; 63 | option broadcast-address 10.3.3.127; 64 | option routers {{ dhcp_routers }}; 65 | option domain-name-servers {{ dhcp_ns1 }}, {{ dhcp_ns2 }}; 66 | option domain-search "{{ search_domain }}"; 67 | pool { 68 | failover peer "failover-dhcp"; 69 | range {{ dhcp_begin }} {{dhcp_end }}; 70 | } 71 | } 72 | 73 | # Ansible-generated DHCP hosts. 74 | 75 | {% if dhcp_hosts is defined %} 76 | {% for host in dhcp_hosts %} 77 | host {{ host }} { 78 | {% if hostvars[host].mac_address is defined %} 79 | hardware ethernet {{ hostvars[host].mac_address }}; 80 | {% endif %} 81 | {% if hostvars[host].ansible_host is defined %} 82 | fixed-address {{ hostvars[host].ansible_host }}; 83 | {% endif %} 84 | } 85 | 86 | {% endfor %} 87 | {% endif %} 88 | -------------------------------------------------------------------------------- /roles/dhcpd/templates/omapi.key.j2: -------------------------------------------------------------------------------- 1 | key omapi_key { 2 | algorithm hmac-md5; 3 | secret {{ omapi_key }}; 4 | } 5 | -------------------------------------------------------------------------------- /roles/dhcpd/templates/rndc.key.j2: -------------------------------------------------------------------------------- 1 | key "rndc-key" { 2 | algorithm hmac-md5; 3 | secret "{{ rndc_key }}"; 4 | }; 5 | -------------------------------------------------------------------------------- /roles/dhcpd/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | search_domain: 'lan.nathancurry.com' 3 | forward_zone: 'lan.nathancurry.com.' 4 | reverse_zone: '3.3.10.in-addr.arpa.' 5 | 6 | # DHCP subnet variables 7 | dhcp_subnet: 10.3.3.0 8 | dhcp_netmask: 255.255.255.128 9 | dhcp_ns1: "{{ hostvars['ns1.lan.nathancurry.com'].ansible_host }}" 10 | dhcp_ns2: "{{ hostvars['ns2.lan.nathancurry.com'].ansible_host }}" 11 | dhcp_routers: 10.3.3.1 12 | dhcp_begin: 10.3.3.80 13 | dhcp_end: 10.3.3.127 14 | 15 | # rndc_key: 16 | # DNS update key, generated with `rndc-confgen -a -b 512 -r /dev/urandom` 17 | # stored in ansible vault 18 | # omapi_key: 19 | # DHCP failover key, generated with `dnssec-keygen -a HMAC-MD5 -b 512 -n USER DHCP_OMAPI ` 20 | # stored in ansible vault 21 | 22 | # Static hosts list 23 | dhcp_hosts: "{{ groups['all']}}" 24 | -------------------------------------------------------------------------------- /roles/ipa-krb5/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | krb5_packages: krb5-workstation 3 | krb5_conf: /etc/krb5.conf 4 | krb5_conf_d: /etc/krb5.conf.d/ # paths.COMMON_KRB5_CONF_DIR 5 | krb5_include_d: /var/lib/sss/pubconf/krb5.include.d/ # paths.SSSD_PUBCONF_KRB5_INCLUDE_D_DIR 6 | 7 | krb5_realm: 8 | krb5_servers: 9 | krb5_dns_lookup_realm: "false" 10 | krb5_dns_lookup_kdc: "false" 11 | krb5_no_default_domain: "false" 12 | krb5_default_ccache_name: KEYRING:persistent:%{uid} 13 | -------------------------------------------------------------------------------- /roles/ipa-krb5/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: Thomas Woerner 3 | description: A role to configure krb5 4 | company: Red Hat, Inc 5 | 6 | license: GPLv3 7 | 8 | min_ansible_version: 2.0 9 | 10 | galaxy_tags: [ 'identity', 'ipa'] 11 | 12 | dependencies: [] 13 | -------------------------------------------------------------------------------- /roles/ipa-krb5/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install {{ krb5_packages }} 3 | package: name="{{ item }}" state=present 4 | with_items: "{{ krb5_packages }}" 5 | 6 | - name: Install - Create ipabkp of krb5.conf 7 | copy: src="{{ krb5_conf }}" dest="{{ krb5_conf }}".ipabkp 8 | failed_when: false 9 | 10 | - name: Install - Backup krb5.conf 11 | ipafstore: 12 | backup: "{{ krb5_conf }}" 13 | 14 | - name: Template krb5.conf 15 | template: 16 | src: krb5.conf.j2 17 | dest: "{{ krb5_conf }}" 18 | backup: no 19 | owner: root 20 | group: root 21 | mode: 0644 22 | force: yes 23 | -------------------------------------------------------------------------------- /roles/ipa-krb5/templates/krb5.conf.j2: -------------------------------------------------------------------------------- 1 | includedir {{ krb5_conf_d }} 2 | includedir {{ krb5_include_d }} 3 | 4 | [libdefaults] 5 | default_realm = {{ krb5_realm | upper }} 6 | dns_lookup_realm = {{ krb5_dns_lookup_realm }} 7 | dns_lookup_kdc = {{ krb5_dns_lookup_kdc }} 8 | rdns = false 9 | {% if krb5_dns_canonicalize_hostname is defined %} 10 | dns_canonicalize_hostname = {{ krb5_dns_canonicalize_hostname }} 11 | {% endif %} 12 | ticket_lifetime = 24h 13 | forwardable = true 14 | udp_preference_limit = 0 15 | default_ccache_name = {{ krb5_default_ccache_name }} 16 | 17 | [realms] 18 | {{ krb5_realm | upper }} = { 19 | {% for server in krb5_servers %} 20 | kdc = {{ server }}:88 21 | master_kdc = {{ server }}:88 22 | admin_server = {{ server }}:749 23 | kpasswd_server = {{ server }}:464 24 | {% endfor %} 25 | {% if krb5_default_domain | bool %} 26 | default_domain = {{ krb5_realm | lower }} 27 | {% endif %} 28 | {% if krb5_pkinit_anchors is defined %} 29 | pkinit_anchors = {{ krb5_pkinit_anchors }} 30 | {% endif %} 31 | {% if krb5_pkinit_pool is defined %} 32 | pkinit_pool = {{ krb5_pkinit_pool }} 33 | {% endif %} 34 | } 35 | 36 | [domain_realm] 37 | .{{ krb5_realm | lower }} = {{ krb5_realm | upper }} 38 | {{ krb5_realm | lower }} = {{ krb5_realm | upper }} 39 | {{ ansible_host | lower }} = {{ krb5_realm | upper }} 40 | -------------------------------------------------------------------------------- /roles/ipa-krb5/vars/default.yml: -------------------------------------------------------------------------------- 1 | krb5_packages: 2 | - krb5-workstation 3 | -------------------------------------------------------------------------------- /roles/ipa-sssd/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | sssd_conf: /etc/sssd/sssd.conf 3 | sssd_packages: sssd, libselinux-python 4 | sssd_on_master: "false" 5 | sssd_domains: 6 | sssd_id_provider: 7 | sssd_auth_provider: 8 | sssd_access_provider: 9 | sssd_chpass_provider: 10 | sssd_cache_credentials: False 11 | sssd_krb5_offline_passwords: False 12 | sssd_ipa_servers: 13 | sssd_services: 14 | -------------------------------------------------------------------------------- /roles/ipa-sssd/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: Thomas Woerner 3 | description: A role to configure sssd for IPA 4 | company: Red Hat, Inc 5 | 6 | license: GPLv3 7 | 8 | min_ansible_version: 2.0 9 | 10 | galaxy_tags: [ 'identity', 'ipa'] 11 | 12 | dependencies: [] 13 | -------------------------------------------------------------------------------- /roles/ipa-sssd/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install {{ sssd_packages }} 3 | package: name="{{ item }}" state=present 4 | with_items: "{{ sssd_packages }}" 5 | 6 | # No backup in ipa-client-install mode 7 | #- name: Backup {{ sssd_conf }} 8 | # copy: 9 | # src: "{{ sssd_conf }}" 10 | # dest: "{{ sssd_conf }}.bkp" 11 | # force: no 12 | 13 | - name: Template sssd.conf 14 | template: 15 | src: sssd.conf.j2 16 | dest: "{{ sssd_conf }}" 17 | backup: no 18 | owner: root 19 | group: root 20 | mode: 0600 21 | force: yes 22 | 23 | #- name: Enable and start sssd 24 | # service: 25 | # name: sssd 26 | # state: restarted 27 | # enabled: yes 28 | -------------------------------------------------------------------------------- /roles/ipa-sssd/templates/sssd.conf.j2: -------------------------------------------------------------------------------- 1 | [domain/{{ sssd_domains }}] 2 | cache_credentials = {{ sssd_cache_credentials }} 3 | krb5_store_password_if_offline = {{ sssd_krb5_offline_passwords }} 4 | ipa_domain = {{ sssd_domains }} 5 | id_provider = {{ sssd_id_provider }} 6 | auth_provider = {{ sssd_auth_provider }} 7 | access_provider = {{ sssd_access_provider }} 8 | ipa_hostname = {{ ansible_host }} 9 | chpass_provider = {{ sssd_chpass_provider }} 10 | {% if sssd_on_master | bool %} 11 | ipa_server = {{ sssd_ipa_servers | join(", ") }} 12 | ipa_server_mode = True 13 | {% else %} 14 | {% if sssd_domains != ansible_domain %} 15 | dns_discovery_domain = sssd_domains 16 | {% endif %} 17 | ipa_server = _srv_, {{ sssd_ipa_servers | join(", ")}} 18 | {% endif %} 19 | ldap_tls_cacert = /etc/ipa/ca.crt 20 | 21 | {% if sssd_on_master | bool %} 22 | {% set sssd_services = sssd_services + ", ifp" %} 23 | {% endif %} 24 | [sssd] 25 | services = {{ sssd_services }} 26 | domains = {{ sssd_domains }} 27 | 28 | {% for service in sssd_services.split(',') %} 29 | [{{ service | trim }}] 30 | {% if service | trim == "nss" %} 31 | homedir_substring = /home 32 | {% endif %} 33 | 34 | {% endfor %} 35 | -------------------------------------------------------------------------------- /roles/ipa-sssd/vars/default.yml: -------------------------------------------------------------------------------- 1 | sssd_packages: 2 | - sssd 3 | - sssd-ipa 4 | - sssd-krb5 5 | -------------------------------------------------------------------------------- /roles/ipaclient/action_plugins/ipahost.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathancurry/homelab.ansible/fba05a5e8931fc3982dcb1bb4143e73bef888080/roles/ipaclient/action_plugins/ipahost.pyc -------------------------------------------------------------------------------- /roles/ipaclient/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for ipaclient 3 | 4 | ipaclient_force_join: no 5 | ipaclient_ntp: no 6 | ipaclient_mkhomedir: no 7 | ipaclient_kinit_attempts: 5 8 | ipaclient_use_otp: no 9 | ipaclient_allow_repair: no 10 | ipaclient_on_master: no 11 | ipaclient_no_ntp: no 12 | ipaclient_no_dns_lookup: no 13 | ipaclient_ssh_trust_dns: no 14 | -------------------------------------------------------------------------------- /roles/ipaclient/files/py3test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # Test ipaclient python3 binding 4 | from ipaclient.install.client import SECURE_PATH 5 | 6 | # Check ipapython version to be >= 4.6 7 | from ipapython.version import NUM_VERSION, VERSION 8 | if NUM_VERSION < 40600: 9 | raise Exception("ipa %s not usable with python3" % VERSION) 10 | -------------------------------------------------------------------------------- /roles/ipaclient/library/ipa_facts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import re 6 | import six 7 | from six.moves.configparser import RawConfigParser 8 | 9 | from ansible.module_utils.basic import AnsibleModule 10 | 11 | try: 12 | from ipalib import api 13 | except ImportError: 14 | HAS_IPALIB = False 15 | else: 16 | HAS_IPALIB = True 17 | from ipaplatform.paths import paths 18 | try: 19 | # FreeIPA >= 4.5 20 | from ipalib.install import sysrestore 21 | except ImportError: 22 | # FreeIPA 4.4 and older 23 | from ipapython import sysrestore 24 | 25 | try: 26 | import ipaserver 27 | except ImportError: 28 | HAS_IPASERVER = False 29 | else: 30 | HAS_IPASERVER = True 31 | 32 | SERVER_SYSRESTORE_STATE = "/var/lib/ipa/sysrestore/sysrestore.state" 33 | NAMED_CONF = "/etc/named.conf" 34 | VAR_LIB_PKI_TOMCAT = "/var/lib/pki/pki-tomcat" 35 | 36 | 37 | def is_ntpd_configured(): 38 | # ntpd is configured when sysrestore.state contains the line 39 | # [ntpd] 40 | ntpd_conf_section = re.compile('^\s*\[ntpd\]\s*$') 41 | 42 | try: 43 | with open(SERVER_SYSRESTORE_STATE) as f: 44 | for line in f.readlines(): 45 | if ntpd_conf_section.match(line): 46 | return True 47 | return False 48 | except IOError: 49 | return False 50 | 51 | def is_dns_configured(): 52 | # dns is configured when /etc/named.conf contains the line 53 | # dyndb "ipa" "/usr/lib64/bind/ldap.so" { 54 | bind_conf_section = re.compile('^\s*dyndb\s+"ipa"\s+"[^"]+"\s+{$') 55 | 56 | try: 57 | with open(NAMED_CONF) as f: 58 | for line in f.readlines(): 59 | if bind_conf_section.match(line): 60 | return True 61 | return False 62 | except IOError: 63 | return False 64 | 65 | def is_dogtag_configured(subsystem): 66 | # ca / kra is configured when the directory /var/lib/pki/pki-tomcat/[ca|kra] 67 | # exists 68 | available_subsystems = { 'ca', 'kra' } 69 | assert subsystem in available_subsystems 70 | 71 | return os.path.isdir(os.path.join(VAR_LIB_PKI_TOMCAT, subsystem)) 72 | 73 | def is_ca_configured(): 74 | return is_dogtag_configured('ca') 75 | 76 | def is_kra_configured(): 77 | return is_dogtag_configured('kra') 78 | 79 | def is_client_configured(): 80 | # IPA Client is configured when /etc/ipa/default.conf exists 81 | # and /var/lib/ipa-client/sysrestore/sysrestore.state exists 82 | 83 | fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) 84 | return (os.path.isfile(paths.IPA_DEFAULT_CONF) and fstore.has_files()) 85 | 86 | def is_server_configured(): 87 | # IPA server is configured when /etc/ipa/default.conf exists 88 | # and /var/lib/ipa/sysrestore/sysrestore.state exists 89 | return (os.path.isfile(paths.IPA_DEFAULT_CONF) and 90 | os.path.isfile(SERVER_SYSRESTORE_STATE)) 91 | 92 | def get_ipa_conf(): 93 | # Extract basedn, realm and domain from /etc/ipa/default.conf 94 | parser = RawConfigParser() 95 | parser.read(paths.IPA_DEFAULT_CONF) 96 | basedn = parser.get('global', 'basedn') 97 | realm = parser.get('global', 'realm') 98 | domain = parser.get('global', 'domain') 99 | return dict( 100 | basedn=basedn, 101 | realm=realm, 102 | domain=domain 103 | ) 104 | 105 | def get_ipa_version(): 106 | try: 107 | from ipapython import version 108 | except ImportError: 109 | return None 110 | else: 111 | version_info = [] 112 | for part in version.VERSION.split('.'): 113 | # DEV versions look like: 114 | # 4.4.90.201610191151GITd852c00 115 | # 4.4.90.dev201701071308+git2e43db1 116 | # 4.6.90.pre2 117 | if part.startswith('dev') or part.startswith('pre') or 'GIT' in part: 118 | version_info.append(part) 119 | else: 120 | version_info.append(int(part)) 121 | 122 | return dict( 123 | api_version=version.API_VERSION, 124 | num_version=version.NUM_VERSION, 125 | vendor_version=version.VENDOR_VERSION, 126 | version=version.VERSION, 127 | version_info=version_info 128 | ) 129 | 130 | def main(): 131 | module = AnsibleModule( 132 | argument_spec = dict(), 133 | supports_check_mode=True 134 | ) 135 | 136 | # The module does not change anything, meaning that 137 | # check mode is supported 138 | 139 | ipa_facts = dict( 140 | packages= dict( 141 | ipalib=HAS_IPALIB, 142 | ipaserver=HAS_IPASERVER, 143 | ), 144 | configured=dict( 145 | client=False, 146 | server=False, 147 | dns=False, 148 | ca=False, 149 | kra=False, 150 | ntpd=False 151 | ) 152 | ) 153 | 154 | if HAS_IPALIB: 155 | if is_client_configured(): 156 | ipa_facts['configured']['client'] = True 157 | 158 | ipa_facts['version'] = get_ipa_version() 159 | for key,value in six.iteritems(get_ipa_conf()): 160 | ipa_facts[key] = value 161 | 162 | if HAS_IPASERVER: 163 | if is_server_configured(): 164 | ipa_facts['configured']['server'] = True 165 | ipa_facts['configured']['dns'] = is_dns_configured() 166 | ipa_facts['configured']['ca'] = is_ca_configured() 167 | ipa_facts['configured']['kra'] = is_kra_configured() 168 | ipa_facts['configured']['ntpd'] = is_ntpd_configured() 169 | 170 | module.exit_json( 171 | changed=False, 172 | ansible_facts=dict(ipa=ipa_facts) 173 | ) 174 | 175 | if __name__ == '__main__': 176 | main() 177 | -------------------------------------------------------------------------------- /roles/ipaclient/library/ipaclient_set_hostname.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-client-install code 8 | # 9 | # Copyright (C) 2018 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | ANSIBLE_METADATA = { 26 | 'metadata_version': '1.0', 27 | 'supported_by': 'community', 28 | 'status': ['preview'], 29 | } 30 | 31 | DOCUMENTATION = ''' 32 | --- 33 | module: ipaclient_set_hostname 34 | short description: Backup and set hostname 35 | description: 36 | Backup and set hostname 37 | options: 38 | hostname: 39 | description: The hostname of the machine to join (FQDN). 40 | required: true 41 | author: 42 | - Thomas Woerner 43 | ''' 44 | 45 | EXAMPLES = ''' 46 | # Backup and set hostname 47 | - name: Backup and set hostname 48 | ipaclient_set_hostname: 49 | hostname: client1.example.com 50 | ''' 51 | 52 | RETURN = ''' 53 | ''' 54 | 55 | import os 56 | import tempfile 57 | 58 | from ansible.module_utils.basic import AnsibleModule 59 | from ansible.module_utils.ansible_ipa_client import * 60 | 61 | def main(): 62 | module = AnsibleModule( 63 | argument_spec = dict( 64 | hostname=dict(required=True), 65 | ), 66 | supports_check_mode = True, 67 | ) 68 | 69 | module._ansible_debug = True 70 | hostname = module.params.get('hostname') 71 | 72 | fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) 73 | statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE) 74 | 75 | tasks.backup_hostname(fstore, statestore) 76 | tasks.set_hostname(hostname) 77 | 78 | module.exit_json(changed=True) 79 | 80 | if __name__ == '__main__': 81 | main() 82 | -------------------------------------------------------------------------------- /roles/ipaclient/library/ipafixca.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-client-install code 8 | # 9 | # Copyright (C) 2017 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | ANSIBLE_METADATA = {'metadata_version': '1.0', 26 | 'status': ['preview'], 27 | 'supported_by': 'community'} 28 | 29 | DOCUMENTATION = ''' 30 | --- 31 | module: ipafixca 32 | short description: Fix IPA ca certificate 33 | description: 34 | Repair Fix IPA ca certificate 35 | options: 36 | servers: 37 | description: The FQDN of the IPA servers to connect to. 38 | required: true 39 | type: list 40 | realm: 41 | description: The Kerberos realm of an existing IPA deployment. 42 | required: true 43 | basedn: 44 | description: The basedn of the IPA server (of the form dc=example,dc=com). 45 | required: true 46 | allow_repair: 47 | description: Allow repair of already joined hosts. Contrary to ipaclient_force_join the host entry will not be changed on the server. 48 | required: true 49 | type: bool 50 | default: no 51 | author: 52 | - Thomas Woerner 53 | ''' 54 | 55 | EXAMPLES = ''' 56 | - name: Fix IPA ca certificate 57 | ipafixca: 58 | servers: ["server1.example.com","server2.example.com"] 59 | realm: EXAMPLE.COM 60 | basedn: dc=example,dc=com 61 | allow_repair: yes 62 | ''' 63 | 64 | RETURN = ''' 65 | ''' 66 | 67 | import os 68 | 69 | from ansible.module_utils.basic import AnsibleModule 70 | from ansible.module_utils.ansible_ipa_client import * 71 | 72 | def main(): 73 | module = AnsibleModule( 74 | argument_spec = dict( 75 | servers=dict(required=True, type='list'), 76 | realm=dict(required=True), 77 | basedn=dict(required=True), 78 | allow_repair=dict(required=True, type='bool'), 79 | ), 80 | ) 81 | 82 | module._ansible_debug = True 83 | servers = module.params.get('servers') 84 | realm = module.params.get('realm') 85 | basedn = module.params.get('basedn') 86 | allow_repair = module.params.get('allow_repair') 87 | 88 | env = {'PATH': SECURE_PATH} 89 | fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) 90 | os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE 91 | 92 | options.ca_cert_file = None 93 | options.unattended = True 94 | options.principal = None 95 | options.force = False 96 | options.password = None 97 | 98 | changed = False 99 | if not os.path.exists(paths.IPA_CA_CRT): 100 | if not allow_repair: 101 | module.fail_json( 102 | msg="%s missing, enable allow_repair to fix it." % \ 103 | paths.IPA_CA_CRT) 104 | 105 | # Repair missing ca.crt file 106 | try: 107 | os.environ['KRB5_CONFIG'] = env['KRB5_CONFIG'] = "/etc/krb5.conf" 108 | env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] 109 | if NUM_VERSION < 40100: 110 | get_ca_cert(fstore, options, servers[0], basedn) 111 | else: 112 | get_ca_certs(fstore, options, servers[0], basedn, realm) 113 | changed = True 114 | del os.environ['KRB5_CONFIG'] 115 | except errors.FileError as e: 116 | module.fail_json(msg='%s' % e) 117 | except Exception as e: 118 | module.fail_json(msg="Cannot obtain CA certificate\n%s" % e) 119 | 120 | module.exit_json(changed=changed) 121 | 122 | if __name__ == '__main__': 123 | main() 124 | -------------------------------------------------------------------------------- /roles/ipaclient/library/ipafstore.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-client-install code 8 | # 9 | # Copyright (C) 2017 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | ANSIBLE_METADATA = { 26 | 'metadata_version': '1.0', 27 | 'supported_by': 'community', 28 | 'status': ['preview'], 29 | } 30 | 31 | DOCUMENTATION = ''' 32 | --- 33 | module: fstore 34 | short description: Backup files using IPA client sysrestore 35 | description: 36 | Backup files using IPA client sysrestore 37 | options: 38 | backup: 39 | description: File to backup 40 | required: true 41 | author: 42 | - Thomas Woerner 43 | ''' 44 | 45 | EXAMPLES = ''' 46 | - name: Backup /etc/krb5.conf 47 | ipafstore: 48 | backup: "/etc/krb5.conf" 49 | ''' 50 | 51 | RETURN = ''' 52 | ''' 53 | 54 | from ansible.module_utils.basic import AnsibleModule 55 | from ansible.module_utils.ansible_ipa_client import * 56 | 57 | def main(): 58 | module = AnsibleModule( 59 | argument_spec = dict( 60 | backup=dict(required=True), 61 | ), 62 | ) 63 | 64 | module._ansible_debug = True 65 | backup = module.params.get('backup') 66 | 67 | fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) 68 | if not fstore.has_file(backup): 69 | fstore.backup_file(backup) 70 | module.exit_json(changed=True) 71 | 72 | module.exit_json(changed=False) 73 | 74 | if __name__ == '__main__': 75 | main() 76 | -------------------------------------------------------------------------------- /roles/ipaclient/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: Florence Blanc-Renaud, Thomas Woerner 3 | description: A role to join a machine to an IPA domain 4 | company: Red Hat, Inc 5 | 6 | # issue_tracker_url: http://example.com/issue/tracker 7 | 8 | license: GPLv3 9 | 10 | min_ansible_version: 2.3.1 11 | 12 | #github_branch: 13 | 14 | platforms: 15 | - name: Fedora 16 | versions: 17 | - 25 18 | - name: rhel 19 | versions: 20 | - 7 21 | 22 | galaxy_tags: [ 'identity', 'ipa'] 23 | 24 | dependencies: [] 25 | -------------------------------------------------------------------------------- /roles/ipaclient/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for ipaclient 3 | 4 | - name: Import variables specific to distribution 5 | include_vars: "{{ item }}" 6 | with_first_found: 7 | - "{{ role_path }}/vars/{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml" 8 | - "{{ role_path }}/vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml" 9 | - "{{ role_path }}/vars/{{ ansible_distribution }}.yml" 10 | - "{{ role_path }}/vars/default.yml" 11 | 12 | - name: Install IPA client 13 | include: tasks/install.yml 14 | when: state|default('present') == 'present' 15 | 16 | - name: Uninstall IPA client 17 | include: tasks/uninstall.yml 18 | when: state|default('present') == 'absent' 19 | -------------------------------------------------------------------------------- /roles/ipaclient/tasks/python_2_3_test.yml: -------------------------------------------------------------------------------- 1 | - block: 2 | - name: Verify Python3 import 3 | script: py3test.py 4 | register: py3test 5 | failed_when: False 6 | changed_when: False 7 | 8 | - name: Set python interpreter to 3 9 | set_fact: 10 | ansible_python_interpreter: "/usr/bin/python3" 11 | when: py3test.rc == 0 12 | 13 | - name: Set python interpreter to 2 14 | set_fact: 15 | ansible_python_interpreter: "/usr/bin/python2" 16 | when: py3test.failed or py3test.rc != 0 17 | -------------------------------------------------------------------------------- /roles/ipaclient/tasks/uninstall.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks to uninstall IPA client 3 | 4 | #- name: Uninstall - Include Python2/3 import test 5 | # include: "{{role_path}}/tasks/python_2_3_test.yml" 6 | # static: yes 7 | 8 | - name: Uninstall - Uninstall IPA client 9 | command: > 10 | /usr/sbin/ipa-client-install 11 | --uninstall 12 | -U 13 | register: uninstall 14 | # 2 means that uninstall failed because IPA client was not configured 15 | failed_when: uninstall.rc != 0 and uninstall.rc != 2 16 | changed_when: uninstall.rc == 0 17 | 18 | #- name: Remove IPA client package 19 | # package: 20 | # name: "{{ item }}" 21 | # state: absent 22 | # with_items: "{{ ipaclient_packages }}" 23 | -------------------------------------------------------------------------------- /roles/ipaclient/vars/CentOS-7.yml: -------------------------------------------------------------------------------- 1 | # defaults file for ipaclient 2 | # vars/rhel.yml 3 | ipaclient_packages: [ "ipa-client", "libselinux-python" ] 4 | #ansible_python_interpreter: '/usr/bin/python2' 5 | -------------------------------------------------------------------------------- /roles/ipaclient/vars/Fedora-25.yml: -------------------------------------------------------------------------------- 1 | ipaclient_packages: [ "ipa-client", "libselinux-python" ] 2 | #ansible_python_interpreter: '/usr/bin/python2' -------------------------------------------------------------------------------- /roles/ipaclient/vars/Fedora-26.yml: -------------------------------------------------------------------------------- 1 | ipaclient_packages: [ "ipa-client", "libselinux-python" ] 2 | #ansible_python_interpreter: '/usr/bin/python2' -------------------------------------------------------------------------------- /roles/ipaclient/vars/RedHat-7.3.yml: -------------------------------------------------------------------------------- 1 | # defaults file for ipaclient 2 | # vars/rhel.yml 3 | ipaclient_packages: [ "ipa-client", "ipa-admintools", "libselinux-python" ] 4 | #ansible_python_interpreter: '/usr/bin/python2' 5 | -------------------------------------------------------------------------------- /roles/ipaclient/vars/RedHat-7.yml: -------------------------------------------------------------------------------- 1 | # defaults file for ipaclient 2 | # vars/rhel.yml 3 | ipaclient_packages: [ "ipa-client", "libselinux-python" ] 4 | #ansible_python_interpreter: '/usr/bin/python2' 5 | -------------------------------------------------------------------------------- /roles/ipaclient/vars/Ubuntu.yml: -------------------------------------------------------------------------------- 1 | # vars/Ubuntu.yml 2 | ipaclient_packages: [ "freeipa-client" ] 3 | -------------------------------------------------------------------------------- /roles/ipaclient/vars/default.yml: -------------------------------------------------------------------------------- 1 | # defaults file for ipaclient 2 | # vars/default.yml 3 | ipaclient_packages: [ "ipa-client", "python3-libselinux" ] 4 | #ansible_python_interpreter: '/usr/bin/python3' 5 | -------------------------------------------------------------------------------- /roles/ipaconf/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ipaconf_default_conf: /etc/ipa/default.conf 3 | 4 | ipaconf_basedn: 5 | ipaconf_realm: 6 | ipaconf_domain: 7 | ipaconf_server: 8 | ipaconf_hostname: 9 | -------------------------------------------------------------------------------- /roles/ipaconf/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: Thomas Woerner 3 | description: A role to configure IPA default.conf 4 | company: Red Hat, Inc 5 | 6 | license: GPLv3 7 | 8 | min_ansible_version: 2.0 9 | 10 | galaxy_tags: [ 'identity', 'ipa'] 11 | 12 | dependencies: [] 13 | -------------------------------------------------------------------------------- /roles/ipaconf/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Backup IPA default.conf 3 | ipafstore: 4 | backup: "{{ ipaconf_default_conf }}" 5 | 6 | - name: Template IPA default.conf 7 | template: 8 | src: default.conf.j2 9 | dest: "{{ ipaconf_default_conf }}" 10 | backup: yes 11 | owner: root 12 | group: root 13 | mode: 0644 14 | -------------------------------------------------------------------------------- /roles/ipaconf/templates/default.conf.j2: -------------------------------------------------------------------------------- 1 | [global] 2 | basedn = {{ ipaconf_basedn }} 3 | realm = {{ ipaconf_realm }} 4 | domain = {{ ipaconf_domain }} 5 | server = {{ ipaconf_server }} 6 | host = {{ ipaconf_hostname }} 7 | xmlrpc_uri = {{ 'https://' + ipaconf_server + '/ipa/xml' }} 8 | enable_ra = True 9 | -------------------------------------------------------------------------------- /roles/ipaconf/vars/default.yml: -------------------------------------------------------------------------------- 1 | krb5_packages: 2 | - krb5-workstation 3 | -------------------------------------------------------------------------------- /roles/ipareplica/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for ipareplica 3 | 4 | ### basic ### 5 | ipareplica_no_host_dns: no 6 | ipareplica_skip_conncheck: no 7 | ### server ### 8 | ipareplica_setup_adtrust: no 9 | ipareplica_setup_ca: no 10 | ipareplica_setup_kra: no 11 | ipareplica_setup_dns: no 12 | ipareplica_no_pkinit: no 13 | ipareplica_no_ui_redirect: no 14 | ### client ### 15 | ipaclient_mkhomedir: no 16 | ipaclient_force_join: no 17 | ipaclient_no_ntp: no 18 | #ipaclient_ssh_trust_dns: no 19 | #ipaclient_no_ssh: no 20 | #ipaclient_no_sshd: no 21 | #ipaclient_no_dns_sshfp: no 22 | ipaclient_ssh_trust_dns: no 23 | ### certificate system ### 24 | ipareplica_skip_schema_check: no 25 | ### dns ### 26 | ipareplica_allow_zone_overlap: no 27 | ipareplica_no_reverse: no 28 | ipareplica_auto_reverse: no 29 | ipareplica_no_forwarders: no 30 | ipareplica_auto_forwarders: no 31 | ipareplica_no_dnssec_validation: no 32 | ### ad trust ### 33 | ipareplica_add_sids: no 34 | ipareplica_add_agents: no 35 | ipareplica_enable_compat: no 36 | ### uninstall ### 37 | ipareplica_ignore_topology_disconnect: no 38 | ipareplica_ignore_last_of_role: no 39 | ### additional ### 40 | ipareplica_no_package_install: no 41 | ipareplica_no_firewalld: no 42 | -------------------------------------------------------------------------------- /roles/ipareplica/files/py3test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # Test ipaerver python3 binding 4 | from ipaserver.install.server.replicainstall import install_check 5 | 6 | # Check ipapython version to be >= 4.6 7 | from ipapython.version import NUM_VERSION, VERSION 8 | if NUM_VERSION < 40590: 9 | raise Exception("ipa %s not usable with python3" % VERSION) 10 | -------------------------------------------------------------------------------- /roles/ipareplica/library/ipareplica_add_to_ipaservers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-replica-install code 8 | # 9 | # Copyright (C) 2018 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: ipareplica_add_to_ipaservers 36 | short description: Add to ipaservers 37 | description: 38 | Add to ipaservers 39 | options: 40 | setup_kra: 41 | description: 42 | required: yes 43 | config_master_host_name: 44 | description: 45 | required: yes 46 | ccache: 47 | description: 48 | required: yes 49 | installer_ccache: 50 | description: 51 | required: yes 52 | _top_dir: 53 | description: 54 | required: yes 55 | author: 56 | - Thomas Woerner 57 | ''' 58 | 59 | EXAMPLES = ''' 60 | ''' 61 | 62 | RETURN = ''' 63 | ''' 64 | 65 | from ansible.module_utils.basic import AnsibleModule 66 | from ansible.module_utils.ansible_ipa_replica import * 67 | 68 | def main(): 69 | ansible_module = AnsibleModule( 70 | argument_spec = dict( 71 | ### server ### 72 | setup_kra=dict(required=True, type='bool'), 73 | ### additional ### 74 | config_master_host_name=dict(required=True), 75 | ccache=dict(required=True), 76 | installer_ccache=dict(required=True), 77 | _top_dir = dict(required=True), 78 | ), 79 | supports_check_mode = True, 80 | ) 81 | 82 | ansible_module._ansible_debug = True 83 | ansible_log = AnsibleModuleLog(ansible_module) 84 | 85 | # get parameters # 86 | 87 | options = installer 88 | ### server ### 89 | options.setup_kra = ansible_module.params.get('setup_kra') 90 | ### additional ### 91 | config_master_host_name = ansible_module.params.get('config_master_host_name') 92 | ccache = ansible_module.params.get('ccache') 93 | os.environ['KRB5CCNAME'] = ccache 94 | options._ccache = ansible_module.params.get('installer_ccache') 95 | #os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache') 96 | options._top_dir = ansible_module.params.get('_top_dir') 97 | 98 | # init # 99 | 100 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 101 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 102 | 103 | ansible_log.debug("== INSTALLER ==") 104 | 105 | options = installer 106 | promote = installer.promote 107 | 108 | env = gen_env_boostrap_finalize_core(paths.ETC_IPA, 109 | constants.DEFAULT_CONFIG) 110 | api_bootstrap_finalize(env) 111 | #config = gen_ReplicaConfig() 112 | 113 | remote_api = gen_remote_api(config_master_host_name, paths.ETC_IPA) 114 | #installer._remote_api = remote_api 115 | 116 | conn = remote_api.Backend.ldap2 117 | ccache = os.environ['KRB5CCNAME'] 118 | 119 | ansible_log.debug("-- HOSTGROUP_ADD_MEMBER --") 120 | try: 121 | ansible_log.debug("-- CONNECT --") 122 | conn.connect(ccache=installer._ccache) 123 | remote_api.Command['hostgroup_add_member']( 124 | u'ipaservers', 125 | host=[unicode(api.env.host)], 126 | ) 127 | finally: 128 | if conn.isconnected(): 129 | ansible_log.debug("-- DISCONNECT --") 130 | conn.disconnect() 131 | os.environ['KRB5CCNAME'] = ccache 132 | 133 | # done # 134 | 135 | ansible_module.exit_json(changed=True) 136 | 137 | if __name__ == '__main__': 138 | main() 139 | -------------------------------------------------------------------------------- /roles/ipareplica/library/ipareplica_krb_enable_ssl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-replica-install code 8 | # 9 | # Copyright (C) 2018 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: ipareplica_krb_enable_ssl 36 | short description: KRB enable SSL 37 | description: 38 | KRB enable SSL 39 | options: 40 | author: 41 | - Thomas Woerner 42 | ''' 43 | 44 | EXAMPLES = ''' 45 | ''' 46 | 47 | RETURN = ''' 48 | ''' 49 | 50 | from ansible.module_utils.basic import AnsibleModule 51 | from ansible.module_utils.ansible_ipa_replica import * 52 | 53 | def main(): 54 | ansible_module = AnsibleModule( 55 | argument_spec = dict( 56 | #### server ### 57 | setup_ca=dict(required=False, type='bool'), 58 | setup_kra=dict(required=False, type='bool'), 59 | no_pkinit=dict(required=False, type='bool'), 60 | #### certificate system ### 61 | subject_base=dict(required=True), 62 | #### additional ### 63 | config_master_host_name=dict(required=True), 64 | ccache=dict(required=True), 65 | _ca_enabled=dict(required=False, type='bool'), 66 | _ca_file=dict(required=False), 67 | _dirsrv_pkcs12_info = dict(required=False), 68 | _pkinit_pkcs12_info = dict(required=False), 69 | _top_dir = dict(required=True), 70 | dirman_password=dict(required=True, no_log=True), 71 | ), 72 | supports_check_mode = True, 73 | ) 74 | 75 | ansible_module._ansible_debug = True 76 | ansible_log = AnsibleModuleLog(ansible_module) 77 | 78 | # get parameters # 79 | 80 | options = installer 81 | ### server ### 82 | options.setup_ca = ansible_module.params.get('setup_ca') 83 | options.setup_kra = ansible_module.params.get('setup_kra') 84 | options.no_pkinit = ansible_module.params.get('no_pkinit') 85 | ### certificate system ### 86 | options.subject_base = ansible_module.params.get('subject_base') 87 | if options.subject_base is not None: 88 | options.subject_base = DN(options.subject_base) 89 | ### additional ### 90 | master_host_name = ansible_module.params.get('config_master_host_name') 91 | ccache = ansible_module.params.get('ccache') 92 | os.environ['KRB5CCNAME'] = ccache 93 | #os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache') 94 | #installer._ccache = ansible_module.params.get('installer_ccache') 95 | ca_enabled = ansible_module.params.get('_ca_enabled') 96 | dirsrv_pkcs12_info = ansible_module.params.get('_dirsrv_pkcs12_info') 97 | options._pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info') 98 | options._top_dir = ansible_module.params.get('_top_dir') 99 | dirman_password = ansible_module.params.get('dirman_password') 100 | 101 | # init # 102 | 103 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 104 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 105 | 106 | ansible_log.debug("== INSTALL ==") 107 | 108 | options = installer 109 | promote = installer.promote 110 | pkinit_pkcs12_info = installer._pkinit_pkcs12_info 111 | 112 | env = gen_env_boostrap_finalize_core(paths.ETC_IPA, 113 | constants.DEFAULT_CONFIG) 114 | api_bootstrap_finalize(env) 115 | config = gen_ReplicaConfig() 116 | config.dirman_password = dirman_password 117 | 118 | remote_api = gen_remote_api(master_host_name, paths.ETC_IPA) 119 | #installer._remote_api = remote_api 120 | 121 | conn = remote_api.Backend.ldap2 122 | ccache = os.environ['KRB5CCNAME'] 123 | 124 | # There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or 125 | # ntpinstance 126 | api.Backend.ldap2.connect() 127 | conn.connect(ccache=ccache) 128 | 129 | # krb 130 | krb = krbinstance.KrbInstance(fstore) 131 | krb.set_output(ansible_log) 132 | with redirect_stdout(ansible_log): 133 | krb.init_info(api.env.realm, api.env.host, 134 | setup_pkinit=not options.no_pkinit, 135 | subject_base=options.subject_base) 136 | 137 | ansible_log.debug("-- KRB ENABLE_SSL --") 138 | 139 | # configure PKINIT now that all required services are in place 140 | krb.enable_ssl() 141 | 142 | # done # 143 | 144 | ansible_module.exit_json(changed=True) 145 | 146 | if __name__ == '__main__': 147 | main() 148 | -------------------------------------------------------------------------------- /roles/ipareplica/library/ipareplica_promote_openldap_conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-replica-install code 8 | # 9 | # Copyright (C) 2018 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: ipareplica_promote_openldap_conf 36 | short description: Promote openldap.conf 37 | description: 38 | Promote openldap.conf 39 | options: 40 | setup_kra: 41 | description: 42 | required: no 43 | subject_base: 44 | description: 45 | required: yes 46 | ccache: 47 | description: 48 | required: yes 49 | _top_dir: 50 | description: 51 | required: yes 52 | config_setup_ca: 53 | description: 54 | required: yes 55 | config_master_host_name: 56 | description: 57 | required: yes 58 | author: 59 | - Thomas Woerner 60 | ''' 61 | 62 | EXAMPLES = ''' 63 | ''' 64 | 65 | RETURN = ''' 66 | ''' 67 | 68 | from ansible.module_utils.basic import AnsibleModule 69 | from ansible.module_utils.ansible_ipa_replica import * 70 | 71 | def main(): 72 | ansible_module = AnsibleModule( 73 | argument_spec = dict( 74 | ### server ### 75 | setup_kra=dict(required=False, type='bool'), 76 | ### certificate system ### 77 | subject_base=dict(required=True), 78 | ### additional ### 79 | ccache=dict(required=True), 80 | _top_dir = dict(required=True), 81 | config_setup_ca=dict(required=True), 82 | config_master_host_name=dict(required=True), 83 | ), 84 | supports_check_mode = True, 85 | ) 86 | 87 | ansible_module._ansible_debug = True 88 | ansible_log = AnsibleModuleLog(ansible_module) 89 | 90 | # get parameters # 91 | 92 | options = installer 93 | ### server ### 94 | options.setup_kra = ansible_module.params.get('setup_kra') 95 | ### certificate system ### 96 | options.subject_base = ansible_module.params.get('subject_base') 97 | if options.subject_base is not None: 98 | options.subject_base = DN(options.subject_base) 99 | ### additional ### 100 | ccache = ansible_module.params.get('ccache') 101 | os.environ['KRB5CCNAME'] = ccache 102 | options._top_dir = ansible_module.params.get('_top_dir') 103 | config_setup_ca = ansible_module.params.get('config_setup_ca') 104 | installer.setup_ca = config_setup_ca 105 | config_master_host_name = ansible_module.params.get('config_master_host_name') 106 | 107 | # init # 108 | 109 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 110 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 111 | 112 | 113 | ansible_log.debug("== INSTALL ==") 114 | 115 | promote = installer.promote 116 | 117 | env = gen_env_boostrap_finalize_core(paths.ETC_IPA, 118 | constants.DEFAULT_CONFIG) 119 | api_bootstrap_finalize(env) 120 | config = gen_ReplicaConfig() 121 | config.subject_base = options.subject_base 122 | config.setup_ca = config_setup_ca 123 | config.master_host_name = config_master_host_name 124 | 125 | remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA) 126 | installer._remote_api = remote_api 127 | 128 | conn = remote_api.Backend.ldap2 129 | ccache = os.environ['KRB5CCNAME'] 130 | 131 | with redirect_stdout(ansible_log): 132 | ansible_log.debug("-- PROMOTE OPENLDAP_CONF--") 133 | 134 | promote_openldap_conf(config.host_name, config.master_host_name) 135 | 136 | # done # 137 | 138 | ansible_module.exit_json(changed=True) 139 | 140 | if __name__ == '__main__': 141 | main() 142 | -------------------------------------------------------------------------------- /roles/ipareplica/library/ipareplica_promote_sssd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-replica-install code 8 | # 9 | # Copyright (C) 2018 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: ipareplica_promote_sssd 36 | short description: Promote sssd 37 | description: 38 | Promote sssd 39 | options: 40 | setup_kra: 41 | description: 42 | required: no 43 | subject_base: 44 | description: 45 | required: yes 46 | ccache: 47 | description: 48 | required: yes 49 | _top_dir: 50 | description: 51 | required: yes 52 | config_setup_ca: 53 | description: 54 | required: yes 55 | config_master_host_name: 56 | description: 57 | required: yes 58 | author: 59 | - Thomas Woerner 60 | ''' 61 | 62 | EXAMPLES = ''' 63 | ''' 64 | 65 | RETURN = ''' 66 | ''' 67 | 68 | from ansible.module_utils.basic import AnsibleModule 69 | from ansible.module_utils.ansible_ipa_replica import * 70 | 71 | def main(): 72 | ansible_module = AnsibleModule( 73 | argument_spec = dict( 74 | ### server ### 75 | setup_kra=dict(required=False, type='bool'), 76 | ### certificate system ### 77 | subject_base=dict(required=True), 78 | ### additional ### 79 | ccache=dict(required=True), 80 | _top_dir = dict(required=True), 81 | config_setup_ca=dict(required=True), 82 | config_master_host_name=dict(required=True), 83 | ), 84 | supports_check_mode = True, 85 | ) 86 | 87 | ansible_module._ansible_debug = True 88 | ansible_log = AnsibleModuleLog(ansible_module) 89 | 90 | # get parameters # 91 | 92 | options = installer 93 | ### server ### 94 | options.setup_kra = ansible_module.params.get('setup_kra') 95 | ### certificate system ### 96 | options.subject_base = ansible_module.params.get('subject_base') 97 | if options.subject_base is not None: 98 | options.subject_base = DN(options.subject_base) 99 | ### additional ### 100 | ccache = ansible_module.params.get('ccache') 101 | os.environ['KRB5CCNAME'] = ccache 102 | options._top_dir = ansible_module.params.get('_top_dir') 103 | config_setup_ca = ansible_module.params.get('config_setup_ca') 104 | installer.setup_ca = config_setup_ca 105 | config_master_host_name = ansible_module.params.get('config_master_host_name') 106 | 107 | # init # 108 | 109 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 110 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 111 | 112 | ansible_log.debug("== INSTALL ==") 113 | 114 | promote = installer.promote 115 | 116 | env = gen_env_boostrap_finalize_core(paths.ETC_IPA, 117 | constants.DEFAULT_CONFIG) 118 | api_bootstrap_finalize(env) 119 | config = gen_ReplicaConfig() 120 | config.subject_base = options.subject_base 121 | config.setup_ca = config_setup_ca 122 | config.master_host_name = config_master_host_name 123 | 124 | remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA) 125 | installer._remote_api = remote_api 126 | 127 | conn = remote_api.Backend.ldap2 128 | ccache = os.environ['KRB5CCNAME'] 129 | 130 | with redirect_stdout(ansible_log): 131 | ansible_log.debug("-- PROMOTE SSSD --") 132 | 133 | promote_sssd(config.host_name) 134 | 135 | # done # 136 | 137 | ansible_module.exit_json(changed=True) 138 | 139 | if __name__ == '__main__': 140 | main() 141 | -------------------------------------------------------------------------------- /roles/ipareplica/library/ipareplica_restart_kdc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-replica-install code 8 | # 9 | # Copyright (C) 2018 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: ipareplica_restart_kdc 36 | short description: Restart KDC 37 | description: 38 | Restart KDC 39 | options: 40 | author: 41 | - Thomas Woerner 42 | ''' 43 | 44 | EXAMPLES = ''' 45 | ''' 46 | 47 | RETURN = ''' 48 | ''' 49 | 50 | from ansible.module_utils.basic import AnsibleModule 51 | from ansible.module_utils.ansible_ipa_replica import * 52 | 53 | def main(): 54 | ansible_module = AnsibleModule( 55 | argument_spec = dict( 56 | #### server ### 57 | setup_ca=dict(required=False, type='bool'), 58 | setup_kra=dict(required=False, type='bool'), 59 | no_pkinit=dict(required=False, type='bool'), 60 | no_ui_redirect=dict(required=False, type='bool'), 61 | #### certificate system ### 62 | subject_base=dict(required=True), 63 | #### additional ### 64 | config_master_host_name=dict(required=True), 65 | ccache=dict(required=True), 66 | _ca_enabled=dict(required=False, type='bool'), 67 | _ca_file=dict(required=False), 68 | _dirsrv_pkcs12_info = dict(required=False), 69 | #_pkinit_pkcs12_info = dict(required=False), 70 | _top_dir = dict(required=True), 71 | dirman_password=dict(required=True, no_log=True), 72 | ), 73 | supports_check_mode = True, 74 | ) 75 | 76 | ansible_module._ansible_debug = True 77 | ansible_log = AnsibleModuleLog(ansible_module) 78 | 79 | # get parameters # 80 | 81 | options = installer 82 | ### server ### 83 | options.setup_ca = ansible_module.params.get('setup_ca') 84 | options.setup_kra = ansible_module.params.get('setup_kra') 85 | options.no_pkinit = ansible_module.params.get('no_pkinit') 86 | ### certificate system ### 87 | options.subject_base = ansible_module.params.get('subject_base') 88 | if options.subject_base is not None: 89 | options.subject_base = DN(options.subject_base) 90 | ### additional ### 91 | master_host_name = ansible_module.params.get('config_master_host_name') 92 | ccache = ansible_module.params.get('ccache') 93 | os.environ['KRB5CCNAME'] = ccache 94 | #os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache') 95 | #installer._ccache = ansible_module.params.get('installer_ccache') 96 | ca_enabled = ansible_module.params.get('_ca_enabled') 97 | dirsrv_pkcs12_info = ansible_module.params.get('_dirsrv_pkcs12_info') 98 | #pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info') 99 | options._top_dir = ansible_module.params.get('_top_dir') 100 | dirman_password = ansible_module.params.get('dirman_password') 101 | 102 | # init # 103 | 104 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 105 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 106 | 107 | ansible_log.debug("== INSTALL ==") 108 | 109 | options = installer 110 | promote = installer.promote 111 | #pkinit_pkcs12_info = installer._pkinit_pkcs12_info 112 | 113 | env = gen_env_boostrap_finalize_core(paths.ETC_IPA, 114 | constants.DEFAULT_CONFIG) 115 | api_bootstrap_finalize(env) 116 | config = gen_ReplicaConfig() 117 | config.dirman_password = dirman_password 118 | 119 | remote_api = gen_remote_api(master_host_name, paths.ETC_IPA) 120 | #installer._remote_api = remote_api 121 | 122 | conn = remote_api.Backend.ldap2 123 | ccache = os.environ['KRB5CCNAME'] 124 | 125 | # There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or 126 | # ntpinstance 127 | api.Backend.ldap2.connect() 128 | conn.connect(ccache=ccache) 129 | 130 | # krb 131 | krb = krbinstance.KrbInstance(fstore) 132 | krb.set_output(ansible_log) 133 | with redirect_stdout(ansible_log): 134 | krb.init_info(api.env.realm, api.env.host, 135 | setup_pkinit=not options.no_pkinit, 136 | subject_base=options.subject_base) 137 | 138 | ansible_log.debug("-- RESTART KDC --") 139 | 140 | service.print_msg("Restarting the KDC") 141 | krb.restart() 142 | 143 | # done # 144 | 145 | ansible_module.exit_json(changed=True) 146 | 147 | if __name__ == '__main__': 148 | main() 149 | -------------------------------------------------------------------------------- /roles/ipareplica/library/ipareplica_setup_adtrust.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-replica-install code 8 | # 9 | # Copyright (C) 2018 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: ipareplica_setup_adtrust 36 | short description: Setup adtrust 37 | description: 38 | Setup adtrust 39 | options: 40 | setup_adtrust: 41 | description: 42 | required: yes 43 | setup_kra: 44 | description: 45 | required: yes 46 | subject_base: 47 | description: 48 | required: yes 49 | ccache: 50 | description: 51 | required: yes 52 | _top_dir: 53 | description: 54 | required: yes 55 | config_setup_ca: 56 | description: 57 | required: yes 58 | config_master_host_name: 59 | description: 60 | required: yes 61 | author: 62 | - Thomas Woerner 63 | ''' 64 | 65 | EXAMPLES = ''' 66 | ''' 67 | 68 | RETURN = ''' 69 | ''' 70 | 71 | from ansible.module_utils.basic import AnsibleModule 72 | from ansible.module_utils.ansible_ipa_replica import * 73 | 74 | def main(): 75 | ansible_module = AnsibleModule( 76 | argument_spec = dict( 77 | ### server ### 78 | setup_adtrust=dict(required=False, type='bool'), 79 | setup_kra=dict(required=False, type='bool'), 80 | ### certificate system ### 81 | subject_base=dict(required=True), 82 | ### additional ### 83 | ccache=dict(required=True), 84 | _top_dir = dict(required=True), 85 | config_setup_ca=dict(required=True), 86 | config_master_host_name=dict(required=True), 87 | ), 88 | supports_check_mode = True, 89 | ) 90 | 91 | ansible_module._ansible_debug = True 92 | ansible_log = AnsibleModuleLog(ansible_module) 93 | 94 | # get parameters # 95 | 96 | options = installer 97 | ### server ### 98 | options.setup_adtrust = ansible_module.params.get('setup_adtrust') 99 | options.setup_kra = ansible_module.params.get('setup_kra') 100 | ### certificate system ### 101 | options.subject_base = ansible_module.params.get('subject_base') 102 | if options.subject_base is not None: 103 | options.subject_base = DN(options.subject_base) 104 | ### additional ### 105 | ccache = ansible_module.params.get('ccache') 106 | os.environ['KRB5CCNAME'] = ccache 107 | options._top_dir = ansible_module.params.get('_top_dir') 108 | config_setup_ca = ansible_module.params.get('config_setup_ca') 109 | config_master_host_name = ansible_module.params.get('config_master_host_name') 110 | 111 | # init # 112 | 113 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 114 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 115 | 116 | ansible_log.debug("== INSTALL ==") 117 | 118 | options = installer 119 | promote = installer.promote 120 | 121 | env = gen_env_boostrap_finalize_core(paths.ETC_IPA, 122 | constants.DEFAULT_CONFIG) 123 | api_bootstrap_finalize(env) 124 | config = gen_ReplicaConfig() 125 | config.subject_base = options.subject_base 126 | 127 | remote_api = gen_remote_api(master_host_name, paths.ETC_IPA) 128 | installer._remote_api = remote_api 129 | 130 | conn = remote_api.Backend.ldap2 131 | ccache = os.environ['KRB5CCNAME'] 132 | 133 | with redirect_stdout(ansible_log): 134 | #if options.setup_adtrust: 135 | ansible_log.debug("-- INSTALL ADTRUST --") 136 | 137 | adtrust.install(False, options, fstore, api) 138 | 139 | # done # 140 | 141 | ansible_module.exit_json(changed=True) 142 | 143 | if __name__ == '__main__': 144 | main() 145 | -------------------------------------------------------------------------------- /roles/ipareplica/library/ipareplica_setup_certmonger.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-replica-install code 8 | # 9 | # Copyright (C) 2018 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: ipareplica_setup_certmonger 36 | short description: Setup certmonger 37 | description: 38 | Setup certmonger 39 | options: 40 | author: 41 | - Thomas Woerner 42 | ''' 43 | 44 | EXAMPLES = ''' 45 | ''' 46 | 47 | RETURN = ''' 48 | ''' 49 | 50 | from ansible.module_utils.basic import AnsibleModule 51 | from ansible.module_utils.ansible_ipa_replica import * 52 | 53 | def main(): 54 | ansible_module = AnsibleModule( 55 | argument_spec = dict( 56 | ), 57 | supports_check_mode = True, 58 | ) 59 | 60 | ansible_module._ansible_debug = True 61 | ansible_log = AnsibleModuleLog(ansible_module) 62 | 63 | # get parameters # 64 | 65 | options = installer 66 | 67 | with redirect_stdout(ansible_log): 68 | ansible_log.debug("-- CONFIGURE_CERTMONGER --") 69 | 70 | # FIXME: allow to use passed in certs instead 71 | configure_certmonger() 72 | 73 | # done # 74 | 75 | ansible_module.exit_json(changed=True) 76 | 77 | if __name__ == '__main__': 78 | main() 79 | -------------------------------------------------------------------------------- /roles/ipareplica/library/ipareplica_setup_dns.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-replica-install code 8 | # 9 | # Copyright (C) 2018 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: ipareplica_setup_dns 36 | short description: Setup DNS 37 | description: 38 | Setup DNS 39 | options: 40 | setup_kra: 41 | description: 42 | required: yes 43 | setup_dns: 44 | description: 45 | required: yes 46 | subject_base: 47 | description: 48 | required: yes 49 | ccache: 50 | description: 51 | required: yes 52 | _top_dir: 53 | description: 54 | required: yes 55 | setup_ca: 56 | description: 57 | required: yes 58 | config_master_host_name: 59 | description: 60 | required: yes 61 | author: 62 | - Thomas Woerner 63 | ''' 64 | 65 | EXAMPLES = ''' 66 | ''' 67 | 68 | RETURN = ''' 69 | ''' 70 | 71 | from ansible.module_utils.basic import AnsibleModule 72 | from ansible.module_utils.ansible_ipa_replica import * 73 | 74 | def main(): 75 | ansible_module = AnsibleModule( 76 | argument_spec = dict( 77 | ### server ### 78 | setup_kra=dict(required=False, type='bool'), 79 | setup_dns=dict(required=False, type='bool'), 80 | ### certificate system ### 81 | subject_base=dict(required=True), 82 | ### additional ### 83 | ccache=dict(required=True), 84 | _top_dir = dict(required=True), 85 | setup_ca=dict(required=True), 86 | config_master_host_name=dict(required=True), 87 | ), 88 | supports_check_mode = True, 89 | ) 90 | 91 | ansible_module._ansible_debug = True 92 | ansible_log = AnsibleModuleLog(ansible_module) 93 | 94 | # get parameters # 95 | 96 | options = installer 97 | ### server ### 98 | options.setup_kra = ansible_module.params.get('setup_kra') 99 | options.setup_dns = ansible_module.params.get('setup_dns') 100 | ### certificate system ### 101 | options.subject_base = ansible_module.params.get('subject_base') 102 | if options.subject_base is not None: 103 | options.subject_base = DN(options.subject_base) 104 | ### additional ### 105 | ccache = ansible_module.params.get('ccache') 106 | os.environ['KRB5CCNAME'] = ccache 107 | options._top_dir = ansible_module.params.get('_top_dir') 108 | options.setup_ca = ansible_module.params.get('setup_ca') 109 | config_master_host_name = ansible_module.params.get('config_master_host_name') 110 | 111 | # init # 112 | 113 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 114 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 115 | 116 | ansible_log.debug("== INSTALL ==") 117 | 118 | promote = installer.promote 119 | 120 | env = gen_env_boostrap_finalize_core(paths.ETC_IPA, 121 | constants.DEFAULT_CONFIG) 122 | api_bootstrap_finalize(env) 123 | config = gen_ReplicaConfig() 124 | config.subject_base = options.subject_base 125 | config.master_host_name = config_master_host_name 126 | 127 | remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA) 128 | installer._remote_api = remote_api 129 | 130 | conn = remote_api.Backend.ldap2 131 | ccache = os.environ['KRB5CCNAME'] 132 | 133 | # There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or 134 | # ntpinstance 135 | api.Backend.ldap2.connect() 136 | 137 | with redirect_stdout(ansible_log): 138 | if options.setup_dns: 139 | ansible_log.debug("-- INSTALL DNS --") 140 | dns.install(False, True, options, api) 141 | else: 142 | ansible_log.debug("-- DNS UPDATE_SYSTEM_RECORDS --") 143 | api.Command.dns_update_system_records() 144 | 145 | # done # 146 | 147 | ansible_module.exit_json(changed=True) 148 | 149 | if __name__ == '__main__': 150 | main() 151 | -------------------------------------------------------------------------------- /roles/ipareplica/library/ipareplica_setup_krb.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-replica-install code 8 | # 9 | # Copyright (C) 2018 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: ipareplica_setup_krb 36 | short description: Setup KRB 37 | description: 38 | Setup KRB 39 | options: 40 | setup_ca: 41 | description: 42 | required: yes 43 | setup_kra: 44 | description: 45 | required: yes 46 | no_pkinit: 47 | description: 48 | required: yes 49 | subject_base: 50 | description: 51 | required: yes 52 | config_master_host_name: 53 | description: 54 | required: yes 55 | ccache: 56 | description: 57 | required: yes 58 | _pkinit_pkcs12_info: 59 | description: 60 | required: yes 61 | _top_dir: 62 | description: 63 | required: yes 64 | author: 65 | - Thomas Woerner 66 | ''' 67 | 68 | EXAMPLES = ''' 69 | ''' 70 | 71 | RETURN = ''' 72 | ''' 73 | 74 | from ansible.module_utils.basic import AnsibleModule 75 | from ansible.module_utils.ansible_ipa_replica import * 76 | 77 | def main(): 78 | ansible_module = AnsibleModule( 79 | argument_spec = dict( 80 | #### server ### 81 | setup_ca=dict(required=False, type='bool'), 82 | setup_kra=dict(required=False, type='bool'), 83 | no_pkinit=dict(required=False, type='bool'), 84 | #### certificate system ### 85 | subject_base=dict(required=True), 86 | #### additional ### 87 | config_master_host_name=dict(required=True), 88 | ccache=dict(required=True), 89 | _pkinit_pkcs12_info = dict(required=False), 90 | _top_dir = dict(required=True), 91 | ), 92 | supports_check_mode = True, 93 | ) 94 | 95 | ansible_module._ansible_debug = True 96 | ansible_log = AnsibleModuleLog(ansible_module) 97 | 98 | # get parameters # 99 | 100 | options = installer 101 | ### server ### 102 | options.setup_ca = ansible_module.params.get('setup_ca') 103 | options.setup_kra = ansible_module.params.get('setup_kra') 104 | options.no_pkinit = ansible_module.params.get('no_pkinit') 105 | ### certificate system ### 106 | options.subject_base = ansible_module.params.get('subject_base') 107 | if options.subject_base is not None: 108 | options.subject_base = DN(options.subject_base) 109 | ### additional ### 110 | config_master_host_name = ansible_module.params.get('config_master_host_name') 111 | ccache = ansible_module.params.get('ccache') 112 | os.environ['KRB5CCNAME'] = ccache 113 | installer._pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info') 114 | 115 | options._top_dir = ansible_module.params.get('_top_dir') 116 | 117 | # init # 118 | 119 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 120 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 121 | 122 | ansible_log.debug("== INSTALL ==") 123 | 124 | options = installer 125 | promote = installer.promote 126 | pkinit_pkcs12_info = installer._pkinit_pkcs12_info 127 | 128 | env = gen_env_boostrap_finalize_core(paths.ETC_IPA, 129 | constants.DEFAULT_CONFIG) 130 | api_bootstrap_finalize(env) 131 | config = gen_ReplicaConfig() 132 | config.master_host_name = config_master_host_name 133 | config.subject_base = options.subject_base 134 | 135 | remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA) 136 | #installer._remote_api = remote_api 137 | 138 | conn = remote_api.Backend.ldap2 139 | ccache = os.environ['KRB5CCNAME'] 140 | 141 | # There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or 142 | # ntpinstance 143 | api.Backend.ldap2.connect() 144 | 145 | ansible_log.debug("-- INSTALL_KRB --") 146 | 147 | with redirect_stdout(ansible_log): 148 | krb = install_krb( 149 | config, 150 | setup_pkinit=not options.no_pkinit, 151 | pkcs12_info=pkinit_pkcs12_info, 152 | promote=promote) 153 | 154 | # done # 155 | 156 | ansible_module.exit_json(changed=True, 157 | config_master_host_name=config.master_host_name) 158 | 159 | if __name__ == '__main__': 160 | main() 161 | -------------------------------------------------------------------------------- /roles/ipareplica/library/ipareplica_setup_otpd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-replica-install code 8 | # 9 | # Copyright (C) 2018 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: ipareplica_setup_otpd 36 | short description: Setup OTPD 37 | description: 38 | Setup OTPD 39 | options: 40 | setup_ca: 41 | description: 42 | required: yes 43 | setup_kra: 44 | description: 45 | required: yes 46 | no_pkinit: 47 | description: 48 | required: yes 49 | no_ui_redirect: 50 | description: 51 | required: yes 52 | subject_base: 53 | description: 54 | required: yes 55 | config_master_host_name: 56 | description: 57 | required: yes 58 | ccache: 59 | description: 60 | required: yes 61 | _ca_enabled: 62 | description: 63 | required: yes 64 | _ca_file: 65 | description: 66 | required: yes 67 | _top_dir: 68 | description: 69 | required: yes 70 | dirman_password: 71 | description: 72 | required: yes 73 | author: 74 | - Thomas Woerner 75 | ''' 76 | 77 | EXAMPLES = ''' 78 | ''' 79 | 80 | RETURN = ''' 81 | ''' 82 | 83 | from ansible.module_utils.basic import AnsibleModule 84 | from ansible.module_utils.ansible_ipa_replica import * 85 | 86 | def main(): 87 | ansible_module = AnsibleModule( 88 | argument_spec = dict( 89 | #### server ### 90 | setup_ca=dict(required=False, type='bool'), 91 | setup_kra=dict(required=False, type='bool'), 92 | no_pkinit=dict(required=False, type='bool'), 93 | no_ui_redirect=dict(required=False, type='bool'), 94 | #### certificate system ### 95 | subject_base=dict(required=True), 96 | #### additional ### 97 | config_master_host_name=dict(required=True), 98 | ccache=dict(required=True), 99 | _ca_enabled=dict(required=False, type='bool'), 100 | _ca_file=dict(required=False), 101 | _top_dir = dict(required=True), 102 | dirman_password=dict(required=True, no_log=True), 103 | ), 104 | supports_check_mode = True, 105 | ) 106 | 107 | ansible_module._ansible_debug = True 108 | ansible_log = AnsibleModuleLog(ansible_module) 109 | 110 | # get parameters # 111 | 112 | options = installer 113 | options.setup_ca = ansible_module.params.get('setup_ca') 114 | options.setup_kra = ansible_module.params.get('setup_kra') 115 | options.no_pkinit = ansible_module.params.get('no_pkinit') 116 | ### certificate system ### 117 | options.subject_base = ansible_module.params.get('subject_base') 118 | if options.subject_base is not None: 119 | options.subject_base = DN(options.subject_base) 120 | ### additional ### 121 | master_host_name = ansible_module.params.get('config_master_host_name') 122 | ccache = ansible_module.params.get('ccache') 123 | os.environ['KRB5CCNAME'] = ccache 124 | #os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache') 125 | #installer._ccache = ansible_module.params.get('installer_ccache') 126 | ca_enabled = ansible_module.params.get('_ca_enabled') 127 | options._top_dir = ansible_module.params.get('_top_dir') 128 | dirman_password = ansible_module.params.get('dirman_password') 129 | 130 | # init # 131 | 132 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 133 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 134 | 135 | ansible_log.debug("== INSTALL ==") 136 | 137 | options = installer 138 | promote = installer.promote 139 | 140 | env = gen_env_boostrap_finalize_core(paths.ETC_IPA, 141 | constants.DEFAULT_CONFIG) 142 | api_bootstrap_finalize(env) 143 | config = gen_ReplicaConfig() 144 | config.dirman_password = dirman_password 145 | 146 | remote_api = gen_remote_api(master_host_name, paths.ETC_IPA) 147 | #installer._remote_api = remote_api 148 | 149 | conn = remote_api.Backend.ldap2 150 | ccache = os.environ['KRB5CCNAME'] 151 | 152 | # There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or 153 | # ntpinstance 154 | api.Backend.ldap2.connect() 155 | conn.connect(ccache=ccache) 156 | 157 | cafile = paths.IPA_CA_CRT 158 | with redirect_stdout(ansible_log): 159 | ansible_log.debug("-- INSTALL_OTPD --") 160 | 161 | otpd = otpdinstance.OtpdInstance() 162 | otpd.set_output(ansible_log) 163 | otpd.create_instance('OTPD', config.host_name, 164 | ipautil.realm_to_suffix(config.realm_name)) 165 | 166 | # done # 167 | 168 | ansible_module.exit_json(changed=True) 169 | 170 | if __name__ == '__main__': 171 | main() 172 | -------------------------------------------------------------------------------- /roles/ipareplica/library/ipaserver_enable_ipa.py: -------------------------------------------------------------------------------- 1 | ../../ipaserver/library/ipaserver_enable_ipa.py -------------------------------------------------------------------------------- /roles/ipareplica/library/ipaserver_master_password.py: -------------------------------------------------------------------------------- 1 | ../../ipaserver/library/ipaserver_master_password.py -------------------------------------------------------------------------------- /roles/ipareplica/library/ipaserver_setup_ntp.py: -------------------------------------------------------------------------------- 1 | ../../ipaserver/library/ipaserver_setup_ntp.py -------------------------------------------------------------------------------- /roles/ipareplica/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: Thomas Woerner 3 | description: A role to setup an IPA domain replica 4 | company: Red Hat, Inc 5 | 6 | # issue_tracker_url: http://example.com/issue/tracker 7 | 8 | license: GPLv3 9 | 10 | min_ansible_version: 2.0 11 | 12 | #github_branch: 13 | 14 | platforms: 15 | - name: Fedora 16 | versions: 17 | - 25 18 | - 26 19 | - 27 20 | - name: rhel 21 | versions: 22 | - 7.3 23 | - 7.4 24 | 25 | galaxy_tags: [ 'identity', 'ipa'] 26 | 27 | dependencies: [] 28 | -------------------------------------------------------------------------------- /roles/ipareplica/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for ipareplica 3 | 4 | - name: Import variables specific to distribution 5 | include_vars: "{{ item }}" 6 | with_first_found: 7 | - "vars/{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml" 8 | - "vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml" 9 | - "vars/{{ ansible_distribution }}.yml" 10 | - "vars/default.yml" 11 | 12 | - name: Install IPA replica 13 | include: tasks/install.yml 14 | when: state|default('present') == 'present' 15 | 16 | - name: Uninstall IPA replica 17 | include: tasks/uninstall.yml 18 | when: state|default('present') == 'absent' 19 | -------------------------------------------------------------------------------- /roles/ipareplica/tasks/python_2_3_test.yml: -------------------------------------------------------------------------------- 1 | - block: 2 | - name: Verify Python3 import 3 | script: py3test.py 4 | register: py3test 5 | failed_when: False 6 | changed_when: False 7 | 8 | - name: Set python interpreter to 3 9 | set_fact: 10 | ansible_python_interpreter: "/usr/bin/python3" 11 | when: py3test.rc == 0 12 | 13 | - name: Fail for IPA 4.5.90 14 | fail: msg="You need to install python2 bindings for ipa server usage" 15 | when: py3test.rc != 0 and "not usable with python3" in py3test.stdout 16 | 17 | - name: Set python interpreter to 2 18 | set_fact: 19 | ansible_python_interpreter: "/usr/bin/python2" 20 | when: py3test.failed or py3test.rc != 0 21 | -------------------------------------------------------------------------------- /roles/ipareplica/tasks/uninstall.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks to uninstall IPA replica 3 | 4 | #- name: Uninstall - Include Python2/3 import test 5 | # include: "{{role_path}}/tasks/python_2_3_test.yml" 6 | # static: yes 7 | 8 | - name: Uninstall - Uninstall IPA replica 9 | command: > 10 | /usr/sbin/ipa-server-install 11 | --uninstall 12 | -U 13 | {{ "--ignore-topology-disconnect" if ipareplica_ignore_topology_disconnect | bool else "" }} 14 | {{ "--ignore-last-of-role" if ipareplica_ignore_last_of_role | bool else "" }} 15 | register: result_uninstall 16 | # 2 means that uninstall failed because IPA replica was not configured 17 | failed_when: result_uninstall.rc != 0 and "'Env' object has no attribute 'basedn'" not in result_uninstall.stderr 18 | #IPA server is not configured on this system" not in result_uninstall.stdout_lines 19 | #changed_when: result_uninstall.rc == 0 20 | #until: result_uninstall.rc == 0 21 | retries: 2 22 | delay: 1 23 | 24 | - name: Uninstall - Remove all replication agreements and data about replica 25 | command: > 26 | /usr/sbin/ipa-replica-manage 27 | del 28 | {{ ipareplica_hostname | default(ansible_fqdn) }} 29 | --force 30 | --password={{ ipadm_password }} 31 | failed_when: False 32 | delegate_to: "{{ groups.ipaserver[0] | default(fail) }}" 33 | 34 | #- name: Remove IPA replica packages 35 | # package: 36 | # name: "{{ item }}" 37 | # state: absent 38 | # with_items: "{{ ipareplica_packages }}" 39 | -------------------------------------------------------------------------------- /roles/ipareplica/vars/CentOS-7.yml: -------------------------------------------------------------------------------- 1 | # defaults file for ipareplica 2 | # vars/RedHat-7.yml 3 | ipareplica_packages: [ "ipa-server", "libselinux-python" ] 4 | ipareplica_packages_dns: [ "ipa-server-dns" ] 5 | ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ] -------------------------------------------------------------------------------- /roles/ipareplica/vars/Fedora-25.yml: -------------------------------------------------------------------------------- 1 | # Fedora-25 defaults file for ipareplica 2 | # vars/Fedora-25.yml 3 | ipareplica_packages: [ "ipa-server", "libselinux-python" ] 4 | ipareplica_packages_dns: [ "ipa-server-dns" ] 5 | ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ] -------------------------------------------------------------------------------- /roles/ipareplica/vars/Fedora-26.yml: -------------------------------------------------------------------------------- 1 | # Fedora defaults file for ipareplica 2 | # vars/Fedora-26.yml 3 | ipareplica_packages: [ "ipa-server", "libselinux-python" ] 4 | ipareplica_packages_dns: [ "ipa-server-dns" ] 5 | ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ] -------------------------------------------------------------------------------- /roles/ipareplica/vars/Fedora-27.yml: -------------------------------------------------------------------------------- 1 | # Fedora defaults file for ipareplica 2 | # vars/Fedora.yml 3 | ipareplica_packages: [ "ipa-server", "libselinux-python" ] 4 | ipareplica_packages_dns: [ "ipa-server-dns" ] 5 | ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ] -------------------------------------------------------------------------------- /roles/ipareplica/vars/Fedora.yml: -------------------------------------------------------------------------------- 1 | # Fedora defaults file for ipareplica 2 | # vars/Fedora.yml 3 | ipareplica_packages: [ "freeipa-server", "python3-libselinux" ] 4 | ipareplica_packages_dns: [ "freeipa-server-dns" ] 5 | ipareplica_packages_adtrust: [ "freeipa-server-trust-ad" ] -------------------------------------------------------------------------------- /roles/ipareplica/vars/RedHat-7.3.yml: -------------------------------------------------------------------------------- 1 | # defaults file for ipareplica 2 | # vars/RedHat-7.3.yml 3 | ipareplica_packages: [ "ipa-server", "libselinux-python" ] 4 | ipareplica_packages_dns: [ "ipa-server-dns" ] 5 | ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ] -------------------------------------------------------------------------------- /roles/ipareplica/vars/RedHat-7.yml: -------------------------------------------------------------------------------- 1 | # defaults file for ipareplica 2 | # vars/RedHat-7.yml 3 | ipareplica_packages: [ "ipa-server", "libselinux-python" ] 4 | ipareplica_packages_dns: [ "ipa-server-dns" ] 5 | ipareplica_packages_adtrust: [ "ipa-server-trust-ad" ] -------------------------------------------------------------------------------- /roles/ipareplica/vars/Ubuntu.yml: -------------------------------------------------------------------------------- 1 | # vars/Ubuntu.yml 2 | ipareplica_packages: [ "freeipa-server" ] 3 | ipareplica_packages_dns: [ "freeipa-server-dns" ] 4 | ipareplica_packages_adtrust: [ ] 5 | -------------------------------------------------------------------------------- /roles/ipareplica/vars/default.yml: -------------------------------------------------------------------------------- 1 | # defaults file for ipareplica 2 | # vars/default.yml 3 | ipareplica_packages: [ "freeipa-server", "python3-libselinux" ] 4 | ipareplica_packages_dns: [ "freeipa-server-dns" ] 5 | ipareplica_packages_adtrust: [ "freeipa-server-trust-ad" ] 6 | -------------------------------------------------------------------------------- /roles/ipaserver/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for ipaserver 3 | 4 | ### basic ### 5 | ipaserver_no_host_dns: no 6 | ### server ### 7 | ipaserver_setup_adtrust: no 8 | ipaserver_setup_kra: no 9 | ipaserver_setup_dns: yes 10 | ipaserver_no_hbac_allow: no 11 | ipaserver_no_pkinit: no 12 | ipaserver_no_ui_redirect: no 13 | ### ssl certificate ### 14 | ### client ### 15 | ipaclient_mkhomedir: no 16 | ipaclient_no_ntp: yes 17 | #ipaclient_ssh_trust_dns: no 18 | #ipaclient_no_ssh: no 19 | #ipaclient_no_sshd: no 20 | #ipaclient_no_dns_sshfp: no 21 | ### certificate system ### 22 | ipaserver_external_ca: no 23 | ### dns ### 24 | ipaserver_allow_zone_overlap: no 25 | ipaserver_no_reverse: no 26 | ipaserver_auto_reverse: no 27 | ipaserver_no_forwarders: no 28 | ipaserver_auto_forwarders: no 29 | ipaserver_no_dnssec_validation: no 30 | ### ad trust ### 31 | ipaserver_enable_compat: no 32 | ipaserver_setup_ca: yes 33 | ### firewalld ### 34 | ipaserver_no_firewalld: no 35 | 36 | ### additional ### 37 | ipaserver_allow_missing: [ ] 38 | 39 | ### uninstall ### 40 | ipaserver_ignore_topology_disconnect: no 41 | ipaserver_ignore_last_of_role: no 42 | -------------------------------------------------------------------------------- /roles/ipaserver/files/py3test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # Test ipaerver python3 binding 4 | from ipaserver.install.server.install import install_check 5 | 6 | # Check ipapython version to be >= 4.6 7 | from ipapython.version import NUM_VERSION, VERSION 8 | if NUM_VERSION < 40590: 9 | raise Exception("ipa %s not usable with python3" % VERSION) 10 | -------------------------------------------------------------------------------- /roles/ipaserver/library/ipaserver_enable_ipa.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-server-install code 8 | # 9 | # Copyright (C) 2017 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: enable_ipa 36 | short description: 37 | description: 38 | options: 39 | author: 40 | - Thomas Woerner 41 | ''' 42 | 43 | EXAMPLES = ''' 44 | ''' 45 | 46 | RETURN = ''' 47 | ''' 48 | 49 | from ansible.module_utils.basic import AnsibleModule 50 | from ansible.module_utils.ansible_ipa_server import * 51 | 52 | def main(): 53 | ansible_module = AnsibleModule( 54 | argument_spec = dict( 55 | hostname=dict(required=False), 56 | setup_ca=dict(required=True, type='bool'), 57 | ), 58 | ) 59 | 60 | ansible_module._ansible_debug = True 61 | ansible_log = AnsibleModuleLog(ansible_module) 62 | 63 | # set values ############################################################# 64 | 65 | options.host_name = ansible_module.params.get('hostname') 66 | options.setup_ca = ansible_module.params.get('setup_ca') 67 | 68 | # Configuration for ipalib, we will bootstrap and finalize later, after 69 | # we are sure we have the configuration file ready. 70 | cfg = dict( 71 | context='installer', 72 | confdir=paths.ETC_IPA, 73 | in_server=True, 74 | # make sure host name specified by user is used instead of default 75 | host=options.host_name, 76 | ) 77 | if options.setup_ca: 78 | # we have an IPA-integrated CA 79 | cfg['ca_host'] = options.host_name 80 | 81 | api.bootstrap(**cfg) 82 | api.finalize() 83 | api.Backend.ldap2.connect() 84 | 85 | # setup ds ###################################################### 86 | 87 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 88 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 89 | 90 | if NUM_VERSION < 40600: 91 | # Make sure the files we crated in /var/run are recreated at startup 92 | tasks.configure_tmpfiles() 93 | 94 | with redirect_stdout(ansible_log): 95 | services.knownservices.ipa.enable() 96 | 97 | ansible_module.exit_json(changed=True) 98 | 99 | if __name__ == '__main__': 100 | main() 101 | -------------------------------------------------------------------------------- /roles/ipaserver/library/ipaserver_load_cache.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-client-install code 8 | # 9 | # Copyright (C) 2017 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: ipaserver_load_cache 36 | short description: 37 | description: 38 | options: 39 | dm_password: 40 | author: 41 | - Thomas Woerner 42 | ''' 43 | 44 | EXAMPLES = ''' 45 | ''' 46 | 47 | RETURN = ''' 48 | ''' 49 | 50 | from ansible.module_utils.basic import AnsibleModule 51 | from ansible.module_utils.ansible_ipa_server import * 52 | 53 | def main(): 54 | ansible_module = AnsibleModule( 55 | argument_spec = dict( 56 | ### basic ### 57 | dm_password=dict(required=True, no_log=True), 58 | ), 59 | ) 60 | 61 | ansible_module._ansible_debug = True 62 | ansible_log = AnsibleModuleLog(ansible_module) 63 | 64 | # set values ############################################################ 65 | 66 | ### basic ### 67 | options.dm_password = ansible_module.params.get('dm_password') 68 | 69 | # restore cache ######################################################### 70 | 71 | if os.path.isfile(paths.ROOT_IPA_CACHE): 72 | if options.dm_password is None: 73 | ansible_module.fail_json(msg="Directory Manager password required") 74 | try: 75 | cache_vars = read_cache(dm_password) 76 | options.__dict__.update(cache_vars) 77 | if cache_vars.get('external_ca', False): 78 | options.external_ca = False 79 | options.interactive = False 80 | except Exception as e: 81 | ansible_module.fail_json( 82 | msg="Cannot process the cache file: %s" % str(e)) 83 | 84 | kwargs = { "changed": True } 85 | for name in options.__dict__: 86 | kwargs[name] = options.__dict__[name] 87 | ansible_module.exit_json(kwargs) 88 | 89 | # done ################################################################## 90 | 91 | ansible_module.exit_json(changed=False) 92 | 93 | if __name__ == '__main__': 94 | main() 95 | -------------------------------------------------------------------------------- /roles/ipaserver/library/ipaserver_master_password.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-server-install code 8 | # 9 | # Copyright (C) 2017 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | ANSIBLE_METADATA = { 26 | 'metadata_version': '1.0', 27 | 'supported_by': 'community', 28 | 'status': ['preview'], 29 | } 30 | 31 | DOCUMENTATION = ''' 32 | --- 33 | module: master_password 34 | short description: Generate kerberos master password if not given 35 | description: 36 | Generate kerberos master password if not given 37 | options: 38 | master_password: 39 | description: kerberos master password (normally autogenerated) 40 | required: false 41 | author: 42 | - Thomas Woerner 43 | ''' 44 | 45 | EXAMPLES = ''' 46 | ''' 47 | 48 | RETURN = ''' 49 | password: 50 | description: The master password 51 | returned: always 52 | ''' 53 | 54 | import os 55 | 56 | from ansible.module_utils.basic import AnsibleModule 57 | from ansible.module_utils.ansible_ipa_server import * 58 | 59 | def main(): 60 | module = AnsibleModule( 61 | argument_spec = dict( 62 | #basic 63 | dm_password=dict(required=True, no_log=True), 64 | master_password=dict(required=False, no_log=True), 65 | ), 66 | supports_check_mode = True, 67 | ) 68 | 69 | module._ansible_debug = True 70 | 71 | options.dm_password = module.params.get('dm_password') 72 | options.master_password = module.params.get('master_password') 73 | 74 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 75 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 76 | 77 | # This will override any settings passed in on the cmdline 78 | if os.path.isfile(paths.ROOT_IPA_CACHE): 79 | # dm_password check removed, checked already 80 | try: 81 | cache_vars = read_cache(options.dm_password) 82 | options.__dict__.update(cache_vars) 83 | except Exception as e: 84 | module.fail_json(msg="Cannot process the cache file: %s" % str(e)) 85 | 86 | if not options.master_password: 87 | options.master_password = ipa_generate_password() 88 | 89 | module.exit_json(changed=True, 90 | password=options.master_password) 91 | 92 | if __name__ == '__main__': 93 | main() 94 | -------------------------------------------------------------------------------- /roles/ipaserver/library/ipaserver_set_ds_password.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-client-install code 8 | # 9 | # Copyright (C) 2017 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: set_ds_password 36 | short description: 37 | description: 38 | options: 39 | author: 40 | - Thomas Woerner 41 | ''' 42 | 43 | EXAMPLES = ''' 44 | ''' 45 | 46 | RETURN = ''' 47 | ''' 48 | 49 | from ansible.module_utils.basic import AnsibleModule 50 | from ansible.module_utils.ansible_ipa_server import * 51 | 52 | def main(): 53 | ansible_module = AnsibleModule( 54 | argument_spec = dict( 55 | ### basic ### 56 | dm_password=dict(required=True, no_log=True), 57 | password=dict(required=True, no_log=True), 58 | domain=dict(required=True), 59 | realm=dict(required=True), 60 | hostname=dict(required=True), 61 | ### server ### 62 | setup_ca=dict(required=True, type='bool'), 63 | idstart=dict(required=True, type='int'), 64 | idmax=dict(required=True, type='int'), 65 | no_hbac_allow=dict(required=False, type='bool', default=False), 66 | no_pkinit=dict(required=False, type='bool', default=False), 67 | dirsrv_config_file=dict(required=False), 68 | _dirsrv_pkcs12_info=dict(required=False), 69 | ### ssl certificate ### 70 | dirsrv_cert_files=dict(required=False, type='list', default=[]), 71 | subject_base=dict(required=False), 72 | ca_subject=dict(required=False), 73 | ### certificate system ### 74 | external_cert_files=dict(required=False, type='list', default=[]), 75 | ### additional ### 76 | domainlevel=dict(required=False, type='int', 77 | default=MAX_DOMAIN_LEVEL), 78 | ), 79 | ) 80 | 81 | ansible_module._ansible_debug = True 82 | ansible_log = AnsibleModuleLog(ansible_module) 83 | 84 | # set values #################################################### 85 | 86 | ### basic ### 87 | options.dm_password = ansible_module.params.get('dm_password') 88 | options.admin_password = ansible_module.params.get('password') 89 | options.domain_name = ansible_module.params.get('domain') 90 | options.realm_name = ansible_module.params.get('realm') 91 | options.host_name = ansible_module.params.get('hostname') 92 | ### server ### 93 | options.setup_ca = ansible_module.params.get('setup_ca') 94 | options.idstart = ansible_module.params.get('idstart') 95 | options.idmax = ansible_module.params.get('idmax') 96 | options.no_hbac_allow = ansible_module.params.get('no_hbac_allow') 97 | options.no_pkinit = ansible_module.params.get('no_pkinit') 98 | options.dirsrv_config_file = ansible_module.params.get('dirsrv_config_file') 99 | options._dirsrv_pkcs12_info = ansible_module.params.get( 100 | '_dirsrv_pkcs12_info') 101 | ### ssl certificate ### 102 | options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files') 103 | options.subject_base = ansible_module.params.get('subject_base') 104 | options.ca_subject = ansible_module.params.get('ca_subject') 105 | ### certificate system ### 106 | options.external_cert_files = ansible_module.params.get( 107 | 'external_cert_files') 108 | ### additional ### 109 | options.domainlevel = ansible_module.params.get('domainlevel') 110 | options.domain_level = options.domainlevel 111 | 112 | # init ########################################################## 113 | 114 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 115 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 116 | 117 | api_Backend_ldap2(options.host_name, options.setup_ca, connect=True) 118 | 119 | ds = ds_init_info(ansible_log, fstore, 120 | options.domainlevel, options.dirsrv_config_file, 121 | options.realm_name, options.host_name, 122 | options.domain_name, options.dm_password, 123 | options.idstart, options.idmax, 124 | options.subject_base, options.ca_subject, 125 | options.no_hbac_allow, options._dirsrv_pkcs12_info, 126 | options.no_pkinit) 127 | 128 | # set ds password ############################################### 129 | 130 | with redirect_stdout(ansible_log): 131 | ds.change_admin_password(options.admin_password) 132 | 133 | # done ########################################################## 134 | 135 | ansible_module.exit_json(changed=True) 136 | 137 | if __name__ == '__main__': 138 | main() 139 | -------------------------------------------------------------------------------- /roles/ipaserver/library/ipaserver_setup_adtrust.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-client-install code 8 | # 9 | # Copyright (C) 2017 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: setup_adtrust 36 | short description: 37 | description: 38 | options: 39 | author: 40 | - Thomas Woerner 41 | ''' 42 | 43 | EXAMPLES = ''' 44 | ''' 45 | 46 | RETURN = ''' 47 | ''' 48 | 49 | from ansible.module_utils.basic import AnsibleModule 50 | from ansible.module_utils.ansible_ipa_server import * 51 | 52 | def main(): 53 | ansible_module = AnsibleModule( 54 | argument_spec = dict( 55 | # basic 56 | hostname=dict(required=False), 57 | setup_ca=dict(required=True, type='bool', default=False), 58 | setup_adtrust=dict(required=True, type='bool', default=False), 59 | ), 60 | ) 61 | 62 | ansible_module._ansible_debug = True 63 | ansible_log = AnsibleModuleLog(ansible_module) 64 | 65 | # set values #################################################### 66 | 67 | options.host_name = ansible_module.params.get('hostname') 68 | options.setup_ca = ansible_module.params.get('setup_ca') 69 | options.setup_adtrust = ansible_module.params.get('setup_adtrust') 70 | 71 | # init ########################################################## 72 | 73 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 74 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 75 | 76 | api_Backend_ldap2_connect(options.host_name, options.setup_ca) 77 | 78 | # setup ds ###################################################### 79 | 80 | with redirect_stdout(ansible_log): 81 | adtrust.install(False, options, fstore, api) 82 | 83 | # done ########################################################## 84 | 85 | ansible_module.exit_json(changed=True) 86 | 87 | if __name__ == '__main__': 88 | main() 89 | -------------------------------------------------------------------------------- /roles/ipaserver/library/ipaserver_setup_custodia.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-client-install code 8 | # 9 | # Copyright (C) 2017 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: ipaserver_setup_custodia 36 | short description: 37 | description: 38 | options: 39 | realm: 40 | hostname: 41 | setup_ca: 42 | author: 43 | - Thomas Woerner 44 | ''' 45 | 46 | EXAMPLES = ''' 47 | ''' 48 | 49 | RETURN = ''' 50 | ''' 51 | 52 | from ansible.module_utils.basic import AnsibleModule 53 | from ansible.module_utils.ansible_ipa_server import * 54 | 55 | def main(): 56 | ansible_module = AnsibleModule( 57 | argument_spec = dict( 58 | # basic 59 | realm=dict(required=True), 60 | hostname=dict(required=False), 61 | setup_ca=dict(required=False, type='bool', default=False), 62 | ), 63 | ) 64 | 65 | ansible_module._ansible_debug = True 66 | ansible_log = AnsibleModuleLog(ansible_module) 67 | 68 | # set values ############################################################ 69 | 70 | options.realm_name = ansible_module.params.get('realm') 71 | options.host_name = ansible_module.params.get('hostname') 72 | options.setup_ca = ansible_module.params.get('setup_ca') 73 | 74 | # init ################################################################## 75 | 76 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 77 | 78 | api_Backend_ldap2(options.host_name, options.setup_ca, connect=True) 79 | 80 | # setup custodia ######################################################## 81 | 82 | custodia = custodiainstance.CustodiaInstance(options.host_name, 83 | options.realm_name) 84 | custodia.set_output(ansible_log) 85 | with redirect_stdout(ansible_log): 86 | custodia.create_instance() 87 | 88 | # done ################################################################## 89 | 90 | ansible_module.exit_json(changed=True) 91 | 92 | if __name__ == '__main__': 93 | main() 94 | -------------------------------------------------------------------------------- /roles/ipaserver/library/ipaserver_setup_dns.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-client-install code 8 | # 9 | # Copyright (C) 2017 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: setup_dns 36 | short description: 37 | description: 38 | options: 39 | hostname: 40 | setup_dns: 41 | setup_ca: 42 | zonemgr: 43 | forwarders: 44 | forward_policy: 45 | no_dnssec_validation: 46 | author: 47 | - Thomas Woerner 48 | ''' 49 | 50 | EXAMPLES = ''' 51 | ''' 52 | 53 | RETURN = ''' 54 | ''' 55 | 56 | from ansible.module_utils.basic import AnsibleModule 57 | from ansible.module_utils.ansible_ipa_server import * 58 | 59 | def main(): 60 | ansible_module = AnsibleModule( 61 | argument_spec = dict( 62 | ### basic ### 63 | hostname=dict(required=True), 64 | ### server ### 65 | setup_dns=dict(required=True, type='bool'), 66 | setup_ca=dict(required=True, type='bool'), 67 | ### dns ### 68 | zonemgr=dict(required=False), 69 | forwarders=dict(required=True, type='list'), 70 | forward_policy=dict(default='first', choices=['first', 'only']), 71 | no_dnssec_validation=dict(required=False, type='bool', 72 | default=False), 73 | ### additional ### 74 | dns_ip_addresses=dict(required=True, type='list'), 75 | dns_reverse_zones=dict(required=True, type='list'), 76 | ), 77 | ) 78 | 79 | ansible_module._ansible_debug = True 80 | ansible_log = AnsibleModuleLog(ansible_module) 81 | 82 | # set values ############################################################ 83 | 84 | ### basic ### 85 | options.host_name = ansible_module.params.get('hostname') 86 | ### server ### 87 | options.setup_dns = ansible_module.params.get('setup_dns') 88 | options.setup_ca = ansible_module.params.get('setup_ca') 89 | ### dns ### 90 | options.zonemgr = ansible_module.params.get('zonemgr') 91 | options.forwarders = ansible_module.params.get('forwarders') 92 | options.forward_policy = ansible_module.params.get('forward_policy') 93 | options.no_dnssec_validation = ansible_module.params.get( 94 | 'no_dnssec_validation') 95 | ### additional ### 96 | dns.ip_addresses = ansible_module_get_parsed_ip_addresses( 97 | ansible_module, 'dns_ip_addresses') 98 | dns.reverse_zones = ansible_module.params.get('dns_reverse_zones') 99 | 100 | # init ################################################################## 101 | 102 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 103 | 104 | api_Backend_ldap2(options.host_name, options.setup_ca, connect=True) 105 | 106 | # setup dns ############################################################# 107 | 108 | with redirect_stdout(ansible_log): 109 | if options.setup_dns: 110 | dns.install(False, False, options) 111 | else: 112 | # Create a BIND instance 113 | bind = bindinstance.BindInstance(fstore) 114 | bind.set_output(ansible_log) 115 | bind.setup(host_name, ip_addresses, realm_name, 116 | domain_name, (), 'first', (), 117 | zonemgr=options.zonemgr, 118 | no_dnssec_validation=options.no_dnssec_validation) 119 | bind.create_file_with_system_records() 120 | 121 | # done ################################################################## 122 | 123 | ansible_module.exit_json(changed=True) 124 | 125 | if __name__ == '__main__': 126 | main() 127 | -------------------------------------------------------------------------------- /roles/ipaserver/library/ipaserver_setup_kra.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-client-install code 8 | # 9 | # Copyright (C) 2017 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: setup_kra 36 | short description: 37 | description: 38 | options: 39 | author: 40 | - Thomas Woerner 41 | ''' 42 | 43 | EXAMPLES = ''' 44 | ''' 45 | 46 | RETURN = ''' 47 | ''' 48 | 49 | from ansible.module_utils.basic import AnsibleModule 50 | from ansible.module_utils.ansible_ipa_server import * 51 | 52 | def main(): 53 | ansible_module = AnsibleModule( 54 | argument_spec = dict( 55 | # basic 56 | dm_password=dict(required=True, no_log=True), 57 | hostname=dict(required=True), 58 | setup_ca=dict(required=True, type='bool'), 59 | setup_kra=dict(required=True, type='bool'), 60 | realm=dict(required=True), 61 | ), 62 | ) 63 | 64 | ansible_module._ansible_debug = True 65 | ansible_log = AnsibleModuleLog(ansible_module) 66 | 67 | # set values #################################################### 68 | 69 | options.dm_password = ansible_module.params.get('dm_password') 70 | options.host_name = ansible_module.params.get('hostname') 71 | options.setup_ca = ansible_module.params.get('setup_ca') 72 | options.setup_kra = ansible_module.params.get('setup_kra') 73 | options.realm_name = ansible_module.params.get('realm') 74 | options.promote = False # first master, no promotion 75 | 76 | # init ########################################################## 77 | 78 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 79 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 80 | 81 | api_Backend_ldap2(options.host_name, options.setup_ca, connect=True) 82 | 83 | # setup kra ##################################################### 84 | 85 | with redirect_stdout(ansible_log): 86 | if hasattr(custodiainstance, "get_custodia_instance"): 87 | custodia = custodiainstance.get_custodia_instance( 88 | options, custodiainstance.CustodiaModes.MASTER_PEER) 89 | custodia.create_instance() 90 | 91 | kra.install(api, None, options, custodia=custodia) 92 | else: 93 | kra.install(api, None, options) 94 | 95 | # done ########################################################## 96 | 97 | ansible_module.exit_json(changed=True) 98 | 99 | if __name__ == '__main__': 100 | main() 101 | -------------------------------------------------------------------------------- /roles/ipaserver/library/ipaserver_setup_krb.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-client-install code 8 | # 9 | # Copyright (C) 2017 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: setup_ds 36 | short description: 37 | description: 38 | options: 39 | author: 40 | - Thomas Woerner 41 | ''' 42 | 43 | EXAMPLES = ''' 44 | ''' 45 | 46 | RETURN = ''' 47 | ''' 48 | 49 | from ansible.module_utils.basic import AnsibleModule 50 | from ansible.module_utils.ansible_ipa_server import * 51 | 52 | def main(): 53 | ansible_module = AnsibleModule( 54 | argument_spec = dict( 55 | # basic 56 | dm_password=dict(required=True, no_log=True), 57 | password=dict(required=True, no_log=True), 58 | master_password=dict(required=True, no_log=True), 59 | domain=dict(required=True), 60 | realm=dict(required=True), 61 | hostname=dict(required=False), 62 | 63 | ip_addresses=dict(required=False, type='list', default=[]), 64 | reverse_zones=dict(required=False, type='list', default=[]), 65 | 66 | setup_adtrust=dict(required=False, type='bool', default=False), 67 | setup_kra=dict(required=False, type='bool', default=False), 68 | setup_dns=dict(required=False, type='bool', default=False), 69 | setup_ca=dict(required=False, type='bool', default=False), 70 | 71 | no_host_dns=dict(required=False, type='bool', default=False), 72 | no_pkinit=dict(required=False, type='bool', default=False), 73 | no_hbac_allow=dict(required=False, type='bool', default=False), 74 | 75 | external_cert_files=dict(required=False, type='list', default=[]), 76 | subject_base=dict(required=False), 77 | ca_subject=dict(required=False), 78 | 79 | idstart=dict(required=True, type='int'), 80 | idmax=dict(required=True, type='int'), 81 | 82 | no_reverse=dict(required=False, type='bool', default=False), 83 | auto_forwarders=dict(required=False, type='bool', default=False), 84 | 85 | _pkinit_pkcs12_info=dict(required=False), 86 | ), 87 | ) 88 | 89 | ansible_module._ansible_debug = True 90 | ansible_log = AnsibleModuleLog(ansible_module) 91 | 92 | # set values ############################################################ 93 | 94 | options.dm_password = ansible_module.params.get('dm_password') 95 | options.admin_password = ansible_module.params.get('password') 96 | options.master_password = ansible_module.params.get('master_password') 97 | options.domain_name = ansible_module.params.get('domain') 98 | options.realm_name = ansible_module.params.get('realm') 99 | options.host_name = ansible_module.params.get('hostname') 100 | 101 | options.ip_addresses = ansible_module_get_parsed_ip_addresses( 102 | ansible_module) 103 | options.reverse_zones = ansible_module.params.get('reverse_zones') 104 | 105 | options.setup_adtrust = ansible_module.params.get('setup_adtrust') 106 | options.setup_kra = ansible_module.params.get('setup_kra') 107 | options.setup_dns = ansible_module.params.get('setup_dns') 108 | options.setup_ca = ansible_module.params.get('setup_ca') 109 | 110 | options.no_host_dns = ansible_module.params.get('no_host_dns') 111 | options.no_pkinit = ansible_module.params.get('no_pkinit') 112 | options.no_hbac_allow = ansible_module.params.get('no_hbac_allow') 113 | 114 | options.external_cert_files = ansible_module.params.get( 115 | 'external_cert_files') 116 | options.subject_base = ansible_module.params.get('subject_base') 117 | options.ca_subject = ansible_module.params.get('ca_subject') 118 | 119 | options.no_reverse = ansible_module.params.get('no_reverse') 120 | options.auto_forwarders = ansible_module.params.get('auto_forwarders') 121 | 122 | options.idstart = ansible_module.params.get('idstart') 123 | options.idmax = ansible_module.params.get('idmax') 124 | 125 | options._pkinit_pkcs12_info = ansible_module.params.get( 126 | '_pkinit_pkcs12_info') 127 | 128 | #options._update_hosts_file = ansible_module.params.get('update_hosts_file') 129 | 130 | # init ################################################################## 131 | 132 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 133 | 134 | api_Backend_ldap2(options.host_name, options.setup_ca, connect=True) 135 | 136 | # setup KRB ############################################################# 137 | 138 | krb = krbinstance.KrbInstance(fstore) 139 | krb.set_output(ansible_log) 140 | with redirect_stdout(ansible_log): 141 | if not options.external_cert_files: 142 | krb.create_instance(options.realm_name, options.host_name, 143 | options.domain_name, 144 | options.dm_password, options.master_password, 145 | setup_pkinit=not options.no_pkinit, 146 | pkcs12_info=options._pkinit_pkcs12_info, 147 | subject_base=options.subject_base) 148 | else: 149 | krb.init_info(options.realm_name, options.host_name, 150 | setup_pkinit=not options.no_pkinit, 151 | subject_base=options.subject_base) 152 | 153 | ansible_module.exit_json(changed=True) 154 | 155 | if __name__ == '__main__': 156 | main() 157 | -------------------------------------------------------------------------------- /roles/ipaserver/library/ipaserver_setup_ntp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-client-install code 8 | # 9 | # Copyright (C) 2017 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: setup_ntp 36 | short description: 37 | description: 38 | options: 39 | author: 40 | - Thomas Woerner 41 | ''' 42 | 43 | EXAMPLES = ''' 44 | ''' 45 | 46 | RETURN = ''' 47 | ''' 48 | 49 | from ansible.module_utils.basic import AnsibleModule 50 | from ansible.module_utils.ansible_ipa_server import * 51 | 52 | def main(): 53 | ansible_module = AnsibleModule( 54 | argument_spec = dict(), 55 | ) 56 | 57 | ansible_module._ansible_debug = True 58 | ansible_log = AnsibleModuleLog(ansible_module) 59 | 60 | # init ########################################################## 61 | 62 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 63 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 64 | 65 | # setup NTP ##################################################### 66 | 67 | if time_service == "chronyd": 68 | # We have to sync time before certificate handling on master. 69 | # As chrony configuration is moved from client here, unconfiguration of 70 | # chrony will be handled here in uninstall() method as well by invoking 71 | # the ipa-server-install --uninstall 72 | ansible_module.log("Synchronizing time") 73 | options.ntp_servers = None 74 | options.ntp_pool = None 75 | if sync_time(options, fstore, sstore): 76 | ansible_module.log("Time synchronization was successful.") 77 | else: 78 | ansible_module.warn("IPA was unable to sync time with chrony!") 79 | ansible_module.warn("Time synchronization is required for IPA " 80 | "to work correctly") 81 | else: 82 | # Configure ntpd 83 | timeconf.force_ntpd(sstore) 84 | ntp = ntpinstance.NTPInstance(fstore) 85 | ntp.set_output(ansible_log) 86 | with redirect_stdout(ansible_log): 87 | if not ntp.is_configured(): 88 | ntp.create_instance() 89 | 90 | # done ########################################################## 91 | 92 | ansible_module.exit_json(changed=True) 93 | 94 | if __name__ == '__main__': 95 | main() 96 | -------------------------------------------------------------------------------- /roles/ipaserver/library/ipaserver_setup_otpd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Authors: 5 | # Thomas Woerner 6 | # 7 | # Based on ipa-client-install code 8 | # 9 | # Copyright (C) 2017 Red Hat 10 | # see file 'COPYING' for use and warranty information 11 | # 12 | # This program 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 program 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 program. If not, see . 24 | 25 | from __future__ import print_function 26 | 27 | ANSIBLE_METADATA = { 28 | 'metadata_version': '1.0', 29 | 'supported_by': 'community', 30 | 'status': ['preview'], 31 | } 32 | 33 | DOCUMENTATION = ''' 34 | --- 35 | module: setup_otpd 36 | short description: 37 | description: 38 | options: 39 | author: 40 | - Thomas Woerner 41 | ''' 42 | 43 | EXAMPLES = ''' 44 | ''' 45 | 46 | RETURN = ''' 47 | ''' 48 | 49 | from ansible.module_utils.basic import AnsibleModule 50 | from ansible.module_utils.ansible_ipa_server import * 51 | 52 | def main(): 53 | ansible_module = AnsibleModule( 54 | argument_spec = dict( 55 | # basic 56 | realm=dict(required=True), 57 | hostname=dict(required=False), 58 | setup_ca=dict(required=False, type='bool', default=False), 59 | ), 60 | ) 61 | 62 | ansible_module._ansible_debug = True 63 | ansible_log = AnsibleModuleLog(ansible_module) 64 | 65 | # set values #################################################### 66 | 67 | options.realm_name = ansible_module.params.get('realm') 68 | options.host_name = ansible_module.params.get('hostname') 69 | options.setup_ca = ansible_module.params.get('setup_ca') 70 | 71 | # init ########################################################## 72 | 73 | fstore = sysrestore.FileStore(paths.SYSRESTORE) 74 | sstore = sysrestore.StateFile(paths.SYSRESTORE) 75 | 76 | api_Backend_ldap2(options.host_name, options.setup_ca, connect=True) 77 | 78 | # setup ds ###################################################### 79 | 80 | otpd = otpdinstance.OtpdInstance() 81 | otpd.set_output(ansible_log) 82 | with redirect_stdout(ansible_log): 83 | otpd.create_instance('OTPD', options.host_name, 84 | ipautil.realm_to_suffix(options.realm_name)) 85 | 86 | # done ########################################################## 87 | 88 | ansible_module.exit_json(changed=True) 89 | 90 | if __name__ == '__main__': 91 | main() 92 | -------------------------------------------------------------------------------- /roles/ipaserver/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: Thomas Woerner 3 | description: A role to setup an iPA domain server 4 | company: Red Hat, Inc 5 | 6 | # issue_tracker_url: http://example.com/issue/tracker 7 | 8 | license: GPLv3 9 | 10 | min_ansible_version: 2.0 11 | 12 | #github_branch: 13 | 14 | platforms: 15 | - name: Fedora 16 | versions: 17 | - 25 18 | - 26 19 | - 27 20 | - name: rhel 21 | versions: 22 | - 7.3 23 | - 7.4 24 | 25 | galaxy_tags: [ 'identity', 'ipa'] 26 | 27 | dependencies: [] 28 | -------------------------------------------------------------------------------- /roles/ipaserver/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for ipaserver 3 | 4 | - name: Import variables specific to distribution 5 | include_vars: "{{ item }}" 6 | with_first_found: 7 | - "vars/{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml" 8 | - "vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml" 9 | - "vars/{{ ansible_distribution }}.yml" 10 | - "vars/default.yml" 11 | 12 | - name: Install IPA server 13 | include: tasks/install.yml 14 | when: state|default('present') == 'present' 15 | 16 | - name: Uninstall IPA server 17 | include: tasks/uninstall.yml 18 | when: state|default('present') == 'absent' 19 | -------------------------------------------------------------------------------- /roles/ipaserver/tasks/python_2_3_test.yml: -------------------------------------------------------------------------------- 1 | - block: 2 | - name: Verify Python3 import 3 | script: py3test.py 4 | register: py3test 5 | failed_when: False 6 | changed_when: False 7 | 8 | - name: Set python interpreter to 3 9 | set_fact: 10 | ansible_python_interpreter: "/usr/bin/python3" 11 | when: py3test.rc == 0 12 | 13 | - name: Fail for IPA 4.5.90 14 | fail: msg="You need to install python2 bindings for ipa server usage" 15 | when: py3test.rc != 0 and "not usable with python3" in py3test.stdout 16 | 17 | - name: Set python interpreter to 2 18 | set_fact: 19 | ansible_python_interpreter: "/usr/bin/python2" 20 | when: py3test.failed or py3test.rc != 0 21 | -------------------------------------------------------------------------------- /roles/ipaserver/tasks/uninstall.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks to uninstall IPA server 3 | 4 | #- name: Uninstall - Include Python2/3 import test 5 | # include: "{{role_path}}/tasks/python_2_3_test.yml" 6 | # static: yes 7 | 8 | - name: Uninstall - Uninstall IPA server 9 | command: > 10 | /usr/sbin/ipa-server-install 11 | --uninstall 12 | -U 13 | {{ '--ignore-topology-disconnect' if ipaserver_ignore_topology_disconnect | bool else '' }} 14 | {{ '--ignore-last-of-role' if ipaserver_ignore_last_of_role | bool else ''}} 15 | register: uninstall 16 | # 1 means that uninstall failed because IPA server was not configured 17 | failed_when: uninstall.rc != 0 and uninstall.rc != 1 18 | changed_when: uninstall.rc == 0 19 | 20 | #- name: Remove IPA server packages 21 | # package: 22 | # name: "{{ item }}" 23 | # state: absent 24 | # with_items: "{{ ipaserver_packages }}" 25 | -------------------------------------------------------------------------------- /roles/ipaserver/vars/CentOS-7.yml: -------------------------------------------------------------------------------- 1 | # defaults file for ipaserver 2 | # vars/rhel.yml 3 | ipaserver_packages: [ "ipa-server", "libselinux-python" ] 4 | ipaserver_packages_dns: [ "ipa-server-dns" ] 5 | ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ] -------------------------------------------------------------------------------- /roles/ipaserver/vars/Fedora-25.yml: -------------------------------------------------------------------------------- 1 | ipaserver_packages: [ "ipa-server", "libselinux-python" ] 2 | ipaserver_packages_dns: [ "ipa-server-dns" ] 3 | ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ] -------------------------------------------------------------------------------- /roles/ipaserver/vars/Fedora-26.yml: -------------------------------------------------------------------------------- 1 | ipaserver_packages: [ "ipa-server", "libselinux-python" ] 2 | ipaserver_packages_dns: [ "ipa-server-dns" ] 3 | ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ] -------------------------------------------------------------------------------- /roles/ipaserver/vars/Fedora-27.yml: -------------------------------------------------------------------------------- 1 | ipaserver_packages: [ "ipa-server", "libselinux-python" ] 2 | ipaserver_packages_dns: [ "ipa-server-dns" ] 3 | ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ] 4 | -------------------------------------------------------------------------------- /roles/ipaserver/vars/Fedora.yml: -------------------------------------------------------------------------------- 1 | ipaserver_packages: [ "freeipa-server", "python3-libselinux" ] 2 | ipaserver_packages_dns: [ "freeipa-server-dns" ] 3 | ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ] -------------------------------------------------------------------------------- /roles/ipaserver/vars/RedHat-7.3.yml: -------------------------------------------------------------------------------- 1 | # defaults file for ipaserver 2 | # vars/rhel.yml 3 | ipaserver_packages: [ "ipa-server", "libselinux-python" ] 4 | ipaserver_packages_dns: [ "ipa-server-dns" ] 5 | ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ] -------------------------------------------------------------------------------- /roles/ipaserver/vars/RedHat-7.yml: -------------------------------------------------------------------------------- 1 | # defaults file for ipaserver 2 | # vars/rhel.yml 3 | ipaserver_packages: [ "ipa-server", "libselinux-python" ] 4 | ipaserver_packages_dns: [ "ipa-server-dns" ] 5 | ipaserver_packages_adtrust: [ "ipa-server-trust-ad" ] -------------------------------------------------------------------------------- /roles/ipaserver/vars/Ubuntu.yml: -------------------------------------------------------------------------------- 1 | # vars/Ubuntu.yml 2 | ipaserver_packages: [ "freeipa-server" ] 3 | ipaserver_packages_dns: [ "freeipa-server-dns" ] 4 | ipaserver_packages_adtrust: [ ] 5 | -------------------------------------------------------------------------------- /roles/ipaserver/vars/default.yml: -------------------------------------------------------------------------------- 1 | # defaults file for ipaserver 2 | # vars/default.yml 3 | ipaserver_packages: [ "ipa-server", "python3-libselinux" ] 4 | ipaserver_packages_dns: [ "ipa-server-dns" ] 5 | ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ] 6 | -------------------------------------------------------------------------------- /roles/kickstart/LICENSE-sergev.md: -------------------------------------------------------------------------------- 1 | # I used material from http://github.com/sergev/ansible-os-autoinstall 2 | # in constructing this role. His role is much more clever than mine. 3 | # This is his license. 4 | 5 | 6 | MIT License 7 | 8 | Copyright (c) 2017 Serge Sergeev 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | -------------------------------------------------------------------------------- /roles/kickstart/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Include secrets 3 | include_vars: ~/0/vault/secrets.yml 4 | 5 | - name: Generate unattended install 6 | template: 7 | src: templates/kickstart.j2 8 | dest: "{{ ks_dir }}/{{ hostvars[item].inventory_hostname_short }}.ks" 9 | with_items: "{{ groups['all'] | difference(groups['hypervisors']) }}" 10 | when: hostvars[item].distro is not defined 11 | 12 | - name: Generate unattended install 13 | template: 14 | src: templates/kickstart-fc28.j2 15 | dest: "{{ ks_dir }}/{{ hostvars[item].inventory_hostname_short }}.ks" 16 | with_items: "{{ groups['all'] | difference(groups['hypervisors']) }}" 17 | when: hostvars[item].distro is defined 18 | 19 | - name: generate pxe files 20 | template: 21 | src: templates/pxe.j2 22 | dest: "{{ menu_dir }}/01-{{ hostvars[item]['mac_address']|regex_replace(':','-')|lower }}" 23 | with_items: "{{ groups['all'] }}" 24 | when: hostvars[item]['mac_address'] is defined 25 | -------------------------------------------------------------------------------- /roles/kickstart/templates/host_default.j2: -------------------------------------------------------------------------------- 1 | UI menu.c32 2 | MENU TITLE Host Menu 3 | PXERetry 5 4 | PROMPT 0 5 | {% if item is defined and host_menu | default('') == "pxe" %} 6 | DEFAULT {{ item }} 7 | {% endif %} 8 | TIMEOUT {{ menu_timeout | default(15) }} 9 | LABEL bootlocal 10 | MENU LABEL Local Boot 11 | TEXT HELP 12 | This will exit from the network boot menu and attempt 13 | to boot from local media (hard disk, DVD, etc) 14 | ENDTEXT 15 | localboot 0 16 | -------------------------------------------------------------------------------- /roles/kickstart/templates/kickstart-fc28.j2: -------------------------------------------------------------------------------- 1 | # encoding # 2 | lang en_US.UTF-8 3 | keyboard us 4 | 5 | # timezone setup 6 | timezone --utc --ntpservers {{ ntp_servers|join(',') }} {{ timezone }} 7 | 8 | # EULA 9 | eula --agreed 10 | firstboot --disable 11 | 12 | ## DISK_SETUP ## 13 | # clear partitions 14 | clearpart --all --drives={{ hostvars[item]['drive'] | default(defaults.drive) }} 15 | zerombr 16 | 17 | # bootloader args 18 | bootloader --location=mbr 19 | 20 | # partition definitions 21 | part /boot --fstype=xfs --size=250 --ondisk={{ hostvars[item]['drive'] | default(defaults.drive) }} 22 | {% if hostvars[item].swap is defined %} 23 | part swap --fstype="swap" --size={{ hostvars[item].swap }} --ondisk={{ hostvars[item]['drive'] | default(defaults.drive) }} 24 | {% endif %} 25 | part / --fstype="xfs" --ondisk={{ hostvars[item]['drive'] | default(defaults.drive) }} --size=1 --grow 26 | 27 | ## NETWORK SETTINGS 28 | firewall --enabled --ssh 29 | 30 | network --activate --device=eth0 --onboot=yes --bootproto=dhcp --hostname={{ hostvars[item].inventory_hostname }} 31 | 32 | ## SELINUX ## 33 | selinux --enforcing 34 | 35 | ## ACCOUNT CREATION ## 36 | 37 | # passwords 38 | rootpw --iscrypted {{ root_password_hash }} 39 | 40 | auth --enableshadow --passalgo=sha512 41 | user --groups=wheel --name=nc --password={{ nc_password_hash }} --iscrypted 42 | 43 | ## SSH KEYS ## 44 | sshkey --username=root "{{ id_ed25519_pub }}" 45 | sshkey --username=nc "{{ id_ed25519_pub }}" 46 | 47 | ## INSTALL ## 48 | install 49 | url --url="{{ hostvars[item].install_url | default(repo_url) }}" 50 | 51 | # text mode 52 | text 53 | skipx 54 | 55 | 56 | # Packages 57 | %packages 58 | @core 59 | chrony 60 | vim-enhanced 61 | sudo 62 | {% if hostvars[item]['packages'] is defined %} 63 | {% for pkg in hostvars[item]['packages'] %} 64 | {{ pkg }} 65 | {% endfor %} 66 | {% endif %} 67 | 68 | %end 69 | %post --log=/root/ks-post.log 70 | sed -i -e 's|^# %wheel\tALL=(ALL)\tNOPASSWD: ALL|%wheel\tALL=(ALL)\tNOPASSWD: ALL|; s|^Defaults requiretty|#&|' /etc/sudoers 71 | %end 72 | reboot 73 | -------------------------------------------------------------------------------- /roles/kickstart/templates/kickstart.j2: -------------------------------------------------------------------------------- 1 | # front matter 2 | install 3 | url --url={{ hostvars[item].install_url | default(repo_url) }} 4 | skipx 5 | text 6 | reboot 7 | lang en_US.UTF-8 8 | keyboard us 9 | eula --agreed 10 | firstboot --disable 11 | 12 | # services 13 | services --enabled=network,sshd,snmpd,chronyd 14 | 15 | # passwords 16 | rootpw --iscrypted {{ root_password_hash }} 17 | authconfig --enableshadow --passalgo=sha512 18 | user --groups=wheel --name=nc --password={{ nc_password_hash }} --iscrypted --gecos="nc" 19 | 20 | # timezone setup 21 | timezone --utc --ntpservers {{ ntp_servers|join(',') }} {{ timezone }} 22 | 23 | network --device={{ hostvars[item]['netdev'] | default(defaults.netdev) }} --onboot=yes --hostname={{ item }} {{ hostvars[item]['netargs'] | default('') }} --bootproto=static --ip={{ hostvars[item]['ansible_host'] }} --netmask={{ hostvars[item]['netmask'] | default(defaults['netmask']) }} --gateway={{ hostvars[item]['gateway'] | default(defaults.gw)}} --nameserver= 24 | {%- for ns in hostvars[item]['nameservers'] | default(defaults.ns) %} 25 | {{ ns }}{% if not loop.last %},{% endif %} 26 | {%- endfor %} 27 | 28 | 29 | 30 | # partition setup 31 | clearpart --all --drives={{ hostvars[item]['drive'] | default(defaults.drive) }} 32 | bootloader --location=mbr --timeout=5 --append="{{ bootargs }}" 33 | zerombr 34 | clearpart --drives={{ hostvars[item]['drive'] | default(defaults.drive) }} --all 35 | part /boot --fstype=xfs --size=250 36 | part pv.156 --fstype="lvmpv" --ondisk={{ hostvars[item]['drive'] | default(defaults.drive) }} --size=1 --grow 37 | volgroup vg_{{ hostvars[item].inventory_hostname_short }} --pesize=4096 pv.156 38 | {% if hostvars[item].swap is defined %} 39 | logvol swap --fstype="swap" --size={{ hostvars[item].swap }} --name=swap --vgname=vg_{{ hostvars[item].inventory_hostname_short }} 40 | {% endif %} 41 | logvol / --fstype="xfs" --size=1 --name=root --vgname=vg_{{ hostvars[item].inventory_hostname_short }} --grow 42 | 43 | 44 | # Packages 45 | %packages --nobase --ignoremissing 46 | @core 47 | chrony 48 | vim-enhanced 49 | libselinux-python 50 | policycoreutils-python 51 | {% if hostvars[item]['packages'] is defined %} 52 | {% for pkg in hostvars[item]['packages'] %} 53 | {{ pkg }} 54 | {% endfor %} 55 | {% endif %} 56 | 57 | %end 58 | 59 | %post --log=/root/ks-post.log 60 | sed -i -e 's|^# %wheel\tALL=(ALL)\tNOPASSWD: ALL|%wheel\tALL=(ALL)\tNOPASSWD: ALL|; s|^Defaults requiretty|#&|' /etc/sudoers 61 | 62 | ## SSH KEYS ## 63 | sshkey --username=root "{{ id_ed25519_pub }}" 64 | sshkey --username=nc "{{ id_ed25519_pub }}" 65 | 66 | 67 | 68 | ########################## 69 | # repository configuration 70 | #find /etc/yum.repos.d/ -type f -exec mv '{}' '{}'.save ';' 71 | cat <<'EOF' > /dev/null 72 | #/etc/yum.repos.d/local.repo 73 | [base-local] 74 | name=Local CentOS-$releasever - Base 75 | baseurl=http://repo.lan.nathancurry.com/repo/centos7-base/ 76 | gpgcheck=1 77 | gpgkey=http://repo.lan.nathancurry.com/repo/centos7-base/RPM-GPG-KEY-CentOS-7 78 | enabled=1 79 | exclude=centos-release* 80 | 81 | #released updates 82 | [updates-local] 83 | name=Local CentOS-$releasever - Updates 84 | baseurl=http://repo.lan.nathancurry.com/repo/centos7-updates/ 85 | gpgcheck=1 86 | gpgkey=repo.lan.nathancurry.com/repo/centos7-updates/RPM-GPG-KEY-CentOS-7 87 | enabled=1 88 | 89 | #additional packages that may be useful 90 | [extras-local] 91 | name=Local CentOS-$releasever - Extras 92 | baseurl=http://repo.lan.nathancurry.com/repo/centos7-extras/ 93 | gpgcheck=1 94 | gpgkey=repo.lan.nathancurry.com/repo/centos7-extras/RPM-GPG-KEY-CentOS-7 95 | enabled=1 96 | 97 | #epel 98 | [epel-local] 99 | name=Local CentOS-$releasever - Extras 100 | baseurl=http://repo.lan.nathancurry.com/repo/centos7-epel/ 101 | gpgcheck=1 102 | gpgkey=http://mirror.grid.uchicago.edu/pub/linux/epel/RPM-GPG-KEY-EPEL-7 103 | enabled=1 104 | EOF 105 | ##################### 106 | # END REPOS 107 | 108 | %end 109 | -------------------------------------------------------------------------------- /roles/kickstart/templates/pxe.j2: -------------------------------------------------------------------------------- 1 | {% if hostvars[item]['mac_address'] is defined %} 2 | {% include "host_default.j2" %} 3 | {% endif %} 4 | 5 | LABEL {{ item }} 6 | MENU LABEL {{ item }} 7 | ipappend 2 8 | kernel /boot/{{ hostvars[item].distro | default(boot_distro) }}-vmlinuz 9 | append initrd=/boot/{{ hostvars[item].distro | default(boot_distro) }}-initrd.img repo={{ hostvars[item].install_url | default(repo_url) }} ks={{ ks_url }}/{{ hostvars[item].inventory_hostname_short }}.ks {{ hostvars[item]['bootargs'] | default('ksdevice=bootif vga=791') }} 10 | -------------------------------------------------------------------------------- /roles/kickstart/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ks_dir: /data/www/html/ks 3 | menu_dir: /var/lib/tftpboot/pxelinux.cfg/ 4 | 5 | repo_url: 'http://repo.lan.nathancurry.com/repo/centos7-base' 6 | ks_url: 'http://repo.lan.nathancurry.com/ks' 7 | 8 | boot_distro: 'centos7-1804' 9 | 10 | ntp_servers: 11 | - gold.lan.nathancurry.com 12 | - silver.lan.nathancurry.com 13 | - bronze.lan.nathancurry.com 14 | timezone: "America/Denver" 15 | hostlist: "{{ groups[all] }}" 16 | bootargs: 'console=ttyS0,115200' 17 | 18 | 19 | defaults: 20 | netmask: 255.255.255.128 21 | ns: 22 | - 10.3.3.2 23 | - 10.3.3.3 24 | gw: 10.3.3.1 25 | domain: lan.nathancurry.com 26 | netdev: eth0 27 | drive: vda 28 | -------------------------------------------------------------------------------- /roles/osapreparenetwork-broken/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ################ 3 | # 4 | # DON'T USE THIS, IT'S BROKEN 5 | # 6 | 7 | - name: install necessary packages 8 | yum: 9 | name: "{{ prerequisites }}" 10 | state: present 11 | 12 | - name: set default iface 13 | nmcli: 14 | conn_name: "{{ osa_netdev }}" 15 | type: ethernet 16 | ip4: "{{ ansible_host }}/{{ native.osa_cidr_prefix }}" 17 | gw4: "{{ native.osa_gw4 }}" 18 | dns4: "{{ native.osa_dns4 }}" 19 | mac: "{{ mac_address }}" 20 | state: present 21 | 22 | - name: create VLANs 23 | nmcli: 24 | conn_name: "{{ osa_netdev }}.{{ item }}" 25 | type: vlan 26 | gw4: '' 27 | gw6: '' 28 | ip4: '' 29 | ip6: '' 30 | vlandev: "{{ osa_netdev }}" 31 | vlanid: "{{ item }}" 32 | state: present 33 | with_items: "{{ vid }}" 34 | 35 | - name: create the management bridge 36 | nmcli: 37 | conn_name: br-mgmt 38 | type: bridge 39 | stp: no 40 | forwarddelay: 0 41 | ip4: "{{ vlans.container.osa_prefix4 }}.{{ osa_host_id }}/{{ vlans.container.osa_cidr_prefix }}" 42 | gw4: "{{ vlans.container.osa_gw4 }}" 43 | dns4: "{{ vlans.container.osa_dns4 }}" 44 | state: present 45 | 46 | - name: add vlan10 to br-mgmt 47 | nmcli: 48 | conn_name: "{{ osa_netdev }}.10" 49 | ifname: "{{ osa_netdev }}.10" 50 | type: bridge-slave 51 | # hairpin: yes 52 | # slavepriority: 32 53 | # path_cost: 100 54 | master: br-mgmt 55 | state: present 56 | 57 | - name: add external VIP alias 58 | nmcli: 59 | conn_name: 'br-mgmt.0' 60 | type: generic 61 | ip4: "{{ vlans.container.osa_prefix4 }}.10/{{ vlans.container.osa_cidr_prefix }}" 62 | state: present 63 | 64 | - name: create br-vxlan 65 | nmcli: 66 | conn_name: br-vxlan 67 | type: bridge 68 | stp: no 69 | forwarddelay: 0 70 | ip4: "{{ vlans.networking.osa_prefix4 }}.{{ osa_host_id }}" 71 | gw4: "{{ vlans.networking.osa_gw4 }}" 72 | dns4: "{{ vlans.networking.osa_dns4 }}" 73 | state: present 74 | 75 | - name: add vlan30 to br-vxlan 76 | nmcli: 77 | conn_name: "{{ osa_netdev }}.30" 78 | ifname: "{{ osa_netdev }}.30" 79 | type: bridge-slave 80 | master: br-vxlan 81 | state: present 82 | 83 | - name: add br-vlan 84 | nmcli: 85 | conn_name: 'br-vlan' 86 | type: bridge 87 | stp: no 88 | forwarddelay: 0 89 | state: present 90 | 91 | - name: "add {{ osa_netdev }} to br-vlan" 92 | nmcli: 93 | conn_name: "{{ osa_netdev }}" 94 | ifname: "{{ osa_netdev }}" 95 | type: bridge-slave 96 | master: br-vlan 97 | state: present 98 | 99 | - name: br-storage 100 | nmcli: 101 | conn_name: br-storage 102 | type: bridge 103 | stp: no 104 | forwarddelay: 0 105 | ip4: "{{ vlans.storage.osa_prefix4 }}.{{ osa_host_id }}/{{ vlans.storage.osa_cidr_prefix }}" 106 | gw4: "{{ vlans.storage.osa_gw4 }}" 107 | dns4: "{{ vlans.storage.osa_dns4 }}" 108 | state: present 109 | 110 | - name: add vlan20 to br-vxlan 111 | nmcli: 112 | conn_name: "{{ osa_netdev }}.20" 113 | ifname: "{{ osa_netdev }}.20" 114 | type: bridge-slave 115 | master: br-vxlan 116 | state: present 117 | -------------------------------------------------------------------------------- /roles/osapreparenetwork-broken/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Hostvars 3 | # osa_netdev: physical device ID (eno1, eth0, em1) 4 | # osa_host_id: last octet 5 | # ansible_host: host ip address 6 | # mac_address: host mac address 7 | 8 | prerequisites: 9 | - python-gobject 10 | - NetworkManager-glib 11 | # - nm-connection-editor 12 | # - libsemanage-python 13 | # - policycoreutils-python 14 | 15 | osa_bonddev: bond0 16 | 17 | native: 18 | osa_gw4: 10.3.3.1 19 | osa_dns4: "10.3.3.1 172.98.193.42" 20 | osa_cidr_prefix: 24 21 | 22 | vid: 23 | - 10 24 | - 20 25 | - 30 26 | 27 | vlans: 28 | container: 29 | osa_vlanid: 10 30 | osa_gw4: 172.29.236.1 31 | osa_prefix4: 172.29.236 32 | osa_dns4: "172.29.236.1 172.98.193.42" 33 | osa_cidr_prefix: 22 34 | networking: 35 | osa_vlanid: 20 36 | osa_gw4: 172.29.240.1 37 | osa_prefix4: 172.29.240 38 | osa_dns4: "172.29.240.1 172.98.193.42" 39 | osa_cidr_prefix: 22 40 | storage: 41 | osa_vlanid: 30 42 | osa_gw4: 172.29.244.1 43 | osa_prefix4: 172.29.244 44 | osa_dns4: "172.29.244.1 172.98.193.42" 45 | osa_cidr_prefix: 22 46 | -------------------------------------------------------------------------------- /roles/osapreparenetwork/files/ifcfg-lo: -------------------------------------------------------------------------------- 1 | DEVICE=lo 2 | IPADDR=127.0.0.1 3 | NETMASK=255.0.0.0 4 | NETWORK=127.0.0.0 5 | # If you're having problems with gated making 127.0.0.0/8 a martian, 6 | # you can change this to something else (255.255.255.255, for example) 7 | BROADCAST=127.255.255.255 8 | ONBOOT=yes 9 | NAME=loopback 10 | -------------------------------------------------------------------------------- /roles/osapreparenetwork/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: ensure backup folder exists 3 | file: 4 | path: "{{ ifcfg_dir }}/backup" 5 | state: directory 6 | owner: root 7 | group: root 8 | mode: 0700 9 | 10 | - name: get files 11 | shell: "ls {{ ifcfg_dir}}/ifcfg-*" 12 | register: files_to_move 13 | 14 | - name: copy files 15 | copy: 16 | remote_src: true 17 | src: "{{ item }}" 18 | dest: "{{ ifcfg_dir }}/backup/" 19 | with_items: "{{ files_to_move.stdout_lines }}" 20 | 21 | - name: delete files 22 | file: 23 | path: "{{ item }}" 24 | state: absent 25 | with_items: "{{ files_to_move.stdout_lines }}" 26 | 27 | - name: install loopback device 28 | copy: 29 | src: ifcfg-lo 30 | dest: "{{ ifcfg_dir }}/ifcfg-lo" 31 | 32 | - name: install netdevices file 33 | template: 34 | src: ifcfg-netdev.j2 35 | dest: "{{ ifcfg_dir }}/ifcfg-{{ item.device }}" 36 | with_items: "{{ osa_networks }}" 37 | when: item['native'] is defined 38 | 39 | - name: install vlans 40 | template: 41 | src: "ifcfg-vlan.j2" 42 | dest: "{{ ifcfg_dir }}/ifcfg-{{ item.device }}.{{ item['vlan_id'] }}" 43 | with_items: "{{ osa_networks }}" 44 | when: item['vlan_id'] is defined 45 | 46 | - name: install management bridge 47 | template: 48 | src: "ifcfg-br-mgmt.j2" 49 | dest: "{{ ifcfg_dir }}/ifcfg-br-mgmt" 50 | with_items: "{{ osa_networks }}" 51 | when: item['name'] == 'br-mgmt' 52 | 53 | - name: other bridges 54 | template: 55 | src: "ifcfg-bridge.j2" 56 | dest: "{{ ifcfg_dir }}/ifcfg-{{ item.name }}" 57 | with_items: "{{ osa_networks }}" 58 | when: item['name'] != 'br-mgmt' 59 | 60 | - name: disable NetworkManager 61 | systemd: 62 | name: NetworkManager 63 | state: stopped 64 | masked: yes 65 | ignore_errors: true 66 | 67 | - name: restart network 68 | systemd: 69 | name: network 70 | state: restarted 71 | enabled: yes 72 | -------------------------------------------------------------------------------- /roles/osapreparenetwork/templates/ifcfg-br-mgmt.j2: -------------------------------------------------------------------------------- 1 | NAME=br-mgmt 2 | DEVICE=br-mgmt 3 | UUID={{ inventory_hostname | password_hash('sha512') | to_uuid }} 4 | TYPE=Bridge 5 | STP=no 6 | PROXY_METHOD=none 7 | BROWSER_ONLY=no 8 | BOOTPROTO=none 9 | DEFROUTE=yes 10 | IPV4_FAILURE_FATAL=no 11 | IPV6INIT=yes 12 | IPV6_AUTOCONF=yes 13 | IPV6_DEFROUTE=yes 14 | IPV6_FAILURE_FATAL=no 15 | IPV6_ADDR_GEN_MODE=stable-privacy 16 | ONBOOT=yes 17 | IPADDR={{ item.network }}.{{ osa_host_id }} 18 | PREFIX={{ item.cidr_prefix}} 19 | GATEWAY={{ item.gw }} 20 | {% for object in item.dns %} 21 | DNS{{loop.index}}={{ object }} 22 | {% endfor %} 23 | {% if osa_deployhost is defined %} 24 | IPADDR2={{ ext_vip_ip }} 25 | {% endif %} 26 | -------------------------------------------------------------------------------- /roles/osapreparenetwork/templates/ifcfg-br-storage.j2: -------------------------------------------------------------------------------- 1 | DEVICE=br-storage 2 | NAME=br-storage 3 | UUID={{ inventory_hostname | password_hash('sha512') | to_uuid }} 4 | STP=no 5 | TYPE=Bridge 6 | PROXY_METHOD=none 7 | BROWSER_ONLY=no 8 | BOOTPROTO=none 9 | DEFROUTE=yes 10 | IPV4_FAILURE_FATAL=no 11 | ONBOOT=yes 12 | {% if osa_deployhost is defined %} 13 | IPADDR={{ item.network }}.{{ host_id }} 14 | PREFIX={{ item.cidr_prefix}} 15 | IPV6INIT=yes 16 | IPV6_AUTOCONF=yes 17 | IPV6_DEFROUTE=yes 18 | IPV6_FAILURE_FATAL=no 19 | IPV6_ADDR_GEN_MODE=stable-privacy 20 | {% endif %} 21 | -------------------------------------------------------------------------------- /roles/osapreparenetwork/templates/ifcfg-br-vlan.j2: -------------------------------------------------------------------------------- 1 | NAME=br-vlan 2 | DEVICE=br-vlan 3 | STP=no 4 | TYPE=Bridge 5 | PROXY_METHOD=none 6 | BROWSER_ONLY=no 7 | BOOTPROTO=none 8 | ONBOOT=yes 9 | DEFROUTE=yes 10 | IPV4_FAILURE_FATAL=no 11 | UUID={{ ansible_date_time.iso8601_micro | random | to_uuid }} 12 | -------------------------------------------------------------------------------- /roles/osapreparenetwork/templates/ifcfg-br-vxlan.j2: -------------------------------------------------------------------------------- 1 | STP=no 2 | TYPE=Bridge 3 | PROXY_METHOD=none 4 | BROWSER_ONLY=no 5 | BOOTPROTO=none 6 | ONBOOT=yes 7 | DEFROUTE=yes 8 | IPV4_FAILURE_FATAL=no 9 | NAME=br-vxlan 10 | DEVICE=br-vxlan 11 | IPV6INIT=yes 12 | IPV6_AUTOCONF=yes 13 | IPV6_DEFROUTE=yes 14 | IPV6_FAILURE_FATAL=no 15 | IPV6_ADDR_GEN_MODE=stable-privacy 16 | UUID={{ ansible_date_time.iso8601_micro | random | to_uuid }} 17 | IPADDR={{ osa_networking.network }}.{{ host_id }} 18 | PREFIX={{ osa_networking.cidr_prefix }} 19 | -------------------------------------------------------------------------------- /roles/osapreparenetwork/templates/ifcfg-bridge.j2: -------------------------------------------------------------------------------- 1 | NAME={{ item.name }} 2 | DEVICE={{ item.name }} 3 | UUID={{ inventory_hostname | password_hash('sha512') | to_uuid }} 4 | TYPE=Bridge 5 | STP=no 6 | PROXY_METHOD=none 7 | BROWSER_ONLY=no 8 | BOOTPROTO=none 9 | ONBOOT=yes 10 | DEFROUTE=yes 11 | IPV4_FAILURE_FATAL=no 12 | {% if item.skip_network is undefined %} 13 | IPADDR={{ item.network }}.{{ osa_host_id }} 14 | PREFIX={{ item.cidr_prefix}} 15 | IPV6INIT=yes 16 | IPV6_AUTOCONF=yes 17 | IPV6_DEFROUTE=yes 18 | IPV6_FAILURE_FATAL=no 19 | IPV6_ADDR_GEN_MODE=stable-privacy 20 | {% endif %} 21 | -------------------------------------------------------------------------------- /roles/osapreparenetwork/templates/ifcfg-netdev.j2: -------------------------------------------------------------------------------- 1 | DEVICE={{ item.device }} 2 | NAME={{ item.device }} 3 | TYPE=Ethernet 4 | BRIDGE={{ item.name }} 5 | PROXY_METHOD=none 6 | BROWSER_ONLY=no 7 | DEFROUTE=yes 8 | IPV4_FAILURE_FATAL=no 9 | ONBOOT=yes 10 | -------------------------------------------------------------------------------- /roles/osapreparenetwork/templates/ifcfg-vlan.j2: -------------------------------------------------------------------------------- 1 | NAME={{ item.device }}.{{ item.vlan_id }} 2 | DEVICE={{ item.device }}.{{ item.vlan_id }} 3 | UUID={{ inventory_hostname | password_hash('sha512') | to_uuid }} 4 | PHYSDEV={{ item.device }} 5 | TYPE=Vlan 6 | VLAN=yes 7 | VLAN_ID={{ item.vlan_id }} 8 | BRIDGE={{ item.name }} 9 | REORDER_HDR=yes 10 | GVRP=no 11 | MVRP=no 12 | PROXY_METHOD=none 13 | BROWSER_ONLY=no 14 | DEFROUTE=yes 15 | IPV4_FAILURE_FATAL=no 16 | ONBOOT=yes 17 | -------------------------------------------------------------------------------- /roles/osapreparenetwork/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: test vars 3 | hosts: infra.lan.nathancurry.com 4 | user: stack 5 | become: true 6 | gather_facts: false 7 | 8 | vars_files: 9 | - vars/main.yml 10 | 11 | tasks: 12 | - name: test 13 | debug: 14 | msg: "{{ item }}" 15 | with_items: "{{ netdev[1] }}" 16 | -------------------------------------------------------------------------------- /roles/osapreparenetwork/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ifcfg_dir: /etc/sysconfig/network-scripts 3 | 4 | ext_vip_ip: 10.3.3.10 5 | 6 | osa_networks: 7 | - native: yes 8 | name: br-vlan 9 | device: "{{ netdev[1] }}" 10 | skip_network: true 11 | - native: yes 12 | name: br-mgmt 13 | device: "{{ netdev[0] }}" 14 | network: 10.3.3 15 | cidr_prefix: 24 16 | gw: 10.3.3.1 17 | dns: 18 | - 10.3.3.1 19 | - 172.98.193.42 20 | - vlan_id: 4 21 | name: br-vxlan 22 | device: "{{ netdev[1] }}" 23 | network: 10.3.4 24 | cidr_prefix: 24 25 | gw: 10.3.4.1 26 | dns: 27 | - 10.3.4.1 28 | - 172.98.193.42 29 | - vlan_id: 5 30 | name: br-storage 31 | device: "{{ netdev[0] }}" 32 | network: 10.3.5 33 | cidr_prefix: 24 34 | gw: 10.3.5.1 35 | dns: 36 | - 10.3.5.1 37 | - 172.98.193.42 38 | -------------------------------------------------------------------------------- /roles/osapreparenode/files/openstack-ansible.conf: -------------------------------------------------------------------------------- 1 | bonding 2 | 8021q 3 | -------------------------------------------------------------------------------- /roles/osapreparenode/tasks/deployhost.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install rdo-release 3 | yum: 4 | name: 'https://rdoproject.org/repos/openstack-rocky/rdo-release-rocky.rpm' 5 | state: present 6 | 7 | - name: install packages on deployhost 8 | yum: 9 | name: "{{ deploypackages }}" 10 | state: present 11 | 12 | - name: install deploy key on deployhost 13 | blockinfile: 14 | block: "{{ id_ed25519_private }}" 15 | create: yes 16 | mode: 0600 17 | owner: "{{ user }}" 18 | group: "{{ user }}" 19 | path: "/home/{{ user }}/.ssh/id_ed25519" 20 | 21 | - name: make osa dir 22 | file: 23 | path: /opt/openstack-ansible 24 | owner: "{{ user }}" 25 | group: "{{ user }}" 26 | mode: 0750 27 | state: directory 28 | 29 | - name: git 30 | git: 31 | dest: /opt/openstack-ansible 32 | repo: https://git.openstack.org/openstack/openstack-ansible 33 | version: 18.0.0.0rc2 34 | 35 | - name: bootstrap ansible 36 | command: './scripts/bootstrap-ansible.sh' 37 | args: 38 | chdir: /opt/openstack-ansible 39 | -------------------------------------------------------------------------------- /roles/osapreparenode/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install packages 3 | yum: 4 | name: "{{ nodepackages }}" 5 | state: present 6 | update_cache: yes 7 | 8 | - name: Include deployhost tasks. 9 | import_tasks: deployhost.yml 10 | when: deployhost 11 | 12 | - name: load modules at boot 13 | copy: 14 | src: openstack-ansible.conf 15 | dest: /etc/modules-load.d/openstack-ansible.conf 16 | owner: root 17 | group: root 18 | mode: 0644 19 | 20 | - name: lower kernel logging level 21 | lineinfile: 22 | line: "kernel.printk='4 1 7 4'" 23 | insertafter: EOF 24 | path: /etc/sysctl.conf 25 | state: present 26 | 27 | - name: stop and mask firewall 28 | systemd: 29 | name: firewalld 30 | state: stopped 31 | masked: yes 32 | -------------------------------------------------------------------------------- /roles/osapreparenode/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | deploypackages: 3 | - git 4 | - python-devel 5 | - '@Development Tools' 6 | 7 | nodepackages: 8 | - bridge-utils 9 | - iputils 10 | - lsof 11 | - lvm2 12 | - chrony 13 | - openssh-server 14 | - sudo 15 | - python 16 | -------------------------------------------------------------------------------- /roles/preparestorage/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Restart container 3 | proxmox: 4 | api_host: '{{ inventory_hostname_short }}' 5 | api_user: 'root@pam' 6 | api_password: '{{api_password}}' 7 | vmid: '{{ vmid }}' 8 | state: restarted 9 | -------------------------------------------------------------------------------- /roles/preparestorage/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Make sure mount directory exists 3 | block: 4 | - file: 5 | state: 'directory' 6 | path: /mnt/external 7 | owner: root 8 | group: root 9 | mode: 0755 10 | 11 | - mount: 12 | path: /mnt/external 13 | src: 'UUID={{ storage_uuid }}' 14 | fstype: ext4 15 | opts: relatime 16 | state: mounted 17 | 18 | - command: "pct set {{ storage_guest_vmid }} -mp0 /mnt/external,mp=/data" 19 | notify: restart container 20 | 21 | # Load vars for handler 22 | - include_vars: "~/0/vault/proxmox.yml" 23 | no_log: true 24 | 25 | when: storage_uuid is defined 26 | -------------------------------------------------------------------------------- /roles/repoclient/files/local.repo: -------------------------------------------------------------------------------- 1 | [base-local] 2 | name=Local CentOS-$releasever - Base 3 | baseurl=http://repo.lan.nathancurry.com/repo/centos7-base/ 4 | gpgcheck=1 5 | gpgkey=http://repo.lan.nathancurry.com/repo/centos7-base/RPM-GPG-KEY-CentOS-7 6 | enabled=1 7 | exclude=centos-release* 8 | 9 | #released updates 10 | [updates-local] 11 | name=Local CentOS-$releasever - Updates 12 | baseurl=http://repo.lan.nathancurry.com/repo/centos7-updates/ 13 | gpgcheck=1 14 | gpgkey=http://repo.lan.nathancurry.com/repo/centos7-updates/RPM-GPG-KEY-CentOS-7 15 | enabled=1 16 | 17 | #additional packages that may be useful 18 | [extras-local] 19 | name=Local CentOS-$releasever - Extras 20 | baseurl=http://repo.lan.nathancurry.com/repo/centos7-extras/ 21 | gpgcheck=1 22 | gpgkey=http://repo.lan.nathancurry.com/repo/centos7-extras/RPM-GPG-KEY-CentOS-7 23 | enabled=1 24 | 25 | #epel 26 | [epel-local] 27 | name=Local CentOS-$releasever - Extras 28 | baseurl=http://repo.lan.nathancurry.com/repo/centos7-epel/ 29 | gpgcheck=1 30 | gpgkey=http://mirror.grid.uchicago.edu/pub/linux/epel/RPM-GPG-KEY-EPEL-7 31 | enabled=1 32 | -------------------------------------------------------------------------------- /roles/repoclient/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Set up local repositories 3 | block: 4 | - yum_repository: 5 | name: '{{ item }}' 6 | state: absent 7 | with_items: 8 | - base 9 | - extras 10 | - updates 11 | - epel 12 | - copy: 13 | src: 'local.repo' 14 | dest: '/etc/yum.repos.d/local.repo' 15 | owner: 'root' 16 | group: 'root' 17 | mode: '0644' 18 | when: (ansible_distribution == "CentOS") 19 | -------------------------------------------------------------------------------- /roles/reposerver/files/local.repo: -------------------------------------------------------------------------------- 1 | [base-local] 2 | name=Local CentOS-$releasever - Base 3 | baseurl=http://repo.lan.nathancurry.com/repo/centos7-base/ 4 | gpgcheck=1 5 | gpgkey=http://repo.lan.nathancurry.com/repo/centos7-base/RPM-GPG-KEY-CentOS-7 6 | enabled=1 7 | exclude=centos-release* 8 | 9 | #released updates 10 | [updates-local] 11 | name=Local CentOS-$releasever - Updates 12 | baseurl=http://repo.lan.nathancurry.com/repo/centos7-updates/ 13 | gpgcheck=1 14 | gpgkey=repo.lan.nathancurry.com/repo/centos7-updates/RPM-GPG-KEY-CentOS-7 15 | enabled=1 16 | 17 | #additional packages that may be useful 18 | [extras-local] 19 | name=Local CentOS-$releasever - Extras 20 | baseurl=http://repo.lan.nathancurry.com/repo/centos7-extras/ 21 | gpgcheck=1 22 | gpgkey=repo.lan.nathancurry.com/repo/centos7-extras/RPM-GPG-KEY-CentOS-7 23 | enabled=1 24 | 25 | #epel 26 | [epel-local] 27 | name=Local CentOS-$releasever - Extras 28 | baseurl=http://repo.lan.nathancurry.com/repo/centos7-epel/ 29 | gpgcheck=1 30 | gpgkey=http://mirror.grid.uchicago.edu/pub/linux/epel/RPM-GPG-KEY-EPEL-7 31 | enabled=1 32 | -------------------------------------------------------------------------------- /roles/reposerver/files/reposync.conf: -------------------------------------------------------------------------------- 1 | [main] 2 | cachedir=/var/cache/yum/$basearch/$releasever 3 | keepcache=0 4 | logfile=/var/log/reposync.log 5 | exactarch=1 6 | obsoletes=1 7 | gpgcheck=1 8 | plugins=0 9 | reposdir=/data/www/html/meta/repos/ 10 | -------------------------------------------------------------------------------- /roles/reposerver/files/reposync.repo: -------------------------------------------------------------------------------- 1 | [centos7-base] 2 | name=CentOS-$releasever - Base 3 | mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra 4 | #baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/ 5 | gpgcheck=1 6 | gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 7 | 8 | #released updates 9 | [centos7-updates] 10 | name=CentOS-$releasever - Updates 11 | mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates&infra=$infra 12 | #baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/ 13 | gpgcheck=1 14 | gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 15 | 16 | #additional packages that may be useful 17 | [centos7-extras] 18 | name=CentOS-$releasever - Extras 19 | mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra 20 | #baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/ 21 | gpgcheck=1 22 | gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 23 | 24 | [centos7-epel] 25 | name=CentOS-7 - EPEL 26 | baseurl=http://mirror.grid.uchicago.edu/pub/linux/epel/7/x86_64/ 27 | gpgcheck=1 28 | gpgkey=http://mirror.grid.uchicago.edu/pub/linux/epel/RPM-GPG-KEY-EPEL-7 29 | -------------------------------------------------------------------------------- /roles/reposerver/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Link /var/www/ to data 3 | file: 4 | src: /data/www 5 | dest: /var/www 6 | owner: root 7 | group: root 8 | state: link 9 | 10 | - name: Install packages 11 | yum: 12 | name: '{{ packages }}' 13 | state: 'present' 14 | update_cache: 'yes' 15 | 16 | - name: Turn on web server 17 | service: 18 | name: httpd 19 | state: started 20 | 21 | - name: make dirs 22 | file: 23 | dest: '/data/www/html/{{ item }}' 24 | state: 'directory' 25 | owner: 'root' 26 | group: 'apache' 27 | mode: '0750' 28 | with_items: 29 | - 'repo' 30 | - 'meta/repos' 31 | 32 | - name: Install reposync.conf 33 | copy: 34 | src: 'reposync.conf' 35 | dest: '/data/www/html/meta/reposync.conf' 36 | owner: 'root' 37 | group: 'root' 38 | mode: '0600' 39 | 40 | - name: install reposync.repo 41 | copy: 42 | src: 'reposync.repo' 43 | dest: '/data/www/html/meta/repos/reposync.repo' 44 | owner: 'root' 45 | group: 'root' 46 | mode: '0600' 47 | 48 | - name: Set reposync cron file 49 | cron: 50 | name: 'reposync' 51 | weekday: '*' 52 | minute: 0 53 | hour: 1 54 | user: root 55 | job: "reposync -n -d -a x86_64 -p /data/www/html/repo/ -c /data/www/html/meta/reposync.conf" 56 | cron_file: 'ansible_reposync' 57 | 58 | - name: Make local repo available on server 59 | copy: 60 | src: '../files/local.repo' 61 | dest: '/data/www/html/repo/centos7-local.repo' 62 | owner: 'root' 63 | group: 'root' 64 | mode: '0644' 65 | -------------------------------------------------------------------------------- /roles/reposerver/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | packages: 3 | - httpd 4 | - createrepo 5 | - yum-utils 6 | -------------------------------------------------------------------------------- /roles/sshdisableroot/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart sshd 2 | service: 3 | name: sshd 4 | state: restarted 5 | -------------------------------------------------------------------------------- /roles/sshdisableroot/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Disable root login over SSH 3 | lineinfile: dest=/etc/ssh/sshd_config regexp="^PermitRootLogin" line="PermitRootLogin no" state=present 4 | notify: 5 | - restart sshd 6 | 7 | - name: Disable password login 8 | lineinfile: dest=/etc/ssh/sshd_config regexp="^PasswordAuthentication" line="PasswordAuthentication no" state=present 9 | notify: 10 | - restart sshd 11 | -------------------------------------------------------------------------------- /roles/sshenableuser/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Import variables specific to distribution 3 | include_vars: "{{ item }}" 4 | with_first_found: 5 | - "vars/{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml" 6 | - "vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml" 7 | - "vars/{{ ansible_distribution }}.yml" 8 | - "vars/default.yml" 9 | 10 | - name: import secrets 11 | include_vars: 12 | file: "~/0/vault/secrets.yml" 13 | 14 | - name: Add user 15 | user: 16 | name: "{{ user | default(defaultuser) }}" 17 | password: "{{ nc_password_hash }}" 18 | groups: "{{ sudo_group }}" 19 | 20 | - name: Add authorized key 21 | authorized_key: 22 | user: "{{ user }}" 23 | key: "{{ id_ed25519_pub }}" 24 | 25 | - name: Add authorized key 26 | authorized_key: 27 | user: "root" 28 | key: "{{ id_ed25519_pub }}" 29 | 30 | 31 | - name: Ensure sudo installed 32 | package: 33 | name: sudo 34 | state: present 35 | 36 | - name: Allow 'wheel' group to have passwordless sudo 37 | lineinfile: 38 | dest: /etc/sudoers 39 | state: present 40 | regexp: '{{ sudo_regex }}' 41 | line: '{{ sudo_line }}' 42 | validate: 'visudo -cf %s' 43 | when: (ansible_distribution == "CentOS") 44 | 45 | - name: Allow 'sudo' group to have passwordless sudo 46 | lineinfile: 47 | dest: /etc/sudoers 48 | state: present 49 | regexp: '^%sudo' 50 | line: '%sudo ALL=(ALL) NOPASSWD: ALL' 51 | validate: 'visudo -cf %s' 52 | when: (ansible_distribution == "Debian") 53 | -------------------------------------------------------------------------------- /roles/sshenableuser/vars/Debian.yml: -------------------------------------------------------------------------------- 1 | sudo_group: sudo 2 | sudo_regex: '^%sudo' 3 | sudo_line: '%sudo ALL=(ALL) NOPASSWD: ALL' 4 | -------------------------------------------------------------------------------- /roles/sshenableuser/vars/default.yml: -------------------------------------------------------------------------------- 1 | sudo_group: wheel 2 | sudo_regex: '^%wheel' 3 | sudo_line: '%wheel ALL=(ALL) NOPASSWD: ALL' 4 | -------------------------------------------------------------------------------- /roles/sshenableuser/vars/main.yml: -------------------------------------------------------------------------------- 1 | defaultuser: nc 2 | -------------------------------------------------------------------------------- /roles/tftpserver/files/chain.c32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathancurry/homelab.ansible/fba05a5e8931fc3982dcb1bb4143e73bef888080/roles/tftpserver/files/chain.c32 -------------------------------------------------------------------------------- /roles/tftpserver/files/mboot.c32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathancurry/homelab.ansible/fba05a5e8931fc3982dcb1bb4143e73bef888080/roles/tftpserver/files/mboot.c32 -------------------------------------------------------------------------------- /roles/tftpserver/files/memdisk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathancurry/homelab.ansible/fba05a5e8931fc3982dcb1bb4143e73bef888080/roles/tftpserver/files/memdisk -------------------------------------------------------------------------------- /roles/tftpserver/files/menu.c32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathancurry/homelab.ansible/fba05a5e8931fc3982dcb1bb4143e73bef888080/roles/tftpserver/files/menu.c32 -------------------------------------------------------------------------------- /roles/tftpserver/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install packages 3 | yum: 4 | name: '{{ packages }}' 5 | state: 'present' 6 | update_cache: 'yes' 7 | 8 | - name: create folder 9 | file: 10 | path: /var/lib/tftpboot/boot 11 | state: directory 12 | mode: 0755 13 | 14 | - name: copy files 15 | copy: 16 | src: '{{ item }}' 17 | dest: /var/lib/tftpboot 18 | mode: 0755 19 | with_fileglob: files/* 20 | 21 | - name: copy boot images 22 | copy: 23 | src: '{{ item }}' 24 | dest: /var/lib/tftpboot/boot 25 | mode: 0755 26 | with_fileglob: files/boot/* 27 | 28 | - name: create folder 29 | file: 30 | path: /var/lib/tftpboot/pxelinux.cfg/hosts 31 | state: directory 32 | mode: 0755 33 | -------------------------------------------------------------------------------- /roles/tftpserver/tasks/start.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Start tftp 3 | service: 4 | name: tftp 5 | state: started 6 | -------------------------------------------------------------------------------- /roles/tftpserver/tasks/stop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Stop tftp 3 | service: 4 | name: tftp 5 | state: stopped 6 | -------------------------------------------------------------------------------- /roles/tftpserver/vars/main.yml: -------------------------------------------------------------------------------- 1 | packages: [ 'tftp-server' ] 2 | -------------------------------------------------------------------------------- /site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Site playbook 3 | 4 | import_playbook: 5 | - hypervisors.yml 6 | - reposerver.yml 7 | - nameservers.yml 8 | -------------------------------------------------------------------------------- /sitevars.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Basic common network variables 3 | searchdomain: 'lan.nathancurry.com' 4 | # Subnets 5 | lan: 6 | cidr: '10.3.3.0/25' 7 | gw: '10.3.3.1' 8 | iot: 9 | cidr: '10.3.3.208/28' 10 | gw: '10.3.3.209' 11 | dmz: 12 | cidr: '10.10.10.0/29' 13 | gw: '10.10.10.1' 14 | --------------------------------------------------------------------------------