├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── ansible ├── ansible.cfg ├── callback_plugins │ └── profile_tasks.py ├── group_vars │ ├── all │ ├── ipa_vpnserver │ └── pki_server ├── ipa-playbook.yml ├── library │ ├── ipa.py │ ├── ipa_facts.py │ ├── resolver.py │ ├── reversezone.py │ └── waitforcertmonger.py ├── pki-playbook.yml └── roles │ ├── bootstrap │ └── tasks │ │ └── main.yml │ ├── common │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ ├── dnf.yml │ │ ├── extravars.yml │ │ ├── main.yml │ │ └── yum.yml │ └── templates │ │ └── etc_hosts │ ├── ipa-client │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── ipa-demoaccounts │ └── tasks │ │ └── main.yml │ ├── ipa-httpd │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── ipa-httpexample │ ├── defaults │ │ └── main.yml │ ├── files │ │ └── example │ │ │ └── html │ │ │ ├── login.html │ │ │ └── unauthorized.html │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ │ ├── example.conf │ │ ├── pam_http_example │ │ └── wsgi.py │ └── vars │ │ └── main.yml │ ├── ipa-inventory │ ├── files │ │ └── xulstore.json │ ├── tasks │ │ └── main.yml │ ├── templates │ │ ├── bookmarks.html │ │ ├── firefox_prefs │ │ ├── ipa_firefox │ │ ├── ipa_kinit │ │ ├── ipa_kkdcp_kinit │ │ ├── ipa_kkdcp_openconnect_kinit │ │ ├── ipa_kkdcp_openconnect_vpn │ │ ├── ipa_ssh │ │ ├── ipa_ssh_config │ │ ├── ipaenv │ │ ├── ipaenv_kkdcp │ │ ├── ipaenv_kkdcp_openconnect │ │ └── krb5.conf │ └── vars │ │ └── main.yml │ ├── ipa-ipsilon-idp │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── ipa-modnss │ ├── files │ │ └── replaced │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── ipa-modssl │ ├── files │ │ └── replaced │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── ipa-nfsserver │ ├── handlers │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── ipa-smbserver │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── smb.conf │ ├── ipa-sp-example │ ├── defaults │ │ └── main.yml │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ │ ├── admin_password │ │ └── sp_example.conf │ └── vars │ │ └── main.yml │ ├── ipa-tests │ ├── tasks │ │ └── main.yml │ ├── templates │ │ ├── default.conf │ │ ├── dot_dmpw │ │ └── krb5.conf │ └── vars │ │ └── main.yml │ ├── ipa-tidy │ └── tasks │ │ └── main.yml │ ├── ipa-vpnserver │ ├── handlers │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── ocserv.conf │ ├── ipa-wwwdemo │ ├── files │ │ ├── pam_websvc │ │ ├── ui │ │ │ ├── css │ │ │ │ ├── patternfly-additions.css │ │ │ │ └── patternfly.css │ │ │ ├── error.html │ │ │ ├── fonts │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── OpenSans-Bold-webfont.eot │ │ │ │ ├── OpenSans-Bold-webfont.ttf │ │ │ │ ├── OpenSans-Bold-webfont.woff │ │ │ │ ├── OpenSans-Bold-webfont.woff2 │ │ │ │ ├── OpenSans-BoldItalic-webfont.eot │ │ │ │ ├── OpenSans-BoldItalic-webfont.ttf │ │ │ │ ├── OpenSans-BoldItalic-webfont.woff │ │ │ │ ├── OpenSans-BoldItalic-webfont.woff2 │ │ │ │ ├── OpenSans-ExtraBold-webfont.eot │ │ │ │ ├── OpenSans-ExtraBold-webfont.ttf │ │ │ │ ├── OpenSans-ExtraBold-webfont.woff │ │ │ │ ├── OpenSans-ExtraBold-webfont.woff2 │ │ │ │ ├── OpenSans-ExtraBoldItalic-webfont.eot │ │ │ │ ├── OpenSans-ExtraBoldItalic-webfont.ttf │ │ │ │ ├── OpenSans-ExtraBoldItalic-webfont.woff │ │ │ │ ├── OpenSans-ExtraBoldItalic-webfont.woff2 │ │ │ │ ├── OpenSans-Italic-webfont.eot │ │ │ │ ├── OpenSans-Italic-webfont.ttf │ │ │ │ ├── OpenSans-Italic-webfont.woff │ │ │ │ ├── OpenSans-Italic-webfont.woff2 │ │ │ │ ├── OpenSans-Light-webfont.eot │ │ │ │ ├── OpenSans-Light-webfont.ttf │ │ │ │ ├── OpenSans-Light-webfont.woff │ │ │ │ ├── OpenSans-Light-webfont.woff2 │ │ │ │ ├── OpenSans-LightItalic-webfont.eot │ │ │ │ ├── OpenSans-LightItalic-webfont.ttf │ │ │ │ ├── OpenSans-LightItalic-webfont.woff │ │ │ │ ├── OpenSans-LightItalic-webfont.woff2 │ │ │ │ ├── OpenSans-Regular-webfont.eot │ │ │ │ ├── OpenSans-Regular-webfont.ttf │ │ │ │ ├── OpenSans-Regular-webfont.woff │ │ │ │ ├── OpenSans-Regular-webfont.woff2 │ │ │ │ ├── PatternFlyIcons-webfont.eot │ │ │ │ ├── PatternFlyIcons-webfont.ttf │ │ │ │ ├── PatternFlyIcons-webfont.woff │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ ├── fontawesome-webfont.woff2 │ │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ │ └── glyphicons-halflings-regular.woff2 │ │ │ ├── img │ │ │ │ ├── OpenShift-Logo-NoText.svg │ │ │ │ ├── OpenShift-Logo-Text.svg │ │ │ │ ├── OpenShift-logo.svg │ │ │ │ ├── RH_Atomic-Logo-NoText.svg │ │ │ │ ├── RH_Atomic-Logo-Text.svg │ │ │ │ ├── RH_atomic.svg │ │ │ │ ├── apple-touch-icon-precomposed-114.png │ │ │ │ ├── apple-touch-icon-precomposed-144.png │ │ │ │ ├── apple-touch-icon-precomposed-152.png │ │ │ │ ├── apple-touch-icon-precomposed-180.png │ │ │ │ ├── apple-touch-icon-precomposed-57.png │ │ │ │ ├── apple-touch-icon-precomposed-72.png │ │ │ │ ├── apple-touch-icon-precomposed-76.png │ │ │ │ ├── bg-login.jpg │ │ │ │ ├── bg-modal-about-pf.png │ │ │ │ ├── bg-navbar-pf-alt.svg │ │ │ │ ├── brand-alt.svg │ │ │ │ ├── brand.svg │ │ │ │ ├── favicon.ico │ │ │ │ ├── kubernetes-Logo.svg │ │ │ │ ├── kubernetes.svg │ │ │ │ ├── logo-alt.svg │ │ │ │ ├── logo.svg │ │ │ │ ├── spinner-inverse-lg.gif │ │ │ │ ├── spinner-inverse-sm.gif │ │ │ │ ├── spinner-inverse-xs.gif │ │ │ │ ├── spinner-inverse.gif │ │ │ │ ├── spinner-lg.gif │ │ │ │ ├── spinner-sm.gif │ │ │ │ ├── spinner-xs.gif │ │ │ │ └── spinner.gif │ │ │ ├── js │ │ │ │ ├── patternfly-functions-base.js │ │ │ │ ├── patternfly-functions-charts.js │ │ │ │ ├── patternfly-functions-colors.js │ │ │ │ ├── patternfly-functions-count-chars.js │ │ │ │ ├── patternfly-functions-data-tables.js │ │ │ │ ├── patternfly-functions-fixed-heights.js │ │ │ │ ├── patternfly-functions-list.js │ │ │ │ ├── patternfly-functions-navigation.js │ │ │ │ ├── patternfly-functions-popovers.js │ │ │ │ ├── patternfly-functions-sidebar.js │ │ │ │ ├── patternfly-functions-tree-grid.js │ │ │ │ ├── patternfly-functions-vertical-nav.js │ │ │ │ ├── patternfly-functions.js │ │ │ │ ├── patternfly-functions.min.js │ │ │ │ ├── patternfly-settings-base.js │ │ │ │ ├── patternfly-settings-charts.js │ │ │ │ ├── patternfly-settings-colors.js │ │ │ │ ├── patternfly-settings.js │ │ │ │ ├── patternfly-settings.min.js │ │ │ │ ├── patternfly.dataTables.pfColVis.js │ │ │ │ ├── patternfly.dataTables.pfEmpty.js │ │ │ │ ├── patternfly.dataTables.pfEmpty.min.js │ │ │ │ ├── patternfly.dataTables.pfFilter.js │ │ │ │ ├── patternfly.dataTables.pfFilter.min.js │ │ │ │ ├── patternfly.dataTables.pfPagination.js │ │ │ │ ├── patternfly.dataTables.pfPagination.min.js │ │ │ │ ├── patternfly.dataTables.pfResize.js │ │ │ │ ├── patternfly.dataTables.pfResize.min.js │ │ │ │ ├── patternfly.dataTables.pfSelect.js │ │ │ │ ├── patternfly.dataTables.pfSelect.min.js │ │ │ │ ├── patternfly.js │ │ │ │ └── patternfly.min.js │ │ │ ├── login.html │ │ │ └── render.html │ │ └── wsgi.py │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ ├── cert.yml │ │ ├── httpdconf.yml │ │ ├── ipaconf.yml │ │ ├── keytab.yml │ │ ├── main.yml │ │ ├── sssd_ifp.yml │ │ ├── undeploy.yml │ │ └── usermachine.yml │ ├── templates │ │ ├── demostep.sh │ │ ├── getcert.sh │ │ ├── getkeytab.sh │ │ ├── ipa_democheck │ │ ├── ipa_demossh │ │ ├── ocsp.sh │ │ ├── rekeycert.sh │ │ ├── rmcert.sh │ │ ├── userpasswd.sh │ │ └── wwwdemo.conf │ └── vars │ │ └── main.yml │ ├── ipa │ ├── files │ │ ├── ipa-client.tmpfiles.conf │ │ └── replaced │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── ipaserver-master │ └── tasks │ │ └── main.yml │ ├── ipaserver-replica │ ├── tasks │ │ ├── main.yml │ │ ├── replica42.yml │ │ └── replica43.yml │ └── vars │ │ └── main.yml │ ├── ipaserver │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── pki-389ds │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── pki-ca │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml │ ├── pki-kra │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ └── tasks │ │ └── main.yml │ └── pki │ ├── handlers │ └── main.yml │ ├── meta │ └── main.yml │ ├── tasks │ ├── fetchadmincert.yml │ ├── limitmemory.yml │ └── main.yml │ └── templates │ └── pki.cfg ├── ipa-tags.txt ├── ipa-tasks.txt ├── ipa ├── Vagrantfile ├── rpms │ └── README └── setup.sh ├── ipademo ├── Vagrantfile ├── demo.txt ├── rpms │ ├── README │ └── rpms └── setup.sh ├── ipatests ├── .gitignore ├── Vagrantfile └── setup.sh ├── pki-tags.txt ├── pki-tasks.txt ├── pki ├── .gitignore ├── README ├── Vagrantfile ├── rpms │ └── README └── setup.sh └── vagrantbuilder ├── .gitignore ├── README ├── boxbuilder └── scripts ├── ipa-firstboot ├── puiterwijk-ipsilon-epel-7.repo └── vagrantsetup /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant/ 2 | 3 | /ipa/bin 4 | /ipa/inventory 5 | /ipa/rpms/* 6 | !/ipa/rpms/README 7 | 8 | /ipademo/bin 9 | /ipademo/inventory 10 | /ipademo/rpms/* 11 | !/ipademo/rpms/README 12 | 13 | /pki/rpms/* 14 | !/pki/rpms/README 15 | 16 | /vagrantbuilder/*.sh 17 | 18 | *.pyc 19 | __pycache__ 20 | venv/ 21 | playbook.retry 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | IPA_PLAYBOOK=ansible/ipa-playbook.yml 2 | PKI_PLAYBOOK=ansible/pki-playbook.yml 3 | 4 | ANSIBLE_PLAYBOOK ?= $(shell which ansible-playbook) 5 | 6 | .PHONY: all tags tasks check 7 | 8 | all: check tags tasks 9 | 10 | tags: $(ANSIBLE_PLAYBOOK) 11 | $(ANSIBLE_PLAYBOOK) --list-tags $(IPA_PLAYBOOK) > ipa-tags.txt 12 | $(ANSIBLE_PLAYBOOK) --list-tags $(PKI_PLAYBOOK) > pki-tags.txt 13 | 14 | tasks: $(ANSIBLE_PLAYBOOK) 15 | $(ANSIBLE_PLAYBOOK) --list-tasks $(IPA_PLAYBOOK) > ipa-tasks.txt 16 | $(ANSIBLE_PLAYBOOK) --list-tasks $(PKI_PLAYBOOK) > pki-tasks.txt 17 | 18 | check: $(ANSIBLE_PLAYBOOK) 19 | $(ANSIBLE_PLAYBOOK) --syntax-check $(IPA_PLAYBOOK) 20 | $(ANSIBLE_PLAYBOOK) --syntax-check $(PKI_PLAYBOOK) 21 | -------------------------------------------------------------------------------- /ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | # Fedora 23 doesn't come with Python 2. The bootstrap role installs 3 | # Python 2 and gathers facts once Python 2 is available. 4 | gathering=explicit 5 | retry_files_enabled=False 6 | 7 | [ssh_connection] 8 | pipelining=True 9 | # disable GSSAPI to avoid delays 10 | ssh_args = -o PreferredAuthentications=publickey -o ControlMaster=auto -o ControlPersist=1200s -o UserKnownHostsFile=/dev/null 11 | 12 | [privilege_escalation] 13 | become=True 14 | become_method=sudo 15 | become_user=root 16 | 17 | -------------------------------------------------------------------------------- /ansible/callback_plugins/profile_tasks.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import os 3 | import time 4 | 5 | 6 | class CallbackModule(object): 7 | """ 8 | A plugin for timing tasks 9 | """ 10 | def __init__(self): 11 | self.stats = {} 12 | self.current = None 13 | 14 | def playbook_on_task_start(self, name, is_conditional): 15 | """ 16 | Logs the start of each task 17 | """ 18 | 19 | if os.getenv("ANSIBLE_PROFILE_DISABLE") is not None: 20 | return 21 | 22 | if self.current is not None: 23 | # Record the running time of the last executed task 24 | self.stats[self.current] = time.time() - self.stats[self.current] 25 | 26 | # Record the start time of the current task 27 | self.current = name 28 | self.stats[self.current] = time.time() 29 | 30 | def playbook_on_stats(self, stats): 31 | """ 32 | Prints the timings 33 | """ 34 | 35 | if os.getenv("ANSIBLE_PROFILE_DISABLE") is not None: 36 | return 37 | 38 | # Record the timing of the very last task 39 | if self.current is not None: 40 | self.stats[self.current] = time.time() - self.stats[self.current] 41 | 42 | # Sort the tasks by their running time 43 | results = sorted( 44 | self.stats.items(), 45 | key=lambda value: value[1], 46 | reverse=True, 47 | ) 48 | 49 | # Print the timings 50 | fast = 0 51 | fast_threshold = 0.5 52 | for name, elapsed in results: 53 | if elapsed < fast_threshold: 54 | fast += 1 55 | continue 56 | print( 57 | "{0:-<70}{1:->9}".format( 58 | '{0} '.format(name), 59 | ' {0:.02f}s'.format(elapsed), 60 | ) 61 | ) 62 | 63 | print("{0} tasks faster than {1} seconds".format(fast, fast_threshold)) 64 | 65 | total_seconds = sum([x[1] for x in self.stats.items()]) 66 | print("\nPlaybook finished: {0}, {1} total tasks. {2} elapsed. \n".format( 67 | time.asctime(), 68 | len(self.stats.items()), 69 | datetime.timedelta(seconds=(int(total_seconds))) 70 | ) 71 | ) 72 | -------------------------------------------------------------------------------- /ansible/group_vars/all: -------------------------------------------------------------------------------- 1 | --- 2 | ansible_ssh_port: 22 3 | 4 | ipa_domain: "{{ ansible_domain }}" 5 | ipa_dm_password: "DMSecret456" 6 | ipa_admin_password: "Secret123" 7 | use_kkdcp: false 8 | http_keytab: /etc/httpd/conf/http.keytab 9 | # all hosts except localhost 10 | ipa_hosts: "{{ groups['all'] | difference(['localhost']) }}" 11 | 12 | ipa_data_dir: "{{ inventory_dir }}/ipadata" 13 | ipa_script_dir: "{{ ipa_data_dir }}/bin" 14 | ipa_rpm_dir: "{{ ipa_data_dir }}/rpms" 15 | ipa_firefox_dir: "{{ ipa_data_dir }}/firefox" 16 | 17 | # 18 | # User options 19 | # ------------ 20 | # 21 | #coprs_enabled: 22 | # - "@freeipa/freeipa-4-3" 23 | custom_rpms: false 24 | package_install: true 25 | package_upgrade: false 26 | selinux_state: enforcing 27 | selinux_policy: targeted 28 | enable_packages: true 29 | enable_network: true 30 | enable_forwarders: "{{ enable_network }}" 31 | -------------------------------------------------------------------------------- /ansible/group_vars/ipa_vpnserver: -------------------------------------------------------------------------------- 1 | --- 2 | use_kkdcp: true 3 | -------------------------------------------------------------------------------- /ansible/group_vars/pki_server: -------------------------------------------------------------------------------- 1 | --- 2 | suffix: dc=example,dc=org 3 | ldap_port: 389 4 | http_port: 8080 5 | https_port: 8443 6 | pki_instance_name: pki-tomcat 7 | security_domain: pki-tests 8 | 9 | dm_password: "DMSecret456" 10 | 11 | pki_password: "Secret123" 12 | pkcs12_password: "{{ pki_password }}" 13 | client_db_password: "{{ pki_password }}" 14 | backup_password: "{{ pki_password }}" 15 | security_domain_password: "{{ pki_password }}" 16 | token_password: "{{ pki_password }}" 17 | ca_password: "{{ pki_password }}" 18 | kra_password: "{{ pki_password }}" 19 | ocsp_password: "{{ pki_password }}" 20 | -------------------------------------------------------------------------------- /ansible/ipa-playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Use roles instead of meta to parallelize common tasks 3 | - name: install IPA base system 4 | any_errors_fatal: true 5 | hosts: all 6 | roles: 7 | - ipa 8 | 9 | - name: install IPA server system 10 | any_errors_fatal: true 11 | hosts: 12 | - ipaserver_master 13 | - ipaserver_replica 14 | roles: 15 | - ipaserver 16 | 17 | - name: install FreeIPA server master 18 | any_errors_fatal: true 19 | hosts: 20 | - ipaserver_master 21 | roles: 22 | - ipaserver-master 23 | 24 | - name: create local inventory files 25 | any_errors_fatal: true 26 | hosts: 27 | - ipaserver_master 28 | roles: 29 | - ipa-inventory 30 | 31 | - name: install FreeIPA server replica 32 | any_errors_fatal: true 33 | hosts: 34 | - ipaserver_replica 35 | roles: 36 | - ipaserver-replica 37 | 38 | - name: install FreeIPA client 39 | any_errors_fatal: true 40 | hosts: 41 | - ipa_client 42 | - ipa_nfsserver 43 | - ipa_smbserver 44 | - ipa_vpnserver 45 | - ipa_httpexample 46 | - ipa_ipsilon_idp 47 | - ipa_wwwdemo 48 | roles: 49 | - ipa-client 50 | # workaround for join race-condition in 4.3.0 51 | serial: 1 52 | 53 | - name: install OpenConnect VPN server for FreeIPA 54 | any_errors_fatal: true 55 | hosts: 56 | - ipa_vpnserver 57 | roles: 58 | - ipa-vpnserver 59 | 60 | - name: install FreeIPA NFS server 61 | any_errors_fatal: true 62 | hosts: 63 | - ipa_nfsserver 64 | roles: 65 | - ipa-nfsserver 66 | 67 | - name: install FreeIPA Samba server 68 | any_errors_fatal: true 69 | hosts: 70 | - ipa_smbserver 71 | roles: 72 | - ipa-smbserver 73 | 74 | - name: install FreeIPA HTTP example app 75 | any_errors_fatal: true 76 | hosts: 77 | - ipa_httpexample 78 | roles: 79 | - ipa-httpexample 80 | 81 | - name: install Ipsilon Identity Provider 82 | any_errors_fatal: true 83 | hosts: 84 | - ipa_ipsilon_idp 85 | roles: 86 | - ipa-ipsilon-idp 87 | 88 | - name: install Ipsilon SP example 89 | any_errors_fatal: true 90 | hosts: 91 | - ipa_sp_example 92 | roles: 93 | - ipa-sp-example 94 | 95 | - name: install WWW demo 96 | any_errors_fatal: true 97 | hosts: 98 | - ipa_wwwdemo 99 | roles: 100 | - ipa-wwwdemo 101 | 102 | - name: Create integration test files 103 | any_errors_fatal: true 104 | hosts: 105 | - ipa_tests 106 | roles: 107 | - ipa-tests 108 | 109 | - name: Tidy up 110 | hosts: all 111 | roles: 112 | - ipa-tidy 113 | -------------------------------------------------------------------------------- /ansible/library/resolver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # (c) 2013, Jan-Piet Mens 5 | # 6 | # This file is part of Ansible 7 | # 8 | # Ansible is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # Ansible is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with Ansible. If not, see . 20 | # 21 | # 22 | 23 | import re 24 | 25 | from ansible.module_utils.basic import * 26 | 27 | DOCUMENTATION = ''' 28 | --- 29 | module: resolver 30 | short_description: Get information from the system's resolver 31 | description: 32 | - Obtains nameserver addresses from C(/etc/resolv.conf) 33 | version_added: "1.3" 34 | options: 35 | resolvconf: 36 | description: 37 | - the file (in C(/etc/resolv.conf)-format) to parse 38 | required: false 39 | default: /etc/resolv.conf 40 | aliases: [] 41 | author: Jan-Piet Mens 42 | ''' 43 | 44 | EXAMPLES = ''' 45 | # Get nameserver entries from /etc/resolv.conf and print first one 46 | - resolver: 47 | register: res 48 | - debug: msg={{ res.nameservers[0] }} 49 | ''' 50 | 51 | 52 | # =========================================== 53 | # Support methods 54 | 55 | def get_nameservers(module, resolvconf=None): 56 | nameservers = [] 57 | searchlist = None 58 | 59 | if resolvconf is None: 60 | resolvconf = '/etc/resolv.conf' 61 | 62 | r = open(resolvconf) 63 | line = r.readline() 64 | while line: 65 | try: 66 | s = re.search(r"^search\s+(.+)", line) 67 | if s is not None: 68 | searchlist = s.group(1).split() 69 | except: 70 | pass 71 | try: 72 | ip = re.search(r"^nameserver\s+([^\s]+)", line) 73 | if ip is not None: 74 | nameservers.append(ip.group(1)) 75 | except: 76 | pass 77 | line = r.readline() 78 | 79 | r.close() 80 | return dict(nameservers=nameservers, searchlist=searchlist) 81 | 82 | 83 | # ============================================================== 84 | # main 85 | 86 | def main(): 87 | module = AnsibleModule( 88 | argument_spec=dict( 89 | resolvconf=dict(required=False), 90 | ) 91 | ) 92 | 93 | resolvconf = module.params['resolvconf'] 94 | 95 | data = get_nameservers(module, resolvconf=resolvconf) 96 | 97 | # Mission complete 98 | module.exit_json(**data) 99 | 100 | 101 | if __name__ == '__main__': 102 | main() 103 | -------------------------------------------------------------------------------- /ansible/library/reversezone.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # (c) 2016, Christian Heimes 5 | 6 | from ansible.module_utils.basic import * 7 | 8 | DOCUMENTATION = """ 9 | --- 10 | module: reversezone 11 | short_description: get reverse zone from an IP address 12 | description: 13 | - get reverse zone from an IP address 14 | version_added: "1.1" 15 | options: 16 | ipaddress: 17 | description: 18 | - IP address 19 | required: true 20 | default: 21 | aliases: [] 22 | author: Christian Heimes 23 | """ 24 | 25 | EXAMPLES = """ 26 | # Get reverse zone 27 | - reversezone: ipaddress={{ ansible_default_ipv4.address }} 28 | register: res 29 | - debug: msg={{ res }} 30 | """ 31 | 32 | 33 | def get_reversezone(module, ipaddress): 34 | if ':' in ipaddress: 35 | raise ValueError('IPv6 not supported yet') 36 | parts = ipaddress.split('.') 37 | if len(parts) != 4: 38 | raise ValueError('Not an IPv4 address: %r' % ipaddress) 39 | parts = [int(p) for p in parts] 40 | return '{0[2]}.{0[1]}.{0[0]}.in-addr.arpa.'.format(parts) 41 | 42 | 43 | def main(): 44 | module = AnsibleModule( 45 | argument_spec=dict( 46 | ipaddress=dict(required=True), 47 | ) 48 | ) 49 | 50 | ipaddress = module.params['ipaddress'] 51 | try: 52 | reversezone = get_reversezone(module, ipaddress) 53 | except Exception as e: 54 | module.fail_json(msg=str(e)) 55 | else: 56 | module.exit_json(changed=True, reversezone=reversezone) 57 | 58 | 59 | if __name__ == '__main__': 60 | main() 61 | -------------------------------------------------------------------------------- /ansible/library/waitforcertmonger.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """Wait for certmonger 4 | 5 | (c) 2016, Christian Heimes 6 | """ 7 | import subprocess 8 | import time 9 | 10 | from ansible.module_utils.basic import * 11 | 12 | DOCUMENTATION = """ 13 | --- 14 | module: waitforcertmonger 15 | short_description: Wait for certmonger to fetch a cert 16 | description: 17 | version_added: "1.0" 18 | options: 19 | max_retries: 20 | description: 21 | - how many retries 22 | required: false 23 | default: 6 24 | aliases: [] 25 | sleep: 26 | description: 27 | - how long to sleep between retries 28 | required: false 29 | default: 5 30 | aliases: [] 31 | author: Christian Heimes 32 | """ 33 | 34 | EXAMPLES = """ 35 | # Get reverse zone 36 | - waitforcertmonger 37 | """ 38 | 39 | 40 | class CAUnreachable(Exception): 41 | pass 42 | 43 | 44 | def get_status(): 45 | stdout = subprocess.check_output(['ipa-getcert', 'list']) 46 | if 'CA_UNREACHABLE' in stdout: 47 | raise CAUnreachable(stdout) 48 | for line in stdout.splitlines(): 49 | line = line.strip() 50 | if line.startswith('status') and line != 'status: MONITORING': 51 | return line, stdout 52 | return True, stdout 53 | 54 | 55 | def main(): 56 | module = AnsibleModule( 57 | argument_spec=dict( 58 | max_retries=dict(default=10, type='int'), 59 | sleep=dict(default=3, type='int'), 60 | ) 61 | ) 62 | 63 | max_retries = int(module.params.get('max_retries', 6)) 64 | sleep = int(module.params.get('sleep', 5)) 65 | 66 | states = [] 67 | kwargs = {'states': states, 'stdout': '', 'changed': False} 68 | 69 | for i in range(1, max_retries + 1): 70 | try: 71 | status, stdout = get_status() 72 | except CAUnreachable as e: 73 | status = 'CA_UNREACHABLE' 74 | stdout = e.args[0] 75 | subprocess.check_call(['systemctl', 'restart', 'certmonger.service']) 76 | 77 | kwargs['stdout'] = stdout 78 | if status is True: 79 | module.exit_json(**kwargs) 80 | else: 81 | time.sleep(sleep) 82 | kwargs['changed'] = True 83 | kwargs['states'].append(status) 84 | 85 | module.fail_json(msg='certmonger failed to retrieve cert', **kwargs) 86 | 87 | 88 | if __name__ == '__main__': 89 | main() 90 | -------------------------------------------------------------------------------- /ansible/pki-playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install Dogtag PKI CA 3 | hosts: pki_server 4 | roles: 5 | - pki-ca 6 | - pki-kra 7 | 8 | -------------------------------------------------------------------------------- /ansible/roles/bootstrap/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # A private network without forwarder has no default route. Ansible populates 3 | # ansible_default_ipv4.address from interface with a default route. 4 | - name: Check default route 5 | tags: 6 | - bootstrap 7 | raw: ip route | grep -q default 8 | failed_when: false 9 | register: default_route 10 | 11 | - name: Create some default route 12 | tags: 13 | - bootstrap 14 | raw: sudo ip route add default via $(ip route | tail -n1 | awk -F. '{printf "%u.%u.%u.1\n", $1, $2, $3}') 15 | when: default_route.rc != 0 16 | 17 | - name: Check for dnf command 18 | tags: 19 | - package-install 20 | - bootstrap 21 | raw: "which dnf 2>/dev/null" 22 | register: which_dnf 23 | failed_when: which_dnf.rc > 1 24 | changed_when: false 25 | 26 | - name: Install python2 and deps for ansible modules 27 | tags: 28 | - package-install 29 | - network 30 | - bootstrap 31 | raw: "dnf install -y python2 python2-dnf libselinux-python" 32 | args: 33 | creates: /usr/bin/python2 34 | register: result 35 | # ignore disabled repos 36 | failed_when: "result.rc != 0 and 'Error: There are no enabled repos.' not in result.stdout_lines" 37 | when: which_dnf.rc == 0 and package_install 38 | 39 | # ini_file depends on Python 2 40 | - name: Auto select fastest DNF mirror 41 | tags: 42 | - package-install 43 | - bootstrap 44 | ini_file: dest=/etc/dnf/dnf.conf 45 | section=main 46 | option=fastestmirror 47 | value=1 48 | backup=yes 49 | when: which_dnf.rc == 0 and package_install 50 | 51 | # Fedora 23+ doesn't have Python 2 installed. 52 | - name: Refresh dnf cache 53 | tags: 54 | - package-install 55 | - network 56 | - bootstrap 57 | raw: "dnf makecache" 58 | register: result 59 | # ignore disabled repos 60 | failed_when: "result.rc != 0 and 'Error: There are no enabled repos.' not in result.stdout_lines" 61 | when: which_dnf.rc == 0 and package_install 62 | 63 | - name: Gather facts 64 | tags: 65 | - bootstrap 66 | - setup 67 | setup: 68 | 69 | - name: Create directories in ipa_data_dir 70 | tags: 71 | - bootstrap 72 | become: no 73 | local_action: 74 | file path={{ item }} state=directory 75 | with_items: 76 | - "{{ ipa_data_dir }}" 77 | - "{{ ipa_script_dir }}" 78 | - "{{ ipa_rpm_dir }}" 79 | - "{{ ipa_firefox_dir }}" 80 | run_once: true 81 | changed_when: false 82 | 83 | - name: Dummy (for ansible.skip_tags) 84 | tags: 85 | - dummy 86 | raw: "true" 87 | changed_when: false 88 | -------------------------------------------------------------------------------- /ansible/roles/common/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | coprs_enabled: false 3 | package_upgrade: false 4 | custom_rpms: false 5 | -------------------------------------------------------------------------------- /ansible/roles/common/handlers/main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/common/handlers/main.yml -------------------------------------------------------------------------------- /ansible/roles/common/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - bootstrap 4 | 5 | -------------------------------------------------------------------------------- /ansible/roles/common/tasks/dnf.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Disable dnf repos to prevent network access 3 | tags: 4 | - common 5 | command: dnf config-manager --set-disabled {{ item }} 6 | with_items: 7 | - fedora 8 | - updates 9 | when: not enable_network 10 | changed_when: false 11 | 12 | - name: Enable dnf repos 13 | tags: 14 | - common 15 | command: dnf config-manager --set-enabled {{ item }} 16 | with_items: 17 | - fedora 18 | - updates 19 | when: enable_network 20 | changed_when: false 21 | failed_when: false 22 | 23 | - name: Auto select fastest DNF mirror 24 | tags: 25 | - common 26 | - package-install 27 | ini_file: dest=/etc/dnf/dnf.conf 28 | section=main 29 | option=fastestmirror 30 | value=1 31 | backup=yes 32 | 33 | - name: Enable yum for Fedora 34 | tags: 35 | - common 36 | - package-install 37 | - network 38 | command: dnf install yum-utils -y 39 | args: 40 | creates: /usr/bin/yumdownloader 41 | when: package_install 42 | -------------------------------------------------------------------------------- /ansible/roles/common/tasks/extravars.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: DNF or YUM? 3 | tags: 4 | - common 5 | set_fact: dnf_package="{{ ansible_distribution == 'Fedora' and ansible_distribution_major_version >= '22' }}" 6 | changed_when: false 7 | 8 | - name: Get nmcli device info 9 | tags: 10 | - common 11 | shell: 12 | "nmcli -t -f GENERAL.CONNECTION device show {{ ansible_default_ipv4.interface }} | awk -F: '{print $2}'" 13 | register: result 14 | changed_when: false 15 | 16 | - name: Set nmcli device info fact 17 | tags: 18 | - common 19 | set_fact: nm_conn="'{{ result.stdout_lines[0] }}'" 20 | changed_when: false 21 | 22 | -------------------------------------------------------------------------------- /ansible/roles/common/tasks/yum.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Disable yum repos to prevent network access 3 | tags: 4 | - common 5 | command: yum-config-manager --disable {{ item }} 6 | with_items: 7 | - fedora 8 | - updates 9 | when: not enable_network 10 | changed_when: false 11 | 12 | - name: Enable yum repos 13 | tags: 14 | - common 15 | command: yum-config-manager --enable {{ item }} 16 | with_items: 17 | - fedora 18 | - updates 19 | when: enable_network 20 | changed_when: false 21 | 22 | - name: Auto-select fastest yum mirror 23 | tags: 24 | - common 25 | - package-install 26 | - network 27 | package: name=yum-plugin-fastestmirror state=present 28 | when: package_install 29 | -------------------------------------------------------------------------------- /ansible/roles/common/templates/etc_hosts: -------------------------------------------------------------------------------- 1 | 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 2 | ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 3 | {{ ansible_default_ipv4.address }} {{ ansible_fqdn }} {{ ansible_hostname }} 4 | -------------------------------------------------------------------------------- /ansible/roles/ipa-client/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart autofs 3 | service: 4 | name: autofs 5 | state: restarted 6 | -------------------------------------------------------------------------------- /ansible/roles/ipa-client/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create /export home directory with correct context 3 | tags: 4 | - ipa-client 5 | - ipa-install 6 | file: 7 | path=/export 8 | state=directory 9 | owner=root 10 | group=root 11 | mode=0755 12 | seuser=system_u 13 | serole=object_r 14 | setype=home_root_t 15 | selevel=s0 16 | when: install_ipa_nfsserver 17 | 18 | - name: join FreeIPA 19 | tags: 20 | - ipa-client 21 | - ipa-install 22 | command: > 23 | ipa-client-install -U 24 | --realm {{ ipa.realm }} 25 | --domain {{ ipa.domain }} 26 | --principal admin 27 | --password {{ ipa_admin_password }} 28 | --ca-cert-file /etc/pki/ipa-ca.crt 29 | --force-join 30 | --mkhomedir 31 | --ssh-trust-dns 32 | when: not ipa.configured.client 33 | 34 | - name: Update IPA facts 35 | tags: 36 | - ipa-client 37 | ipa_facts: domain={{ ipa_domain }} 38 | -------------------------------------------------------------------------------- /ansible/roles/ipa-demoaccounts/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | -------------------------------------------------------------------------------- /ansible/roles/ipa-httpd/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | server_cert_name: location='/etc/httpd/alias',nickname='Server-Cert' 3 | -------------------------------------------------------------------------------- /ansible/roles/ipa-httpd/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart httpd 3 | service: name=httpd state=restarted 4 | -------------------------------------------------------------------------------- /ansible/roles/ipa-httpd/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - ipa-modnss 4 | -------------------------------------------------------------------------------- /ansible/roles/ipa-httpd/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Replace nss.conf port 8443 with 443 3 | tags: 4 | - ipa-modnss 5 | replace: dest=/etc/httpd/conf.d/nss.conf regexp='8443' replace='443' backup=yes 6 | notify: 7 | - restart httpd 8 | 9 | - name: Get keytab content 10 | tags: 11 | - ipa-httpd 12 | - ipa-install 13 | command: klist -ke {{ http_keytab }} 14 | register: keytab 15 | changed_when: false 16 | failed_when: "keytab.rc != 0 and 'not found' not in keytab.stderr" 17 | 18 | - name: Check for principal in keytab 19 | tags: 20 | - ipa-httpd 21 | - ipa-install 22 | changed_when: false 23 | set_fact: 24 | keytab_http_principal: "{{ 'HTTP/{{ ansible_fqdn }}' in keytab.stdout }}" 25 | 26 | - name: Create HTTP service 27 | tags: 28 | - ipa-httpd 29 | - ipa-install 30 | ipa: 31 | args="service-add --force HTTP/{{ ansible_fqdn }}" 32 | password="{{ ipa_admin_password }}" 33 | ignore_already_exists=true 34 | when: not keytab_http_principal 35 | 36 | - name: Add HTTP service to keytab 37 | tags: 38 | - ipa-httpd 39 | - ipa-install 40 | ipa: > 41 | cmd=ipa-getkeytab 42 | args="-s $IPA_SERVER -p HTTP/{{ ansible_fqdn }} -k {{ http_keytab }}" 43 | password="{{ ipa_admin_password }}" 44 | when: not keytab_http_principal 45 | notify: 46 | - restart httpd 47 | 48 | - name: chown http.keytab 49 | tags: 50 | - ipa-httpd 51 | - ipa-install 52 | file: 53 | path={{ http_keytab }} 54 | owner=apache 55 | group=apache 56 | mode=0600 57 | seuser=unconfined_u 58 | serole=object_r 59 | setype=httpd_config_t 60 | selevel=s0 61 | notify: 62 | - restart httpd 63 | 64 | # mod_nss cert 65 | - name: Get ipa-getcert list 66 | tags: 67 | - ipa-httpd 68 | - ipa-install 69 | command: 70 | ipa-getcert list 71 | register: 72 | ipa_getcert 73 | changed_when: false 74 | 75 | - name: Set has_server_cert and CA unreachable facts 76 | tags: 77 | - ipa-httpd 78 | - ipa-install 79 | set_fact: 80 | has_server_cert: "{{ server_cert_name in ipa_getcert.stdout }}" 81 | ca_unreachable: "{{ 'CA_UNREACHABLE' in ipa_getcert.stdout }}" 82 | changed_when: false 83 | 84 | - name: Restart certmonger when in state CA_UNREACHABLE 85 | tags: 86 | - ipa-httpd 87 | - ipa-install 88 | service: name=certmonger.service enabled=yes state=restarted 89 | when: ca_unreachable 90 | 91 | - name: Remove example certs from /etc/httpd/alias NSSDB 92 | tags: 93 | - ipa-httpd 94 | - ipa-install 95 | command: 96 | certutil -D -d /etc/httpd/alias/ -n 'Server-Cert' 97 | when: not has_server_cert 98 | notify: 99 | - restart httpd 100 | 101 | - name: Request certificate with ipa-getcert 102 | tags: 103 | - ipa-httpd 104 | - ipa-install 105 | ipa: 106 | cmd=ipa-getcert 107 | args="request -w -d /etc/httpd/alias -n 'Server-Cert' -t 'NSS Certificate DB' -T caIPAserviceCert -C 'systemctl reload httpd.service'" 108 | password="{{ ipa_admin_password }}" 109 | when: not has_server_cert 110 | notify: 111 | - restart httpd 112 | 113 | # Also a workaround for https://fedorahosted.org/freeipa/ticket/5653 114 | - name: Wait for certmonger 115 | tags: 116 | - ipa-httpd 117 | - ipa-install 118 | waitforcertmonger: 119 | 120 | - name: Remove welcome.conf 121 | tags: 122 | - ipa-httpd 123 | - ipa-install 124 | file: dest=/etc/httpd/conf.d/welcome.conf state=absent 125 | notify: 126 | - restart httpd 127 | 128 | - name: Enable Apache HTTPD service 129 | tags: 130 | - ipa-http 131 | - ipa-install 132 | service: name=httpd.service enabled=yes 133 | -------------------------------------------------------------------------------- /ansible/roles/ipa-httpexample/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | app_title: Demo app for mod_lookup_identity and mod_auth_gssapi 3 | -------------------------------------------------------------------------------- /ansible/roles/ipa-httpexample/files/example/html/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Login 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 14 |
15 |
16 | 17 |
18 | 19 |
20 |
21 |
22 | 23 |
24 | 25 |
26 |
27 |
28 |
29 | 30 |
31 |
32 |
33 |
34 | 35 | 36 | -------------------------------------------------------------------------------- /ansible/roles/ipa-httpexample/files/example/html/unauthorized.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Login 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 14 |
15 |

Please obtain a valid Kerberos ticket with

./ipa_kinit

16 |
17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /ansible/roles/ipa-httpexample/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart httpd 3 | service: name=httpd state=restarted 4 | 5 | - name: restart sssd 6 | service: name=sssd state=restarted 7 | 8 | - name: flush sssd 9 | command: sss_cache -E -------------------------------------------------------------------------------- /ansible/roles/ipa-httpexample/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - ipa-httpd 4 | -------------------------------------------------------------------------------- /ansible/roles/ipa-httpexample/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install Apache modules 3 | tags: 4 | - ipa-httpexample 5 | - package-install 6 | - network 7 | package: name={{ item }} state=present 8 | with_items: 9 | - mod_auth_gssapi 10 | - mod_authnz_pam 11 | - mod_intercept_form_submit 12 | - mod_lookup_identity 13 | - libsss_simpleifp 14 | - sssd-dbus 15 | - mod_nss 16 | - mod_session 17 | when: package_install 18 | notify: 19 | - restart httpd 20 | - restart sssd 21 | 22 | - name: setsebool allow_httpd_mod_auth_pam on 23 | tags: 24 | - ipa-httpexample 25 | - ipa-install 26 | seboolean: name=httpd_mod_auth_pam state=yes persistent=yes 27 | notify: 28 | - restart httpd 29 | 30 | - name: setsebool httpd_dbus_sssd on 31 | tags: 32 | - ipa-httpexample 33 | - ipa-install 34 | seboolean: name=httpd_dbus_sssd state=yes persistent=yes 35 | notify: 36 | - restart httpd 37 | 38 | - name: Add rewrite rule for / to nss.conf 39 | tags: 40 | - ipa-httpexample 41 | - ipa-install 42 | lineinfile: 43 | dest=/etc/httpd/conf.d/nss.conf 44 | regexp='^RewriteRule' 45 | line='RewriteRule ^/$ https://{{ ansible_fqdn }}/example [L,NC,R=301]' 46 | insertafter='^RewriteEngine' 47 | notify: 48 | - restart httpd 49 | 50 | # SSSD 51 | - name: Add ldap_user_extra_attrs to sssd.conf 52 | tags: 53 | - ipa-httpexample 54 | - ipa-install 55 | ini_file: 56 | dest=/etc/sssd/sssd.conf 57 | section="domain/{{ ipa.domain }}" 58 | option=ldap_user_extra_attrs 59 | value="mail, givenname, sn" 60 | notify: 61 | - restart sssd 62 | - flush sssd 63 | 64 | - name: Add [ifp]allowed_uids to sssd.conf 65 | tags: 66 | - ipa-httpexample 67 | - ipa-install 68 | ini_file: 69 | dest=/etc/sssd/sssd.conf 70 | section="ifp" 71 | option=allowed_uids 72 | value="apache, root" 73 | notify: 74 | - restart sssd 75 | - flush sssd 76 | 77 | - name: Add [ifp]user_attributes to sssd.conf 78 | tags: 79 | - ipa-httpexample 80 | - ipa-install 81 | ini_file: 82 | dest=/etc/sssd/sssd.conf 83 | section="ifp" 84 | option=user_attributes 85 | value="+mail, +givenname, +sn" 86 | notify: 87 | - restart sssd 88 | - flush sssd 89 | 90 | # XXX may override additional values 91 | - name: Add [ifp]user_attributes to sssd.conf 92 | tags: 93 | - ipa-httpexample 94 | - ipa-install 95 | ini_file: 96 | dest=/etc/sssd/sssd.conf 97 | section="sssd" 98 | option=services 99 | value="nss, sudo, pam, autofs, ssh, ifp" 100 | notify: 101 | - restart sssd 102 | - flush sssd 103 | 104 | # Example app 105 | - name: Create Apache config for example 106 | tags: 107 | - ipa-httpexample 108 | - ipa-install 109 | template: 110 | src=example.conf 111 | dest=/etc/httpd/conf.d/example.conf 112 | notify: 113 | - restart httpd 114 | 115 | - name: Copy Apache example app files 116 | tags: 117 | - ipa-httpexample 118 | - ipa-install 119 | copy: 120 | src=example/ 121 | dest=/srv/www/example/ 122 | mode=0644 123 | directory_mode=0755 124 | owner=root 125 | group=root 126 | seuser=system_u 127 | serole=object_r 128 | setype=httpd_sys_content_t 129 | selevel=s0 130 | notify: 131 | - restart httpd 132 | 133 | - name: Create Apache example app 134 | tags: 135 | - ipa-httpexample 136 | - ipa-install 137 | template: 138 | src=wsgi.py 139 | dest=/srv/www/example/wsgi.py 140 | mode=0644 141 | directory_mode=0755 142 | owner=root 143 | group=root 144 | seuser=system_u 145 | serole=object_r 146 | setype=httpd_sys_content_t 147 | selevel=s0 148 | notify: 149 | - restart httpd 150 | 151 | - name: Create PAM service for Apache example app 152 | tags: 153 | - ipa-httpexample 154 | - ipa-install 155 | template: 156 | src=pam_http_example 157 | dest=/etc/pam.d/http_example 158 | notify: 159 | - restart httpd 160 | -------------------------------------------------------------------------------- /ansible/roles/ipa-httpexample/templates/example.conf: -------------------------------------------------------------------------------- 1 | LoadModule lookup_identity_module modules/mod_lookup_identity.so 2 | 3 | # Based on ipa.conf 4 | ProxyRequests Off 5 | DirectoryIndex index.html 6 | LimitRequestFieldSize 100000 7 | 8 | # Configure mod_wsgi handler for /example 9 | WSGIDaemonProcess example display-name=%{GROUP} 10 | WSGIImportScript /srv/www/example/wsgi.py process-group=example application-group=example 11 | WSGIScriptAlias /example /srv/www/example/wsgi.py 12 | WSGIScriptReloading Off 13 | 14 | # Turn off mod_msgi handler for errors, config, crl: 15 | 16 | SetHandler None 17 | 18 | 19 | # Protect /example and everything below it in webspace with Apache Kerberos auth 20 | 21 | AuthType GSSAPI 22 | AuthName "Kerberos Login" 23 | GssapiCredStore keytab:{{ http_keytab }} 24 | # GssapiCredStore client_keytab:{{ http_keytab }} 25 | # GssapiDelegCcacheDir /var/run/httpd/example/clientcaches 26 | # GssapiAllowedMech krb5 27 | Require valid-user 28 | ErrorDocument 401 /example/errors/unauthorized.html 29 | WSGIProcessGroup example 30 | WSGIApplicationGroup example 31 | 32 | # mod_lookup_identity 33 | LookupUserGECOS REMOTE_USER_FULLNAME 34 | LookupUserGroups REMOTE_USER_GROUPS : 35 | LookupUserAttr uidNumber REMOTE_USER_UID 36 | LookupUserAttr mail REMOTE_USER_EMAIL 37 | LookupUserAttr sn REMOTE_USER_SN 38 | LookupUserAttr givenname REMOTE_USER_GIVENNAME 39 | 40 | 41 | # This is where we redirect on failed auth 42 | Alias /example/errors "/srv/www/example/html" 43 | 44 | # Do no authentication on the directory that contains error messages 45 | 46 | SetHandler None 47 | AllowOverride None 48 | Satisfy Any 49 | Allow from all 50 | ExpiresActive On 51 | ExpiresDefault "access plus 0 seconds" 52 | 53 | 54 | # List explicitly only the fonts we want to serve 55 | Alias /example/fonts/open-sans "/usr/share/fonts/open-sans" 56 | Alias /example/fonts/fontawesome "/usr/share/fonts/fontawesome" 57 | 58 | SetHandler None 59 | AllowOverride None 60 | Satisfy Any 61 | Allow from all 62 | ExpiresActive On 63 | ExpiresDefault "access plus 1 year" 64 | 65 | 66 | # Use FreeIPA webui CSS 67 | Alias /example/css "/usr/share/ipa/ui/css" 68 | 69 | SetHandler None 70 | AllowOverride None 71 | Satisfy Any 72 | Allow from all 73 | ExpiresActive On 74 | ExpiresDefault "access plus 1 year" 75 | 76 | 77 | RewriteEngine on 78 | 79 | RewriteRule ^/$ https://{{ ansible_fqdn }}/example [L,NC,R=301] 80 | 81 | RewriteCond %{HTTP_HOST} !^{{ ansible_fqdn }}$ [NC] 82 | RewriteRule ^/example/(.*) https://{{ ansible_fqdn }}/example/$1 [L,R=301] 83 | 84 | RewriteCond %{SERVER_PORT} !^443$ 85 | RewriteCond %{REQUEST_URI} !^/example/errors 86 | RewriteRule ^/example/(.*) https://{{ ansible_fqdn }}/example/$1 [L,R=301] 87 | -------------------------------------------------------------------------------- /ansible/roles/ipa-httpexample/templates/pam_http_example: -------------------------------------------------------------------------------- 1 | auth required pam_sss.so 2 | account required pam_sss.so 3 | -------------------------------------------------------------------------------- /ansible/roles/ipa-httpexample/templates/wsgi.py: -------------------------------------------------------------------------------- 1 | #/usr/bin/python2 2 | from pprint import pformat 3 | 4 | HTML = """ 5 | 6 | 7 | {title} 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 18 |
19 |
20 | {envvars} 21 |
22 | 25 |
26 |
27 | 28 | 29 | """ 30 | 31 | 32 | def application(environ, start_response): 33 | status = '200 OK' 34 | 35 | envvars = [] 36 | prefixes = ('REMOTE_USER', 'REMOTE_GROUPS') 37 | 38 | # {% if app_mellon %} 39 | 40 | prefixes += ('MELLON_',) 41 | 42 | # {% endif %} 43 | 44 | for k, v in sorted(environ.iteritems()): 45 | if not k.startswith(prefixes): 46 | continue 47 | envvars.append('
{0}
'.format(k)) 48 | if k.lower().endswith('groups'): 49 | envvars.append('
    ') 50 | for group in sorted(v.split(':')): 51 | envvars.append('
  • {0}
  • '.format(group)) 52 | envvars.append('
') 53 | else: 54 | envvars.append('
{0}
'.format(v)) 55 | 56 | kwargs = dict( 57 | title='{{ app_title }}', 58 | envvars='\n'.join(envvars), 59 | env=pformat(environ) 60 | ) 61 | output = HTML.format(**kwargs) 62 | 63 | response_headers = [ 64 | ('Content-type', 'text/html'), 65 | ('Content-Length', str(len(output))) 66 | ] 67 | start_response(status, response_headers) 68 | return [output] 69 | -------------------------------------------------------------------------------- /ansible/roles/ipa-httpexample/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | app_mellon: false 3 | -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/files/xulstore.json: -------------------------------------------------------------------------------- 1 | {"chrome://browser/content/browser.xul":{"navigator-toolbox":{"iconsize":"small"},"main-window":{"screenX":"87","screenY":"113","width":"1440","height":"783","sizemode":"normal"},"PersonalToolbar":{"collapsed":"false"},"sidebar-box":{"sidebarcommand":"","width":"","src":""},"sidebar-title":{"value":""}}} -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create Firefox prefs 3 | tags: 4 | - ipa-inventory 5 | - ipa-install 6 | template: src=firefox_prefs dest=/etc/ipa/prefs.js 7 | run_once: true 8 | 9 | - name: Create Firefox bookmarks 10 | tags: 11 | - ipa-inventory 12 | - ipa-install 13 | template: src=bookmarks.html dest=/etc/ipa/bookmarks.html 14 | run_once: true 15 | 16 | - name: Fetch Firefox files 17 | tags: 18 | - ipa-inventory 19 | - ipa-install 20 | - fetch 21 | fetch: 22 | src=/etc/ipa/{{ item }} 23 | dest={{ ipa_data_dir }}/{{ item }} 24 | flat=yes 25 | with_items: 26 | - prefs.js 27 | - bookmarks.html 28 | run_once: true 29 | 30 | - name: Copy local Firefox files 31 | tags: 32 | - ipa-inventory 33 | - ipa-install 34 | become: no 35 | local_action: 36 | copy 37 | src={{ item }} 38 | dest={{ ipa_data_dir }}/{{ item }} 39 | with_items: 40 | - xulstore.json 41 | run_once: true 42 | 43 | # ipa-vpnserver creates another krb5 config for KKDCP 44 | - name: Write custom krb5.conf 45 | tags: 46 | - ipa-inventory 47 | - ipa-install 48 | become: no 49 | local_action: 50 | template 51 | src=krb5.conf 52 | dest={{ ipa_data_dir }}/krb5.conf 53 | 54 | - name: Write custom krb5.conf for MS-KKDCP 55 | tags: 56 | - ipa-inventory 57 | - ipa-install 58 | become: no 59 | local_action: 60 | template 61 | src=krb5.conf 62 | dest={{ ipa_data_dir }}/krb5_kkdcp.conf 63 | vars: 64 | use_kkdcp: True 65 | 66 | - name: Fetch resolv.conf 67 | tags: 68 | - ipa-inventory 69 | - ipa-install 70 | - fetch 71 | fetch: 72 | src=/etc/resolv.conf 73 | dest={{ ipa_data_dir }}/resolv.conf 74 | flat=yes 75 | 76 | - name: Fetch IPA ca.crt 77 | tags: 78 | - ipa-inventory 79 | - ipa-install 80 | - fetch 81 | fetch: 82 | src=/etc/ipa/ca.crt 83 | dest={{ ipa_data_dir }}/ca.crt 84 | flat=yes 85 | 86 | - name: Fetch ipa default.conf 87 | tags: 88 | - ipa-inventory 89 | - ipa-install 90 | - fetch 91 | fetch: 92 | src=/etc/ipa/default.conf 93 | dest={{ ipa_data_dir }}/default.conf 94 | flat=yes 95 | 96 | - name: Fetch kra agent pem file 97 | tags: 98 | - ipa-inventory 99 | - ipa-install 100 | - fetch 101 | fetch: 102 | src=/etc/httpd/alias/kra-agent.pem 103 | dest={{ ipa_data_dir }}/kra-agent.pem 104 | flat=yes 105 | 106 | - name: Template local scripts 107 | tags: 108 | - ipa-inventory 109 | - ipa-install 110 | become: no 111 | local_action: 112 | template 113 | src={{ item }} 114 | dest={{ ipa_script_dir }}/{{ item }} 115 | mode=0755 116 | with_items: 117 | - ipa_firefox 118 | - ipa_kinit 119 | - ipa_kkdcp_kinit 120 | - ipa_ssh 121 | # Handled by ipa-vpnserver 122 | # - ipa_kkdcp_openconnect_kinit 123 | # - ipa_kkdcp_openconnect_vpn 124 | run_once: true 125 | 126 | - name: Template local inventory files 127 | tags: 128 | - ipa-inventory 129 | - ipa-install 130 | become: no 131 | local_action: 132 | template 133 | src={{ item }} 134 | dest={{ ipa_data_dir }}/{{ item }} 135 | mode=0644 136 | with_items: 137 | - ipa_ssh_config 138 | - ipaenv 139 | - ipaenv_kkdcp 140 | # Handled by ipa-vpnserver 141 | # - ipaenv_kkdcp_openconnect 142 | run_once: true 143 | 144 | - name: Check for NSSDB 145 | tags: 146 | - ipa-inventory 147 | - ipa-install 148 | become: no 149 | local_action: 150 | stat 151 | path={{ ipa_data_dir }}/nssdb 152 | register: nssdb 153 | run_once: true 154 | 155 | - name: Create NSSDB directory 156 | tags: 157 | - ipa-inventory 158 | - ipa-install 159 | become: no 160 | local_action: 161 | file 162 | dest={{ ipa_data_dir }}/nssdb 163 | state=directory 164 | run_once: true 165 | when: not nssdb.stat.exists 166 | 167 | - name: Create NSSDB 168 | tags: 169 | - ipa-inventory 170 | - ipa-install 171 | become: no 172 | local_action: 173 | command 174 | certutil -N -d '{{ ipa_data_dir }}/nssdb' --empty-password 175 | run_once: true 176 | when: not nssdb.stat.exists 177 | 178 | - name: Remove old CA.crt from NSSDB 179 | tags: 180 | - ipa-inventory 181 | - ipa-install 182 | become: no 183 | local_action: 184 | command 185 | certutil -D -d '{{ ipa_data_dir }}/nssdb' -n 'IPA CA' 186 | when: nssdb.stat.exists 187 | failed_when: false 188 | 189 | - name: Populate NSSDB with CA.crt 190 | tags: 191 | - ipa-inventory 192 | - ipa-install 193 | become: no 194 | local_action: 195 | command 196 | certutil -A -d '{{ ipa_data_dir }}/nssdb' -n 'IPA CA' -i '{{ ipa_data_dir }}/ca.crt' -t 'TC,C,T' 197 | run_once: true 198 | # no when, always add cert 199 | -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/templates/firefox_prefs: -------------------------------------------------------------------------------- 1 | user_pref("browser.startup.homepage", "https://{{ ansible_fqdn }}"); 2 | 3 | pref("browser.newtabpage.pinned", '[ 4 | {"url":"https://{{ ansible_fqdn }}/","title":"IPA: Master"}, 5 | {% for host in groups['ipaserver_replica'] | default([]) %} 6 | {"url":"https://{{ hostvars[host].ansible_fqdn }}/","title":"IPA: {{ hostvars[host].ansible_hostname }}"}, 7 | {% endfor %} 8 | {% for host in groups['ipa_ipsilon_idp'] | default([]) %} 9 | {"url":"https://{{ hostvars[host].ansible_fqdn }}/idp","title":"Ipsilon IdP"}, 10 | {% endfor %} 11 | {% for host in groups['ipa_sp_example'] | default([]) %} 12 | {"url":"https://{{ hostvars[host].ansible_fqdn }}/sp_example","title":"HTTP mod_auth_mellon with Ipsilon example"}, 13 | {% endfor %} 14 | {% for host in groups['ipa_httpexample'] | default([]) %} 15 | {"url":"https://{{ hostvars[host].ansible_fqdn }}/example","title":"HTTP mod_auth_gssapi / mod_lookup identity example"}, 16 | {% endfor %} 17 | {"url":"http://www.freeipa.org","title":"FreeIPA"} 18 | ]'); 19 | user_pref("browser.newtabpage.enhanced", true); 20 | user_pref("browser.newtabpage.introShown", true); 21 | 22 | pref("browser.rights.3.shown", true); 23 | pref("browser.startup.homepage_override.mstone","ignore"); 24 | pref("datareporting.healthreport.service.enabled", false); 25 | pref("datareporting.policy.dataSubmissionEnabled", false); 26 | 27 | /* Kerberos SSO configuration */ 28 | user_pref("network.negotiate-auth.trusted-uris", ".{{ ipa.domain }}"); 29 | pref("network.negotiate-auth.trusted-uris", ".{{ ipa.domain }}"); 30 | 31 | /* These are the defaults */ 32 | pref("network.negotiate-auth.gsslib", ""); 33 | pref("network.negotiate-auth.using-native-gsslib", true); 34 | pref("network.negotiate-auth.allow-proxies", true); 35 | -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/templates/ipa_firefox: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | . "{{ ipa_data_dir }}/ipaenv" 5 | 6 | if [ -z "${IPA_FIREFOX}" ]; then 7 | echo "empty IPA_FIREFOX var" 8 | exit 1 9 | fi 10 | 11 | rm -rf "${IPA_FIREFOX}" 12 | mkdir "${IPA_FIREFOX}" 13 | 14 | cp "${IPA_INVENTORY}/prefs.js" "${IPA_FIREFOX}/" 15 | cp "${IPA_INVENTORY}/bookmarks.html" "${IPA_FIREFOX}/" 16 | cp "${IPA_INVENTORY}/xulstore.json" "${IPA_FIREFOX}/" 17 | 18 | certutil -N -d "${IPA_FIREFOX}" --empty-password 19 | certutil -A -d "${IPA_FIREFOX}" -n 'IPA CA' -i "${IPA_INVENTORY}/ca.crt" -t "TC,C,T" 20 | 21 | firefox -no-remote -profile "${IPA_FIREFOX}" $@ 22 | -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/templates/ipa_kinit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | . "{{ ipa_data_dir }}/ipaenv" 5 | 6 | # pkinit depends krb5-pkinit package 7 | /usr/bin/kinit -c ${KRB5CCNAMEARMOR} -n 8 | /usr/bin/kinit -T ${KRB5CCNAMEARMOR} $@ 9 | -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/templates/ipa_kkdcp_kinit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | . "{{ ipa_data_dir }}/ipaenv_kkdcp" 5 | 6 | /usr/bin/kinit -c ${KRB5CCNAMEARMOR} -n 7 | /usr/bin/kinit -T ${KRB5CCNAMEARMOR} $@ 8 | -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/templates/ipa_kkdcp_openconnect_kinit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | . "{{ ipa_data_dir }}/ipaenv_kkdcp_openconnect" 5 | 6 | /usr/bin/kinit $@ 7 | -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/templates/ipa_kkdcp_openconnect_vpn: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | . "{{ ipa_data_dir }}/ipaenv_kkdcp" 5 | 6 | openconnect --cafile ${IPA_INVENTORY}/ca.crt vpn.ipa.example $@ 7 | -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/templates/ipa_ssh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | . "{{ ipa_data_dir }}/ipaenv" 5 | 6 | ssh -F "${IPA_INVENTORY}/ipa_ssh_config" $@ 7 | -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/templates/ipa_ssh_config: -------------------------------------------------------------------------------- 1 | Host * 2 | GSSAPIAuthentication yes 3 | GSSAPIDelegateCredentials yes 4 | PreferredAuthentications gssapi-with-mic 5 | VerifyHostKeyDNS yes 6 | # pubkey auth slows us down 7 | PubkeyAuthentication no 8 | IdentitiesOnly yes 9 | IdentityFile /dev/null 10 | # don't use host key validation for the demo 11 | UserKnownHostsFile /dev/null 12 | StrictHostKeyChecking no 13 | -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/templates/ipaenv: -------------------------------------------------------------------------------- 1 | export IPA_INVENTORY="{{ ipa_data_dir }}" 2 | export IPA_FIREFOX="{{ ipa_firefox_dir }}" 3 | 4 | export IPA_CONFDIR="${IPA_INVENTORY}" 5 | export KRB5_CONFIG="${IPA_INVENTORY}/krb5.conf" 6 | export KRB5CCNAME="${IPA_INVENTORY}/ccache" 7 | export KRB5CCNAMEARMOR="${IPA_INVENTORY}/ccache.armor" 8 | 9 | export PS1="[\u@\h \W]\[\e[44m\][IPA]\[\e[m\]\$ " 10 | -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/templates/ipaenv_kkdcp: -------------------------------------------------------------------------------- 1 | export IPA_INVENTORY="{{ ipa_data_dir }}" 2 | export IPA_FIREFOX="{{ ipa_firefox_dir }}" 3 | 4 | export IPA_CONFDIR="${IPA_INVENTORY}" 5 | export KRB5_CONFIG="${IPA_INVENTORY}/krb5_kkdcp.conf" 6 | export KRB5CCNAME="${IPA_INVENTORY}/ccache_kkdcp" 7 | -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/templates/ipaenv_kkdcp_openconnect: -------------------------------------------------------------------------------- 1 | export IPA_INVENTORY="{{ ipa_data_dir }}" 2 | export IPA_FIREFOX="{{ ipa_firefox_dir }}" 3 | export KRB5_CONFIG="${IPA_INVENTORY}/krb5_kkdcp_openconnect.conf" 4 | -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/templates/krb5.conf: -------------------------------------------------------------------------------- 1 | [logging] 2 | default = FILE:/var/log/krb5libs.log 3 | kdc = FILE:/var/log/krb5kdc.log 4 | admin_server = FILE:/var/log/kadmind.log 5 | 6 | [libdefaults] 7 | default_realm = {{ ipa.realm }} 8 | dns_lookup_realm = false 9 | dns_lookup_kdc = false 10 | rdns = false 11 | ticket_lifetime = 24h 12 | forwardable = yes 13 | udp_preference_limit = 0 14 | {% if use_kkdcp %} 15 | default_ccache_name = FILE:{{ ipa_data_dir }}/ccache_kkdcp 16 | {% else %} 17 | default_ccache_name = FILE:{{ ipa_data_dir }}/ccache 18 | {% endif %} 19 | 20 | [realms] 21 | {{ ipa.realm }} = { 22 | {% if use_kkdcp %} 23 | kdc = https://{{ ansible_fqdn }}/KdcProxy 24 | master_kdc = https://{{ ansible_fqdn }}/KdcProxy 25 | admin_server = https://{{ ansible_fqdn }}/KdcProxy 26 | kpasswd_server = https://{{ ansible_fqdn }}/KdcProxy 27 | {% else %} 28 | kdc = {{ ansible_fqdn }}:88 29 | master_kdc = {{ ansible_fqdn }}:88 30 | admin_server = {{ ansible_fqdn }}:749 31 | kpasswd_server = {{ ansible_fqdn }}:464 32 | {% endif %} 33 | default_domain = {{ ipa.domain }} 34 | pkinit_anchors = FILE:{{ ipa_data_dir }}/ca.crt 35 | http_anchors = FILE:{{ ipa_data_dir }}/ca.crt 36 | } 37 | 38 | [domain_realm] 39 | .{{ ipa.domain }} = {{ ipa.realm }} 40 | {{ ipa.domain }} = {{ ipa.realm }} 41 | -------------------------------------------------------------------------------- /ansible/roles/ipa-inventory/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | use_kkdcp: false 3 | -------------------------------------------------------------------------------- /ansible/roles/ipa-ipsilon-idp/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart httpd 3 | service: name=httpd state=restarted 4 | -------------------------------------------------------------------------------- /ansible/roles/ipa-ipsilon-idp/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - ipa-httpd 4 | -------------------------------------------------------------------------------- /ansible/roles/ipa-ipsilon-idp/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Ipsilon server packages 3 | tags: 4 | - ipa-ipsilon-idp 5 | - package-install 6 | - network 7 | package: name={{ item }} state=present 8 | with_items: 9 | - ipsilon 10 | - ipsilon-saml2 11 | - ipsilon-openid 12 | - ipsilon-openidc 13 | - ipsilon-persona 14 | - ipsilon-authform 15 | - ipsilon-infosssd 16 | - ipsilon-tools-ipa 17 | - ipsilon-authgssapi 18 | when: package_install 19 | 20 | - name: Install Ipsilon IdP 21 | tags: 22 | - ipa-ipsilon-idp 23 | - ipa-install 24 | command: > 25 | ipsilon-server-install 26 | --admin-user admin 27 | --secure yes 28 | --openid yes 29 | --persona yes 30 | --saml2 yes 31 | --saml2-metadata-validity 185 32 | --form yes 33 | --gssapi yes 34 | --gssapi-httpd-keytab /etc/httpd/conf/http.keytab 35 | --info-sssd yes 36 | --info-sssd-domain {{ ipa.domain }} 37 | --ipa yes 38 | args: 39 | creates: /etc/ipsilon/idp/idp.conf 40 | notify: 41 | - restart httpd 42 | 43 | - name: Use NSS instead of mod_ssl 44 | tags: 45 | - ipa-ipsilon-idp 46 | - ipa-install 47 | replace: 48 | regexp='SSLRequireSSL' 49 | replace='NSSRequireSSL' 50 | dest=/etc/httpd/conf.d/ipsilon-idp.conf 51 | notify: 52 | - restart httpd 53 | -------------------------------------------------------------------------------- /ansible/roles/ipa-modnss/files/replaced: -------------------------------------------------------------------------------- 1 | # This configuration file has been replaced with an empty file for FreeIPA. 2 | -------------------------------------------------------------------------------- /ansible/roles/ipa-modnss/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart httpd 3 | service: name=httpd state=restarted 4 | -------------------------------------------------------------------------------- /ansible/roles/ipa-modnss/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Apache HTTPD with mod_nss 3 | tags: 4 | - ipa-modnss 5 | - package-install 6 | - network 7 | package: name={{ item }} state=present 8 | with_items: 9 | - httpd 10 | - mod_nss 11 | when: package_install 12 | 13 | - name: Open Firewall for Apache 14 | tags: 15 | - ipa-modnss 16 | - firewall 17 | firewalld: 18 | service={{ item }} 19 | permanent=true 20 | state=enabled 21 | immediate=yes 22 | with_items: 23 | - http 24 | - https 25 | when: has_firewalld.stat.exists 26 | 27 | - name: Check for mod_ssl configuration 28 | tags: 29 | - ipa-modnss 30 | stat: path=/etc/httpd/conf.d/ssl.conf 31 | register: ssl_conf 32 | 33 | - name: Disable mod_ssl configuration 34 | tags: 35 | - ipa-modnss 36 | copy: 37 | src=replaced 38 | dest={{ item }} 39 | backup=true 40 | owner=root 41 | group=root 42 | mode=0644 43 | with_items: 44 | - /etc/httpd/conf.d/ssl.conf 45 | - /etc/httpd/conf.modules.d/00-ssl.conf 46 | when: ssl_conf.stat.exists 47 | notify: 48 | - restart httpd 49 | 50 | # Other roles use rewrite rules 51 | - name: Enable rewrite engine for nss.conf 52 | tags: 53 | - ipa-modnss 54 | lineinfile: 55 | dest=/etc/httpd/conf.d/nss.conf 56 | regexp='^RewriteEngine' 57 | line='RewriteEngine On' 58 | insertafter='^NSSEngine' 59 | notify: 60 | - restart httpd 61 | -------------------------------------------------------------------------------- /ansible/roles/ipa-modssl/files/replaced: -------------------------------------------------------------------------------- 1 | # This configuration file has been replaced with an empty file for FreeIPA. 2 | -------------------------------------------------------------------------------- /ansible/roles/ipa-modssl/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart httpd 3 | service: name=httpd state=restarted 4 | -------------------------------------------------------------------------------- /ansible/roles/ipa-modssl/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Apache HTTPD with mod_ssl 3 | tags: 4 | - ipa-modssl 5 | - package-install 6 | - network 7 | package: name={{ item }} state=present 8 | with_items: 9 | - httpd 10 | - mod_ssl 11 | when: package_install 12 | 13 | - name: Open Firewall for Apache 14 | tags: 15 | - ipa-modssl 16 | - firewall 17 | firewalld: 18 | service={{ item }} 19 | permanent=true 20 | state=enabled 21 | immediate=yes 22 | with_items: 23 | - http 24 | - https 25 | when: has_firewalld.stat.exists 26 | 27 | - name: Check for mod_nss configuration 28 | tags: 29 | - ipa-modssl 30 | stat: path=/etc/httpd/conf.d/nss.conf 31 | register: nss_conf 32 | 33 | - name: Disable mod_nss configuration 34 | tags: 35 | - ipa-modssk 36 | copy: 37 | src=replaced 38 | dest={{ item }} 39 | backup=true 40 | owner=root 41 | group=root 42 | mode=0644 43 | with_items: 44 | - /etc/httpd/conf.d/nss.conf 45 | - /etc/httpd/conf.modules.d/10-nss.conf 46 | when: nss_conf.stat.exists 47 | notify: 48 | - restart httpd 49 | -------------------------------------------------------------------------------- /ansible/roles/ipa-nfsserver/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart NFS 3 | service: name=nfs-server state=restarted 4 | -------------------------------------------------------------------------------- /ansible/roles/ipa-smbserver/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart samba 3 | service: name={{ item }} state=restarted 4 | with_items: 5 | - smb.service 6 | - nmb.service 7 | 8 | - name: restart sssd 9 | service: name=sssd state=restarted 10 | -------------------------------------------------------------------------------- /ansible/roles/ipa-smbserver/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install Samba dependencies 3 | tags: 4 | - ipa-smbserver 5 | - package-install 6 | - network 7 | package: name={{ item }} state=present 8 | with_items: 9 | - samba 10 | - samba-client 11 | - sssd-libwbclient 12 | when: package_install 13 | notify: 14 | - restart sssd 15 | - restart samba 16 | 17 | - name: Open Firewall for Samba 18 | tags: 19 | - ipa-smbserver 20 | - firewall 21 | firewalld: 22 | service={{ item }} 23 | permanent=true 24 | state=enabled 25 | immediate=yes 26 | with_items: 27 | - samba 28 | when: has_firewalld.stat.exists 29 | 30 | - name: setsebool samba_enable_home_dirs on 31 | tags: 32 | - ipa-smbserver 33 | - ipa-install 34 | seboolean: name=samba_enable_home_dirs state=yes persistent=yes 35 | 36 | - name: Get keytab content 37 | tags: 38 | - ipa-smbserver 39 | - ipa-install 40 | command: klist -ke /etc/samba/samba.keytab 41 | register: keytab 42 | changed_when: false 43 | failed_when: "keytab.rc != 0 and 'not found' not in keytab.stderr" 44 | 45 | - name: Check for principal in keytab 46 | tags: 47 | - ipa-smbserver 48 | - ipa-install 49 | changed_when: false 50 | set_fact: 51 | keytab_cifs_principal: "{{ 'cifs/{{ ansible_fqdn }}' in keytab.stdout }}" 52 | 53 | - name: Create CIFS service 54 | tags: 55 | - ipa-smbserver 56 | - ipa-install 57 | ipa: 58 | args="service-add --force cifs/{{ ansible_fqdn }}" 59 | password="{{ ipa_admin_password }}" 60 | ignore_already_exists=true 61 | when: not keytab_cifs_principal 62 | 63 | - name: Add CIFS service to keytab 64 | tags: 65 | - ipa-smbserver 66 | - ipa-install 67 | ipa: > 68 | cmd=ipa-getkeytab 69 | args="-s $IPA_SERVER -p cifs/{{ ansible_fqdn }} -k /etc/samba/samba.keytab" 70 | password="{{ ipa_admin_password }}" 71 | when: not keytab_cifs_principal 72 | notify: 73 | - restart samba 74 | 75 | - name: Write smb.conf 76 | tags: 77 | - ipa-smbserver 78 | - ipa-install 79 | template: 80 | src=smb.conf 81 | dest=/etc/samba/smb.conf 82 | force=yes 83 | backup=true 84 | notify: 85 | - restart samba 86 | 87 | - name: Enable Samba services 88 | tags: 89 | - ipa-smbserver 90 | - ipa-install 91 | service: name={{ item }} enabled=yes state=started 92 | with_items: 93 | - smb.service 94 | - nmb.service 95 | -------------------------------------------------------------------------------- /ansible/roles/ipa-smbserver/templates/smb.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | workgroup = {{ ipa.domain | upper | regex_replace('\.', '') }} 3 | realm = {{ ipa.realm }} 4 | dedicated keytab file = FILE:/etc/samba/samba.keytab 5 | kerberos method = dedicated keytab 6 | log file = /var/log/samba/log.%m 7 | security = ads 8 | preferred master = yes 9 | local master = yes 10 | 11 | [homes] 12 | browsable = no 13 | writable = yes 14 | -------------------------------------------------------------------------------- /ansible/roles/ipa-sp-example/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | app_title: Demo app for mod_auth_mellon SP with Ipsilon IdP 3 | -------------------------------------------------------------------------------- /ansible/roles/ipa-sp-example/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart httpd 3 | service: name=httpd state=restarted 4 | -------------------------------------------------------------------------------- /ansible/roles/ipa-sp-example/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - ipa-modnss 4 | - ipa-httpd 5 | -------------------------------------------------------------------------------- /ansible/roles/ipa-sp-example/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Ipsilon client package 3 | tags: 4 | - ipa-sp-example 5 | - package-install 6 | - network 7 | package: name={{ item }} state=present 8 | with_items: 9 | - ipsilon-client 10 | - mod_nss 11 | - mod_wsgi 12 | when: package_install 13 | 14 | - name: Set IdP url fact 15 | tags: 16 | - ipa-sp-example 17 | - ipa-install 18 | set_fact: idp_fqdn="{{ hostvars[groups['ipa_ipsilon_idp'][0]].ansible_fqdn }}" 19 | when: groups['ipa_ipsilon_idp'] 20 | 21 | - name: Check for /etc/httpd/conf.d/ipsilon-saml.conf 22 | tags: 23 | - ipa-sp-example 24 | - ipa-install 25 | stat: path=/etc/httpd/conf.d/ipsilon-saml.conf 26 | register: ipsilon_saml 27 | 28 | - name: Write password to file 29 | tags: 30 | - ipa-sp-example 31 | - ipa-install 32 | template: 33 | src=admin_password 34 | dest=/root/admin_password 35 | when: not ipsilon_saml.stat.exists and groups['ipa_ipsilon_idp'] 36 | 37 | - name: Install Ipsilon client 38 | tags: 39 | - ipa-sp-example 40 | - ipa-install 41 | command: > 42 | ipsilon-client-install 43 | --admin-user admin 44 | --admin-password /root/admin_password 45 | --saml-idp-url https://{{ idp_fqdn }}/idp/ 46 | --saml-sp-name 'Fileserver' 47 | --saml-idp-metadata https://{{ idp_fqdn }}/idp/saml2/metadata 48 | --saml-auth /sp_example 49 | args: 50 | creates: 51 | /etc/httpd/conf.d/ipsilon-saml.conf 52 | when: groups['ipa_ipsilon_idp'] 53 | 54 | - name: Remove password file 55 | tags: 56 | - ipa-sp-example 57 | - ipa-install 58 | file: dest=/root/admin_password state=absent 59 | 60 | - name: Create /srv/www/sp_example 61 | tags: 62 | - ipa-sp-example 63 | - ipa-install 64 | file: 65 | path=/srv/www/sp_example 66 | mode=0755 67 | state=directory 68 | owner=root 69 | group=root 70 | seuser=system_u 71 | serole=object_r 72 | setype=httpd_sys_content_t 73 | selevel=s0 74 | 75 | - name: Create Apache SP example app 76 | tags: 77 | - ipa-sp-example 78 | - ipa-install 79 | template: 80 | src=../../ipa-httpexample/templates/wsgi.py 81 | dest=/srv/www/sp_example/wsgi.py 82 | mode=0644 83 | directory_mode=0755 84 | owner=root 85 | group=root 86 | seuser=system_u 87 | serole=object_r 88 | setype=httpd_sys_content_t 89 | selevel=s0 90 | when: groups['ipa_ipsilon_idp'] 91 | notify: 92 | - restart httpd 93 | 94 | - name: Overwrite ipsilon-saml.conf with custom config 95 | tags: 96 | - ipa-sp-example 97 | - ipa-install 98 | template: 99 | src=sp_example.conf 100 | dest=/etc/httpd/conf.d/ipsilon-saml.conf 101 | backup=true 102 | when: groups['ipa_ipsilon_idp'] 103 | notify: 104 | - restart httpd 105 | -------------------------------------------------------------------------------- /ansible/roles/ipa-sp-example/templates/admin_password: -------------------------------------------------------------------------------- 1 | {{ ipa_admin_password }} -------------------------------------------------------------------------------- /ansible/roles/ipa-sp-example/templates/sp_example.conf: -------------------------------------------------------------------------------- 1 | # Configure mod_wsgi handler for /sp_example 2 | WSGIDaemonProcess sp_example display-name=%{GROUP} 3 | WSGIImportScript /srv/www/sp_example/wsgi.py process-group=sp_example application-group=sp_example 4 | WSGIScriptAlias /sp_example /srv/www/sp_example/wsgi.py 5 | WSGIScriptReloading Off 6 | 7 | # This is a server-wide configuration that will add information from the Mellon 8 | # session to all requests under this path. 9 | 10 | # MellonEnable "info" 11 | MellonEnable "off" 12 | MellonSPPrivateKeyFile "/etc/httpd/saml2/{{ ansible_fqdn }}/certificate.key" 13 | MellonSPCertFile "/etc/httpd/saml2/{{ ansible_fqdn }}/certificate.pem" 14 | MellonSPMetadataFile "/etc/httpd/saml2/{{ ansible_fqdn }}/metadata.xml" 15 | MellonIdPMetadataFile "/etc/httpd/saml2/{{ ansible_fqdn }}/idp-metadata.xml" 16 | MellonEndpointPath /saml2 17 | MellonVariable "saml-sesion-cookie" 18 | # Comment out the next two lines if you want to allow logins on bare HTTP 19 | MellonsecureCookie On 20 | NSSRequireSSL 21 | MellonUser "NAME_ID" 22 | MellonIdP "IDP" 23 | MellonSessionLength 3600 24 | MellonNoCookieErrorPage "https://{{ idp_fqdn }}/no-cookie-error.html" 25 | # MellonPostDirectory "/var/lib/ipsilon/post_cache" 26 | # MellonPostReplay On 27 | 28 | # additional configuration 29 | MellonMergeEnvVars On ":" 30 | 31 | 32 | 33 | MellonEnable "auth" 34 | WSGIProcessGroup sp_example 35 | WSGIApplicationGroup sp_example 36 | Require valid-user 37 | Header append Cache-Control "no-cache" 38 | 39 | 40 | # List explicitly only the fonts we want to serve 41 | Alias /sp_example/fonts/open-sans "/usr/share/fonts/open-sans" 42 | Alias /sp_example/fonts/fontawesome "/usr/share/fonts/fontawesome" 43 | 44 | SetHandler None 45 | AllowOverride None 46 | Satisfy Any 47 | Allow from all 48 | ExpiresActive On 49 | ExpiresDefault "access plus 1 year" 50 | 51 | 52 | # Use FreeIPA webui CSS 53 | Alias /sp_example/css "/usr/share/ipa/ui/css" 54 | 55 | SetHandler None 56 | AllowOverride None 57 | Satisfy Any 58 | Allow from all 59 | ExpiresActive On 60 | ExpiresDefault "access plus 1 year" 61 | 62 | 63 | # Alias /saml2protected /usr/share/ipsilon/ui/saml2sp 64 | # 65 | # 66 | # SSLRequireSSL 67 | # Require all granted 68 | # 69 | 70 | # Redirect requests to the secure port 71 | RewriteEngine on 72 | RewriteCond %{SERVER_PORT} !^443$ 73 | RewriteRule ^/(.*) https://{{ ansible_fqdn }}/$1 [L,R=301,NC] 74 | -------------------------------------------------------------------------------- /ansible/roles/ipa-sp-example/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | app_mellon: true 3 | -------------------------------------------------------------------------------- /ansible/roles/ipa-tests/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create dot_ipa directories 3 | tags: 4 | - ipa-tests 5 | file: 6 | path={{ item }} 7 | mode=0755 8 | state=directory 9 | owner=root 10 | group=root 11 | with_items: 12 | - "{{ dot_ipa }}" 13 | - "{{ dot_ipa_nssdb }}" 14 | 15 | - name: Create default.conf 16 | tags: 17 | - ipa-tests 18 | template: 19 | src=default.conf 20 | dest={{ dot_ipa }}/default.conf 21 | 22 | - name: Create .dmpw 23 | tags: 24 | - ipa-tests 25 | template: 26 | src=dot_dmpw 27 | dest={{ dot_ipa }}/.dmpw 28 | 29 | - name: copy alias /etc/httpd/alias databases 30 | tags: 31 | - ipa-tests 32 | copy: 33 | src=/etc/httpd/alias/{{ item }} 34 | dest={{ dot_ipa_nssdb }}/ 35 | remote_src=True 36 | with_items: 37 | - cert8.db 38 | - key3.db 39 | - secmod.db 40 | 41 | - name: copy /etc/httpd/alias/pwdfile.txt 42 | tags: 43 | - ipa-tests 44 | copy: 45 | src=/etc/httpd/alias/pwdfile.txt 46 | dest={{ dot_ipa_nssdb }}/.pwd 47 | remote_src=True 48 | 49 | - name: copy /etc/ipa/ca.crt 50 | tags: 51 | - ipa-tests 52 | copy: 53 | src=/etc/ipa/ca.crt 54 | dest={{ dot_ipa }} 55 | remote_src=True 56 | 57 | - name: create krb5.conf 58 | tags: 59 | - ipa-tests 60 | template: 61 | src=krb5.conf 62 | dest={{ dot_ipa }}/krb5.conf 63 | 64 | - name: Fetch dot_ipa 65 | tags: 66 | - ipa-tests 67 | synchronize: 68 | src={{ dot_ipa }}/ 69 | dest={{ ipa_data_dir }}/dotipa/ 70 | mode=pull 71 | delete=true 72 | -------------------------------------------------------------------------------- /ansible/roles/ipa-tests/templates/default.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | domain = {{ ipa.domain }} 3 | realm = {{ ipa.realm }} 4 | basedn = {{ ipa.basedn }} 5 | # XXX hack 6 | host = {{ ipa.api_env.host }} 7 | server = {{ ipa.api_env.host }} 8 | 9 | xmlrpc_uri = {{ ipa.api_env.xmlrpc_uri }} 10 | jsonrpc_uri = {{ ipa.api_env.jsonrpc_uri }} 11 | ldap_uri = ldap://{{ ipa.api_env.host }}:389 12 | 13 | enable_ra = True 14 | ra_plugin = dogtag 15 | dogtag_version = 10 16 | 17 | in_tree = True 18 | wait_for_attr = True 19 | wait_for_dns = 5 20 | -------------------------------------------------------------------------------- /ansible/roles/ipa-tests/templates/dot_dmpw: -------------------------------------------------------------------------------- 1 | {{ ipa_dm_password }} -------------------------------------------------------------------------------- /ansible/roles/ipa-tests/templates/krb5.conf: -------------------------------------------------------------------------------- 1 | [libdefaults] 2 | default_realm = {{ ipa.realm }} 3 | dns_lookup_realm = false 4 | dns_lookup_kdc = false 5 | rdns = false 6 | ticket_lifetime = 24h 7 | forwardable = yes 8 | udp_preference_limit = 0 9 | default_ccache_name = KEYRING:user:ipatests 10 | 11 | [realms] 12 | {{ ipa.realm }} = { 13 | # kdc = https://{{ ansible_fqdn }}/KdcProxy 14 | # kpasswd_server = https://{{ ansible_fqdn }}/KdcProxy 15 | # master_kdc = https://{{ ansible_fqdn }}/KdcProxy 16 | # admin_server = https://{{ ansible_fqdn }}/KdcProxy 17 | kdc = {{ ansible_fqdn }}:88 18 | kpasswd_server = {{ ansible_fqdn }}:464 19 | master_kdc = {{ ansible_fqdn }}:88 20 | admin_server = {{ ansible_fqdn }}:749 21 | 22 | default_domain = {{ ipa.domain }} 23 | pkinit_anchors = FILE:{{ local_home }}/.ipa/ca.crt 24 | http_anchors = FILE:{{ local_home }}/.ipa/ca.crt 25 | } 26 | 27 | [domain_realm] 28 | .{{ ipa.domain }} = {{ ipa.realm }} 29 | {{ ipa.domain }} = {{ ipa.realm }} 30 | -------------------------------------------------------------------------------- /ansible/roles/ipa-tests/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dot_ipa: /tmp/dotipa 3 | dot_ipa_nssdb: "{{ dot_ipa }}/nssdb" 4 | local_home: "{{ lookup('env','HOME') }}" 5 | local_dot_ipa: "{{ local_home }}/.ipa" 6 | -------------------------------------------------------------------------------- /ansible/roles/ipa-tidy/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Run kdestroy 3 | tags: 4 | - ipa-tidy 5 | - ipa-install 6 | command: kdestroy -A 7 | changed_when: false 8 | -------------------------------------------------------------------------------- /ansible/roles/ipa-vpnserver/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart ocserv 3 | service: name=ocserv state=restarted 4 | 5 | - name: permanent masquerade 6 | command: firewall-cmd --permanent --add-masquerade 7 | -------------------------------------------------------------------------------- /ansible/roles/ipa-vpnserver/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install ocserv VPN server 3 | tags: 4 | - ipa-vpnserver 5 | - package-install 6 | - network 7 | package: name=ocserv state=present 8 | when: package_install 9 | 10 | - name: Open Firewall services for ocserv VPN server 11 | tags: 12 | - ipa-vpnserver 13 | - firewall 14 | firewalld: 15 | service={{ item }} 16 | permanent=true 17 | state=enabled 18 | immediate=yes 19 | with_items: 20 | - https 21 | when: has_firewalld.stat.exists 22 | 23 | - name: Open Firewall DTLS UDP port for ocserv VPN server 24 | tags: 25 | - ipa-vpnserver 26 | - firewall 27 | firewalld: 28 | port={{ item }} 29 | permanent=true 30 | state=enabled 31 | immediate=yes 32 | with_items: 33 | - 443/udp 34 | when: has_firewalld.stat.exists 35 | 36 | # http://www.infradead.org/ocserv/recipes-ocserv-pseudo-bridge.html 37 | - name: Enable IPv4 proxy_arp 38 | tags: 39 | - ipa-vpnserver 40 | - ipa-install 41 | sysctl: name="net.ipv4.conf.all.proxy_arp" value=1 state=present reload=true 42 | 43 | - name: Enable masquerading 44 | tags: 45 | - ipa-vpnserver 46 | - ipa-install 47 | command: firewall-cmd --add-masquerade 48 | register: result 49 | changed_when: "{{ 'ALREADY_ENABLED' not in result.stdout }}" 50 | when: has_firewalld.stat.exists 51 | notify: 52 | - permanent masquerade 53 | 54 | - name: Get keytab /etc/ocserv/key.tab content 55 | tags: 56 | - ipa-vpnserver 57 | - ipa-install 58 | command: klist -ke /etc/ocserv/key.tab 59 | register: keytab 60 | changed_when: false 61 | failed_when: "keytab.rc != 0 and 'not found' not in keytab.stderr" 62 | 63 | - name: Check for principal in keytab 64 | tags: 65 | - ipa-vpnserver 66 | - ipa-install 67 | changed_when: false 68 | set_fact: 69 | keytab_ocserv_http_principal: "{{ 'HTTP/{{ ansible_fqdn }}' in keytab.stdout }}" 70 | 71 | - name: Create VPN service 72 | tags: 73 | - ipa-vpnserver 74 | - ipa-install 75 | ipa: 76 | args="service-add --force HTTP/{{ ansible_fqdn }}" 77 | password="{{ ipa_admin_password }}" 78 | ignore_already_exists=true 79 | when: not keytab_ocserv_http_principal 80 | 81 | - name: Add VPN service to keytab /etc/ocserv/key.tab 82 | tags: 83 | - ipa-vpnserver 84 | - ipa-install 85 | ipa: > 86 | cmd=ipa-getkeytab 87 | args="-s $IPA_SERVER -p HTTP/{{ ansible_fqdn }} -k /etc/ocserv/key.tab" 88 | password="{{ ipa_admin_password }}" 89 | when: not keytab_ocserv_http_principal 90 | 91 | - name: Look for /etc/pki/ocserv/public/server.crt 92 | tags: 93 | - ipa-vpnserver 94 | - ipa-install 95 | stat: path=/etc/pki/ocserv/public/server.crt 96 | register: vpn_server_cert 97 | 98 | - name: Request certificate /etc/pki/ocserv/public/server.crt with ipa-getcert 99 | tags: 100 | - ipa-vpnserver 101 | - ipa-install 102 | ipa: 103 | cmd=ipa-getcert 104 | args="request -w -k /etc/pki/ocserv/private/server.key -f /etc/pki/ocserv/public/server.crt -T caIPAserviceCert -C 'systemctl reload-or-restart ocserv.service'" 105 | password="{{ ipa_admin_password }}" 106 | when: not vpn_server_cert.stat.exists 107 | notify: 108 | - restart ocserv 109 | 110 | - name: Wait for certmonger 111 | tags: 112 | - ipa-vpnserver 113 | - ipa-install 114 | waitforcertmonger: 115 | 116 | - name: Create a link from /etc/pki/ocserv/cacerts/ca.crt to /etc/ipa/ca.crt 117 | tags: 118 | - ipa-vpnserver 119 | - ipa-install 120 | file: 121 | src=/etc/ipa/ca.crt 122 | dest=/etc/pki/ocserv/cacerts/ca.crt 123 | state=link 124 | notify: 125 | - restart ocserv 126 | 127 | - name: Write ocserv.conf 128 | tags: 129 | - ipa-vpnserver 130 | - ipa-install 131 | template: 132 | src=ocserv.conf 133 | dest=/etc/ocserv/ocserv.conf 134 | force=yes 135 | backup=true 136 | notify: 137 | - restart ocserv 138 | 139 | # XXX incomplete, routing is missing 140 | 141 | - name: Enable ocserv 142 | tags: 143 | - ipa-vpnserver 144 | - ipa-install 145 | service: name=ocserv enabled=yes state=started 146 | 147 | - name: Template local scripts 148 | tags: 149 | - ipa-vpnserver 150 | - ipa-install 151 | become: no 152 | local_action: 153 | template 154 | src=../../ipa-inventory/templates/{{ item }} 155 | dest={{ ipa_script_dir }}/{{ item }} 156 | mode=0755 157 | with_items: 158 | - ipa_kkdcp_openconnect_kinit 159 | - ipa_kkdcp_openconnect_vpn 160 | run_once: true 161 | 162 | - name: Template local inventory files 163 | tags: 164 | - ipa-vpnserver 165 | - ipa-install 166 | become: no 167 | local_action: 168 | template 169 | src=../../ipa-inventory/templates/{{ item }} 170 | dest={{ ipa_data_dir }}/{{ item }} 171 | mode=0644 172 | with_items: 173 | - ipaenv_kkdcp_openconnect 174 | run_once: true 175 | 176 | - name: Write custom krb5.conf 177 | tags: 178 | - ipa-vpnserver 179 | - ipa-install 180 | - fetch 181 | become: no 182 | local_action: 183 | template 184 | src=../../ipa-inventory/templates/krb5.conf 185 | dest={{ ipa_data_dir }}/krb5_kkdcp_openconnect.conf 186 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/pam_websvc: -------------------------------------------------------------------------------- 1 | auth required pam_sss.so 2 | account required pam_sss.so 3 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {title} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 15 |
16 | 19 | 20 | {strongmsg} {msg} 21 |
22 | 25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Bold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Bold-webfont.eot -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Bold-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Bold-webfont.ttf -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Bold-webfont.woff -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Bold-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Bold-webfont.woff2 -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-BoldItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-BoldItalic-webfont.eot -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-BoldItalic-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-BoldItalic-webfont.ttf -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-BoldItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-BoldItalic-webfont.woff -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-BoldItalic-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-BoldItalic-webfont.woff2 -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBold-webfont.eot -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBold-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBold-webfont.ttf -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBold-webfont.woff -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBold-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBold-webfont.woff2 -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBoldItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBoldItalic-webfont.eot -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBoldItalic-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBoldItalic-webfont.ttf -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBoldItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBoldItalic-webfont.woff -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBoldItalic-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-ExtraBoldItalic-webfont.woff2 -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Italic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Italic-webfont.eot -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Italic-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Italic-webfont.ttf -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Italic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Italic-webfont.woff -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Italic-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Italic-webfont.woff2 -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Light-webfont.eot -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Light-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Light-webfont.ttf -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Light-webfont.woff -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Light-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Light-webfont.woff2 -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-LightItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-LightItalic-webfont.eot -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-LightItalic-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-LightItalic-webfont.ttf -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-LightItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-LightItalic-webfont.woff -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-LightItalic-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-LightItalic-webfont.woff2 -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Regular-webfont.eot -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Regular-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Regular-webfont.ttf -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Regular-webfont.woff -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Regular-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/OpenSans-Regular-webfont.woff2 -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/PatternFlyIcons-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/PatternFlyIcons-webfont.eot -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/PatternFlyIcons-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/PatternFlyIcons-webfont.ttf -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/PatternFlyIcons-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/PatternFlyIcons-webfont.woff -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/OpenShift-Logo-NoText.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 25 | 26 | 27 | 29 | 30 | 31 | 33 | 34 | 35 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/RH_Atomic-Logo-NoText.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | 12 | 13 | 15 | 17 | 32 | 35 | 36 | 37 | 39 | 41 | 43 | 45 | 46 | 47 | 48 | 49 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/apple-touch-icon-precomposed-114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/apple-touch-icon-precomposed-114.png -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/apple-touch-icon-precomposed-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/apple-touch-icon-precomposed-144.png -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/apple-touch-icon-precomposed-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/apple-touch-icon-precomposed-152.png -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/apple-touch-icon-precomposed-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/apple-touch-icon-precomposed-180.png -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/apple-touch-icon-precomposed-57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/apple-touch-icon-precomposed-57.png -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/apple-touch-icon-precomposed-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/apple-touch-icon-precomposed-72.png -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/apple-touch-icon-precomposed-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/apple-touch-icon-precomposed-76.png -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/bg-login.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/bg-login.jpg -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/bg-modal-about-pf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/bg-modal-about-pf.png -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/bg-navbar-pf-alt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/favicon.ico -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/logo-alt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 18 | 19 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/spinner-inverse-lg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/spinner-inverse-lg.gif -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/spinner-inverse-sm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/spinner-inverse-sm.gif -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/spinner-inverse-xs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/spinner-inverse-xs.gif -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/spinner-inverse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/spinner-inverse.gif -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/spinner-lg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/spinner-lg.gif -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/spinner-sm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/spinner-sm.gif -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/spinner-xs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/spinner-xs.gif -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/img/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/ipa-wwwdemo/files/ui/img/spinner.gif -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/js/patternfly-functions-base.js: -------------------------------------------------------------------------------- 1 | // Util: definition of breakpoint sizes for tablet and desktop modes 2 | (function ($) { 3 | 'use strict'; 4 | if (patternfly !== undefined) { 5 | $.pfBreakpoints = patternfly.pfBreakpoints; 6 | } 7 | }(jQuery)); -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/js/patternfly-functions-charts.js: -------------------------------------------------------------------------------- 1 | // Util: PatternFly C3 Chart Defaults 2 | (function ($) { 3 | 'use strict'; 4 | if (patternfly !== undefined) { 5 | $.fn.pfSetDonutChartTitle = patternfly.pfSetDonutChartTitle; 6 | $.fn.pfDonutTooltipContents = patternfly.pfDonutTooltipContents; 7 | $.fn.pfGetUtilizationDonutTooltipContentsFn = patternfly.pfGetUtilizationDonutTooltipContentsFn; 8 | $.fn.pfGetBarChartTooltipContentsFn = patternfly.pfGetBarChartTooltipContentsFn; 9 | $.fn.pfSingleLineChartTooltipContentsFn = patternfly.pfSingleLineChartTooltipContentsFn; 10 | $.fn.pfPieTooltipContents = patternfly.pfPieTooltipContents; 11 | $.fn.c3ChartDefaults = patternfly.c3ChartDefaults; 12 | } 13 | }(jQuery)); 14 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/js/patternfly-functions-colors.js: -------------------------------------------------------------------------------- 1 | // Util: PatternFly Palette colors 2 | (function ($) { 3 | 'use strict'; 4 | 5 | if (patternfly !== undefined) { 6 | $.pfPaletteColors = patternfly.pfPaletteColors; 7 | } 8 | }(jQuery)); 9 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/js/patternfly-functions-count-chars.js: -------------------------------------------------------------------------------- 1 | // Count and Display Remaining Characters 2 | (function ($) { 3 | 4 | 'use strict'; 5 | 6 | $.fn.countRemainingChars = function (options) { 7 | 8 | var settings = $.extend({ 9 | // These are the defaults. 10 | charsMaxLimit: 100, 11 | charsWarnRemaining: 5, 12 | blockInputAtMaxLimit: false 13 | }, options), 14 | $taFld = this, 15 | $countFld = $('#' + settings.countFld).text(settings.charsMaxLimit), 16 | charsRemainingFn = function (charsLength) { 17 | var charsRemaining = settings.charsMaxLimit - charsLength; 18 | $countFld.text(charsRemaining); 19 | $countFld.toggleClass('chars-warn-remaining-pf', charsRemaining <= settings.charsWarnRemaining); 20 | if (charsRemaining < 0) { 21 | $taFld.trigger("overCharsMaxLimitEvent", $taFld.attr('id')); 22 | } else { 23 | $taFld.trigger("underCharsMaxLimitEvent", $taFld.attr('id')); 24 | } 25 | }; 26 | 27 | this.on('paste', function (event) { 28 | setTimeout(function () { 29 | var charsLength = $taFld.val().length, maxTxt; 30 | 31 | if (settings.blockInputAtMaxLimit && charsLength > settings.charsMaxLimit) { 32 | maxTxt = $taFld.val(); 33 | maxTxt = maxTxt.substring(0, settings.charsMaxLimit); 34 | $taFld.val(maxTxt); 35 | charsLength = $taFld.val().length; 36 | } 37 | 38 | charsRemainingFn(charsLength); 39 | }, 100); 40 | }); 41 | 42 | this.keyup(function (event) { 43 | charsRemainingFn($taFld.val().length); 44 | }); 45 | 46 | this.keydown(function (event) { 47 | var charsLength = $taFld.val().length; 48 | 49 | if (settings.blockInputAtMaxLimit && charsLength >= settings.charsMaxLimit) { 50 | // Except backspace 51 | if (event.keyCode !== 8) { 52 | event.preventDefault(); 53 | } 54 | } 55 | }); 56 | 57 | return this; 58 | }; 59 | }(jQuery)); 60 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/js/patternfly-functions-fixed-heights.js: -------------------------------------------------------------------------------- 1 | // Util: PatternFly Collapse with fixed heights 2 | // Update the max-height of collapse elements based on the parent container's height. 3 | (function ($) { 4 | 'use strict'; 5 | 6 | $.fn.initCollapseHeights = function (scrollSelector) { 7 | var parentElement = this, setCollapseHeights, targetScrollSelector = scrollSelector; 8 | 9 | setCollapseHeights = function () { 10 | var height, openPanel, contentHeight, bodyHeight, overflowY = 'hidden'; 11 | 12 | height = parentElement.height(); 13 | 14 | // Close any open panel 15 | openPanel = parentElement.find('.collapse.in'); 16 | if (openPanel && openPanel.length > 0) { 17 | openPanel.removeClass('in'); 18 | } 19 | 20 | // Determine the necessary height for the closed content 21 | contentHeight = 0; 22 | parentElement.children().each($.proxy(function (i, element) { 23 | var $element = $(element); 24 | contentHeight += $element.outerHeight(true); 25 | }, parentElement)).end(); 26 | 27 | // Determine the height remaining for opened collapse panels 28 | bodyHeight = height - contentHeight; 29 | 30 | // Make sure we have enough height to be able to scroll the contents if necessary 31 | if (bodyHeight < 25) { 32 | bodyHeight = 25; 33 | 34 | // Allow the parent to scroll so the child elements are accessible 35 | overflowY = 'auto'; 36 | } 37 | 38 | // Reopen the initially opened panel 39 | if (openPanel && openPanel.length > 0) { 40 | openPanel.addClass("in"); 41 | } 42 | 43 | setTimeout(function () { 44 | // Set the max-height for the collapse panels 45 | parentElement.find('[data-toggle="collapse"]').each($.proxy(function (i, element) { 46 | var $element, selector, $target, scrollElement, innerHeight = 0; 47 | $element = $(element); 48 | 49 | // Determine the selector to find the target 50 | selector = $element.attr('data-target'); 51 | if (!selector) { 52 | selector = $element.attr('href'); 53 | } 54 | 55 | // Determine the scroll element (either the target or the child of the target based on the given selector) 56 | $target = $(selector); 57 | scrollElement = $target; 58 | if (targetScrollSelector) { 59 | scrollElement = $target.find(targetScrollSelector); 60 | if (scrollElement.length === 1) { 61 | innerHeight = 0; 62 | $target.children().each($.proxy(function (j, sibling) { 63 | var $sibling = $(sibling); 64 | if (sibling !== scrollElement[0]) { 65 | innerHeight += $sibling.outerHeight(true); 66 | } 67 | }, $target)).end(); 68 | bodyHeight -= innerHeight; 69 | } else { 70 | scrollElement = $target; 71 | } 72 | } 73 | // Set the max-height and vertical scroll of the scroll element 74 | scrollElement.css({'max-height': (bodyHeight - innerHeight) + 'px', 'overflow-y': 'auto'}); 75 | }, parentElement)).end(); 76 | 77 | parentElement.css({'overflow-y': overflowY}); 78 | }, 100); 79 | }; 80 | 81 | setCollapseHeights(); 82 | 83 | // Update on window resizing 84 | $(window).resize(setCollapseHeights); 85 | 86 | }; 87 | }(jQuery)); 88 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/js/patternfly-functions-list.js: -------------------------------------------------------------------------------- 1 | // PatternFly pf-list 2 | (function ($) { 3 | 'use strict'; 4 | 5 | $.fn.pfList = function () { 6 | function init (list) { 7 | // Ensure the state of the expansion elements is consistent 8 | list.find('[data-list=expansion], .list-pf-item, .list-pf-expansion').each(function (index, element) { 9 | var $expansion = $(element), 10 | $collapse = $expansion.find('.collapse').first(), 11 | expanded = $collapse.hasClass('in'); 12 | updateChevron($expansion, expanded); 13 | if ($expansion.hasClass('list-pf-item')) { 14 | updateActive($expansion, expanded); 15 | } 16 | }); 17 | list.find('.list-pf-container').each(function (index, element) { 18 | var $element = $(element); 19 | // The toggle element is the element with the data-list=toggle attribute 20 | // or the entire .list-pf-container as a fallback 21 | var $toggles = $element.find('[data-list=toggle]'); 22 | $toggles.length || ($toggles = $element); 23 | $toggles.on('keydown', function (event) { 24 | if (event.keyCode === 13 || event.keyCode === 32) { 25 | toggleCollapse(this); 26 | event.stopPropagation(); 27 | event.preventDefault(); 28 | } 29 | }); 30 | $toggles.on('click', function (event) { 31 | toggleCollapse(this); 32 | event.stopPropagation(); 33 | event.preventDefault(); 34 | }); 35 | }); 36 | } 37 | 38 | function toggleCollapse (toggle) { 39 | var $toggle, $expansion, $collapse, expanded, $listItem; 40 | $toggle = $(toggle); 41 | // Find the parent expansion of the toggle 42 | $expansion = $toggle.parentsUntil('.list-pf', '[data-list=expansion]').first(); 43 | $expansion.length || ($expansion = $toggle.closest('.list-pf-item, .list-pf-expansion')); 44 | 45 | // toggle the "in" class of its first .collapse child 46 | $collapse = $expansion.find('.collapse').first(); 47 | $collapse.toggleClass('in'); 48 | 49 | // update the state of the expansion element 50 | updateChevron($expansion, $collapse.hasClass('in')); 51 | $listItem = $expansion.closest('.list-pf-item'); 52 | updateActive($listItem, $listItem.find('.collapse').first().hasClass('in')); 53 | } 54 | 55 | function updateActive ($listItem, expanded) { 56 | // Find the closest .list-pf-item of the expansion, and set its "active" class 57 | if (expanded) { 58 | $listItem.addClass('active'); 59 | } else { 60 | $listItem.removeClass('active'); 61 | } 62 | } 63 | 64 | function updateChevron ($expansion, expanded) { 65 | var $chevron = $expansion.find('.list-pf-chevron .fa').first(); 66 | if (expanded) { 67 | $chevron.removeClass('fa-angle-right'); 68 | $chevron.addClass('fa-angle-down'); 69 | } else { 70 | $chevron.addClass('fa-angle-right'); 71 | $chevron.removeClass('fa-angle-down'); 72 | } 73 | } 74 | 75 | init(this); 76 | 77 | return this; 78 | }; 79 | }(jQuery)); 80 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/js/patternfly-functions-navigation.js: -------------------------------------------------------------------------------- 1 | // Util: PatternFly Collapsible Left Hand Navigation 2 | // Must have navbar-toggle in navbar-pf-alt for expand/collapse 3 | (function ($) { 4 | 5 | 'use strict'; 6 | 7 | $.fn.navigation = function () { 8 | 9 | var navElement = $('.layout-pf-alt-fixed .nav-pf-vertical-alt'), 10 | bodyContentElement = $('.container-pf-alt-nav-pf-vertical-alt'), 11 | toggleNavBarButton = $('.navbar-toggle'), 12 | explicitCollapse = false, 13 | checkNavState = function () { 14 | var width = $(window).width(); 15 | 16 | //Always remove the hidden & peek class 17 | navElement.removeClass('hidden show-mobile-nav collapsed'); 18 | 19 | //Set the body class back to the default 20 | bodyContentElement.removeClass('collapsed-nav hidden-nav'); 21 | 22 | // Check to see if the nav needs to collapse 23 | if (width < $.pfBreakpoints.desktop || explicitCollapse) { 24 | navElement.addClass('collapsed'); 25 | bodyContentElement.addClass('collapsed-nav'); 26 | } 27 | 28 | // Check to see if we need to move down to the mobile state 29 | if (width < $.pfBreakpoints.tablet) { 30 | //Set the nav to being hidden 31 | navElement.addClass('hidden'); 32 | 33 | //Make sure this is expanded 34 | navElement.removeClass('collapsed'); 35 | 36 | //Set the body class to the correct state 37 | bodyContentElement.removeClass('collapsed-nav'); 38 | bodyContentElement.addClass('hidden-nav'); 39 | } 40 | }, 41 | collapseMenu = function () { 42 | //Make sure this is expanded 43 | navElement.addClass('collapsed'); 44 | //Set the body class to the correct state 45 | bodyContentElement.addClass('collapsed-nav'); 46 | 47 | explicitCollapse = true; 48 | }, 49 | enableTransitions = function () { 50 | // enable transitions only when toggleNavBarButton is clicked or window is resized 51 | $('html').addClass('transitions'); 52 | }, 53 | expandMenu = function () { 54 | //Make sure this is expanded 55 | navElement.removeClass('collapsed'); 56 | //Set the body class to the correct state 57 | bodyContentElement.removeClass('collapsed-nav'); 58 | 59 | explicitCollapse = false; 60 | }, 61 | bindMenuBehavior = function () { 62 | toggleNavBarButton.on('click', function (e) { 63 | var inMobileState = bodyContentElement.hasClass('hidden-nav'); 64 | enableTransitions(); 65 | 66 | if (inMobileState && navElement.hasClass('show-mobile-nav')) { 67 | //In mobile state just need to hide the nav 68 | navElement.removeClass('show-mobile-nav'); 69 | } else if (inMobileState) { 70 | navElement.addClass('show-mobile-nav'); 71 | } else if (navElement.hasClass('collapsed')) { 72 | expandMenu(); 73 | } else { 74 | collapseMenu(); 75 | } 76 | }); 77 | }, 78 | setTooltips = function () { 79 | $('.nav-pf-vertical-alt [data-toggle="tooltip"]').tooltip({'container': 'body', 'delay': { 'show': '500', 'hide': '200' }}); 80 | 81 | $(".nav-pf-vertical-alt").on("show.bs.tooltip", function (e) { 82 | return $(this).hasClass("collapsed"); 83 | }); 84 | 85 | }, 86 | init = function () { 87 | //Set correct state on load 88 | checkNavState(); 89 | 90 | // Bind Top level hamburger menu with menu behavior; 91 | bindMenuBehavior(); 92 | 93 | //Set tooltips 94 | setTooltips(); 95 | }; 96 | 97 | //Listen for the window resize event and collapse/hide as needed 98 | $(window).on('resize', function () { 99 | checkNavState(); 100 | enableTransitions(); 101 | }); 102 | 103 | init(); 104 | 105 | }; 106 | 107 | $(document).ready(function () { 108 | if ($('.nav-pf-vertical-alt').length > 0) { 109 | $.fn.navigation(); 110 | } 111 | }); 112 | 113 | }(jQuery)); 114 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/js/patternfly-functions-popovers.js: -------------------------------------------------------------------------------- 1 | // Util: PatternFly Popovers 2 | // Add data-close="true" to insert close X icon 3 | (function ($) { 4 | 'use strict'; 5 | 6 | $.fn.popovers = function () { 7 | // Initialize 8 | this.popover(); 9 | 10 | // Add close icons 11 | this.filter('[data-close=true]').each(function (index, element) { 12 | var $this = $(element), 13 | title = $this.attr('data-original-title') + ''; 14 | 15 | $this.attr('data-original-title', title); 16 | }); 17 | 18 | // Bind Close Icon to Toggle Display 19 | this.on('click', function (e) { 20 | var $this = $(this), 21 | $title = $this.next('.popover').find('.popover-title'); 22 | 23 | // Only if data-close is true add class "x" to title for right padding 24 | $title.find('.close').parent('.popover-title').addClass('closable'); 25 | 26 | // Bind x icon to close popover 27 | $title.find('.close').on('click', function () { 28 | $this.popover('hide'); 29 | }); 30 | 31 | // Prevent href="#" page scroll to top 32 | e.preventDefault(); 33 | }); 34 | 35 | return this; 36 | }; 37 | }(jQuery)); 38 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/js/patternfly-functions-sidebar.js: -------------------------------------------------------------------------------- 1 | // Util: PatternFly Sidebar 2 | // Set height of sidebar-pf to height of document minus height of navbar-pf if not mobile 3 | (function ($) { 4 | 'use strict'; 5 | $.fn.sidebar = function () { 6 | var documentHeight = 0, 7 | navbarpfHeight = 0, 8 | colHeight = 0; 9 | 10 | if ($('.navbar-pf .navbar-toggle').is(':hidden')) { 11 | documentHeight = $(document).height(); 12 | navbarpfHeight = $('.navbar-pf').outerHeight(); 13 | colHeight = documentHeight - navbarpfHeight; 14 | } 15 | $('.sidebar-pf').parent('.row').children('[class*="col-"]').css({"min-height" : colHeight}); 16 | }; 17 | 18 | $(document).ready(function () { 19 | // Call sidebar() on ready if .sidebar-pf exists and .datatable does not exist 20 | if ($('.sidebar-pf').length > 0 && $('.datatable').length === 0) { 21 | $.fn.sidebar(); 22 | } 23 | }); 24 | 25 | $(window).resize(function () { 26 | // Call sidebar() on resize if .sidebar-pf exists 27 | if ($('.sidebar-pf').length > 0) { 28 | $.fn.sidebar(); 29 | } 30 | }); 31 | }(jQuery)); 32 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/js/patternfly-functions-tree-grid.js: -------------------------------------------------------------------------------- 1 | // Util: PatternFly TreeGrid Tables 2 | (function ($) { 3 | 'use strict'; 4 | 5 | function getParent (rows, node) { 6 | var parent = node.attr('data-parent'); 7 | 8 | if (typeof parent === "string") { 9 | if (isNaN(parent)) { 10 | parent = rows.closest(parent); 11 | } else { 12 | parent = $(rows[parseInt(parent, 10)]); 13 | } 14 | return parent; 15 | } 16 | return undefined; 17 | } 18 | 19 | function renderItem (item, parent) { 20 | if (parent) { 21 | parent.find('.treegrid-node > span.expand-icon') 22 | .toggleClass('fa-angle-right', parent.hasClass('collapsed')) 23 | .toggleClass('fa-angle-down', !parent.hasClass('collapsed')); 24 | item.toggleClass('hidden', parent.hasClass('collapsed')); 25 | if (parent.hasClass('collapsed')) { 26 | item.addClass('collapsed'); 27 | } 28 | } 29 | } 30 | 31 | function reStripe (tree) { 32 | tree.find('tbody > tr').removeClass('odd'); 33 | tree.find('tbody > tr:not(.hidden):odd').addClass('odd'); 34 | } 35 | 36 | $.fn.treegrid = function (options) { 37 | var i, rows, _this; 38 | rows = this.find('tbody > tr'); 39 | _this = this; 40 | $.each(rows, function () { 41 | var node, parent; 42 | node = $(this); 43 | parent = getParent(rows, node); 44 | // Append expand icon dummies 45 | node.children('.treegrid-node').prepend(''); 46 | 47 | // Set up an event listener for the node 48 | node.children('.treegrid-node').on('click', function (e) { 49 | var icon = node.find('span.expand-icon'); 50 | 51 | if (options && typeof options.callback === 'function') { 52 | options.callback(e); 53 | } 54 | 55 | if (icon.hasClass('fa-angle-right')) { 56 | node.removeClass('collapsed'); 57 | } 58 | if (icon.hasClass('fa-angle-down')) { 59 | node.addClass('collapsed'); 60 | } 61 | $.each(rows.slice(rows.index(node) + 1), function () { 62 | renderItem($(this), getParent(rows, $(this))); 63 | }); 64 | reStripe(_this); 65 | }); 66 | 67 | if (parent) { 68 | // Calculate indentation depth 69 | i = parent.find('.treegrid-node > span.indent').length + 1; 70 | for (; i > 0; i -= 1) { 71 | node.children('.treegrid-node').prepend(''); 72 | } 73 | // Render expand/collapse icons 74 | renderItem(node, parent); 75 | } 76 | }); 77 | reStripe(_this); 78 | }; 79 | }(jQuery)); 80 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/js/patternfly-settings-base.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | 'use strict'; 3 | 4 | var patternfly = { 5 | version: "3.25.1", 6 | }; 7 | 8 | // definition of breakpoint sizes for tablet and desktop modes 9 | patternfly.pfBreakpoints = { 10 | 'tablet': 768, 11 | 'desktop': 1200 12 | }; 13 | 14 | window.patternfly = patternfly; 15 | 16 | })(window); 17 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/js/patternfly-settings-colors.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | 'use strict'; 3 | 4 | // Util: PatternFly Palette colors 5 | patternfly.pfPaletteColors = { 6 | black: '#030303', 7 | black100: '#fafafa', 8 | black200: '#ededed', 9 | black300: '#d1d1d1', 10 | black400: '#bbbbbb', 11 | black500: '#8b8d8f', 12 | black600: '#72767b', 13 | black700: '#4d5258', 14 | black800: '#393f44', 15 | black900: '#292e34', 16 | blue: '#0088ce', 17 | blue100: '#bee1f4', 18 | blue200: '#7dc3e8', 19 | blue300: '#39a5dc', 20 | blue400: '#0088ce', 21 | blue500: '#00659c', 22 | blue600: '#004368', 23 | blue700: '#002235', 24 | gold: '#f0ab00', 25 | gold100: '#fbeabc', 26 | gold200: '#f9d67a', 27 | gold300: '#f5c12e', 28 | gold400: '#f0ab00', 29 | gold500: '#b58100', 30 | gold600: '#795600', 31 | gold700: '#3d2c00', 32 | orange: '#ec7a08', 33 | orange100: '#fbdebf', 34 | orange200: '#f7bd7f', 35 | orange300: '#f39d3c', 36 | orange400: '#ec7a08', 37 | orange500: '#b35c00', 38 | orange600: '#773d00', 39 | orange700: '#3b1f00', 40 | lightBlue: '#00b9e4', 41 | lightBlue100: '#beedf9', 42 | lightBlue200: '#7cdbf3', 43 | lightBlue300: '#35caed', 44 | lightBlue400: '#00b9e4', 45 | lightBlue500: '#008bad', 46 | lightBlue600: '#005c73', 47 | lightBlue700: '#002d39', 48 | green: '#3f9c35', 49 | green100: '#cfe7cd', 50 | green200: '#9ecf99', 51 | green300: '#6ec664', 52 | green400: '#3f9c35', 53 | green500: '#2d7623', 54 | green600: '#1e4f18', 55 | green700: '#0f280d', 56 | lightGreen: '#92d400', 57 | lightGreen100: '#e4f5bc', 58 | lightGreen200: '#c8eb79', 59 | lightGreen300: '#ace12e', 60 | lightGreen400: '#92d400', 61 | lightGreen500: '#6ca100', 62 | lightGreen600: '#486b00', 63 | lightGreen700: '#253600', 64 | cyan: '#007a87', 65 | cyan100: '#bedee1', 66 | cyan200: '#7dbdc3', 67 | cyan300: '#3a9ca6', 68 | cyan400: '#007a87', 69 | cyan500: '#005c66', 70 | cyan600: '#003d44', 71 | cyan700: '#001f22', 72 | purple: '#703fec', 73 | purple100: '#c7bfff', 74 | purple200: '#a18fff', 75 | purple300: '#8461f7', 76 | purple400: '#703fec', 77 | purple500: '#582fc0', 78 | purple600: '#40199a', 79 | purple700: '#1f0066', 80 | red: '#cc0000', 81 | red100: '#cc0000', 82 | red200: '#a30000', 83 | red300: '#8b0000', 84 | red400: '#470000', 85 | red500: '#2c0000' 86 | }; 87 | })(window); 88 | 89 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/js/patternfly.dataTables.pfEmpty.min.js: -------------------------------------------------------------------------------- 1 | !function(factory){"use strict";"function"==typeof define&&define.amd?define(["jquery","datatables.net"],function($){return factory($,window,document)}):"object"==typeof exports?module.exports=function(root,$){return root||(root=window),$&&$.fn.dataTable||($=require("datatables.net")(root,$).$),factory($,root,root.document)}:factory(jQuery,window,document)}(function($,window,document,undefined){"use strict";function updateEmptyState(dt){var ctx=dt.settings()[0];ctx._pfEmpty.emptyState!==undefined&&0!==ctx._pfEmpty.emptyState.length&&ctx._pfEmpty.emptyState.removeClass("hidden"),ctx._pfEmpty.tbody!==undefined&&0!==ctx._pfEmpty.tbody.length&&ctx._pfEmpty.tbody.addClass("hidden"),ctx._pfEmpty.thead!==undefined&&0!==ctx._pfEmpty.thead.length&&ctx._pfEmpty.thead.addClass("hidden"),ctx._pfEmpty.toolbarActions!==undefined&&0!==ctx._pfEmpty.toolbarActions.length&&$("button",ctx._pfEmpty.toolbarActions).prop("disabled",!0),ctx._pfEmpty.toolbarActions!==undefined&&0!==ctx._pfEmpty.toolbarActions.length&&$("input",ctx._pfEmpty.toolbarActions).prop("disabled",!0),ctx._pfEmpty.toolbarResults!==undefined&&0!==ctx._pfEmpty.toolbarResults.length&&ctx._pfEmpty.toolbarResults.children().addClass("hidden"),ctx._pfEmpty.pagination!==undefined&&0!==ctx._pfEmpty.pagination.length&&ctx._pfEmpty.pagination.addClass("hidden"),ctx._pfEmpty.enableOnEmpty!==undefined&&$(ctx._pfEmpty.enableOnEmpty).prop("disabled",!1),ctx._pfEmpty.enableOnEmpty!==undefined&&$(ctx._pfEmpty.enableOnEmpty).prop("disabled",!1)}function updateNonEmptyState(dt){var ctx=dt.settings()[0];ctx._pfEmpty.emptyState!==undefined&&0!==ctx._pfEmpty.emptyState.length&&ctx._pfEmpty.emptyState.addClass("hidden"),ctx._pfEmpty.tbody!==undefined&&0!==ctx._pfEmpty.tbody.length&&ctx._pfEmpty.tbody.removeClass("hidden"),ctx._pfEmpty.thead!==undefined&&0!==ctx._pfEmpty.thead.length&&ctx._pfEmpty.thead.removeClass("hidden"),ctx._pfEmpty.toolbarActions!==undefined&&0!==ctx._pfEmpty.toolbarActions.length&&$("button",ctx._pfEmpty.toolbarActions).prop("disabled",!1),ctx._pfEmpty.toolbarActions!==undefined&&0!==ctx._pfEmpty.toolbarActions.length&&$("input",ctx._pfEmpty.toolbarActions).prop("disabled",!1),ctx._pfEmpty.toolbarResults!==undefined&&0!==ctx._pfEmpty.toolbarResults.length&&ctx._pfEmpty.toolbarResults.children().removeClass("hidden"),ctx._pfEmpty.pagination!==undefined&&0!==ctx._pfEmpty.pagination.length&&ctx._pfEmpty.pagination.removeClass("hidden")}function updateState(dt){var ctx=dt.settings()[0];0===dt.data().length?(ctx._pfEmpty.isEmptyState=!0,updateEmptyState(dt)):!0===ctx._pfEmpty.isEmptyState&&(ctx._pfEmpty.isEmptyState=!1,updateNonEmptyState(dt))}var DataTable=$.fn.dataTable;return DataTable.pfEmpty={},DataTable.pfEmpty.init=function(dt){var ctx=dt.settings()[0],opts=ctx.oInit.pfConfig?ctx.oInit.pfConfig:{};ctx._pfEmpty={},ctx._pfEmpty.emptyState=$(opts.emptyStateSelector),ctx._pfEmpty.isEmptyState=!1,ctx._pfEmpty.pagination=$(opts.paginationSelector),ctx._pfEmpty.tbody=$("tbody",dt.table().container()),ctx._pfEmpty.thead=$("thead",dt.table().container()),ctx._pfEmpty.toolbarActions=$(".toolbar-pf-actions",opts.toolbarSelector),ctx._pfEmpty.toolbarResults=$(".toolbar-pf-results",opts.toolbarSelector),dt.on("draw.dt",function(){updateState(dt)}),updateState(dt)},DataTable.Api.register("pfEmpty.updateState()",function(){return this.iterator("table",function(ctx){updateState(new DataTable.Api(ctx))})}),$(document).on("init.dt",function(e,ctx,json){"dt"===e.namespace&&DataTable.pfEmpty.init(new DataTable.Api(ctx))}),DataTable.pfEmpty}); 2 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/js/patternfly.dataTables.pfFilter.min.js: -------------------------------------------------------------------------------- 1 | !function(factory){"use strict";"function"==typeof define&&define.amd?define(["jquery","datatables.net"],function($){return factory($,window,document)}):"object"==typeof exports?module.exports=function(root,$){return root||(root=window),$&&$.fn.dataTable||($=require("datatables.net")(root,$).$),factory($,root,root.document)}:factory(jQuery,window,document)}(function($,window,document,undefined){"use strict";function addActiveFilterControl(dt,filter){var i,ctx=dt.settings()[0];ctx._pfFilter.activeFilterControls.append('
  • '+filter.name+": "+filter.value+'
  • '),$("a",ctx._pfFilter.activeFilterControls).last().on("click",function(e){for(i=0;i0&&addFilter(dt,{column:ctx._pfFilter.filterColumn,name:ctx._pfFilter.filterName,value:this.value}),!1)})}function handleFilterOption(dt,i){var ctx=dt.settings()[0];null!==ctx._pfFilter.filterCols[i]&&ctx._pfFilter.filterCols[i].optionSelector!==undefined&&$(ctx._pfFilter.filterCols[i].optionSelector).on("click",function(e){ctx._pfFilter.filterInput!==undefined&&0!==ctx._pfFilter.filterInput.length&&(ctx._pfFilter.filterInput.get(0).placeholder=ctx._pfFilter.filterCols[i].placeholder),ctx._pfFilter.filterLabel!==undefined&&0!==ctx._pfFilter.filterLabel.length&&ctx._pfFilter.filterLabel.html($(this).text()),ctx._pfFilter.filterButton!==undefined&&0!==ctx._pfFilter.filterButton.length&&ctx._pfFilter.filterButton.html($(this).text()+' '),ctx._pfFilter.filterColumn=i,ctx._pfFilter.filterName=$(this).text()})}function updateFilterResults(dt){var ctx=dt.settings()[0],filteredRows=dt.rows({page:"current",search:"applied"}).flatten().length;ctx._pfFilter.filterResults!==undefined&&0!==ctx._pfFilter.filterResults.length&&ctx._pfFilter.filterResults.html(filteredRows+" Results")}var DataTable=$.fn.dataTable;return DataTable.pfFilter={},DataTable.pfFilter.init=function(dt){var i,ctx=dt.settings()[0],opts=ctx.oInit.pfConfig?ctx.oInit.pfConfig:{};if(ctx._pfFilter={},ctx._pfFilter.filterButton=$(".toolbar-pf-filter button",opts.toolbarSelector),ctx._pfFilter.filterCols=opts.filterCols,ctx._pfFilter.filterLabel=$(".toolbar-pf-filter label",opts.toolbarSelector),ctx._pfFilter.filterInput=$(".toolbar-pf-filter input",opts.toolbarSelector),ctx._pfFilter.filters=[],ctx._pfFilter.activeFilterControls=$(".list-inline",opts.toolbarSelector),ctx._pfFilter.activeFilters=ctx._pfFilter.activeFilterControls.closest("div"),ctx._pfFilter.clearFilters=$(".toolbar-pf-results a",opts.toolbarSelector),ctx._pfFilter.results=$(".toolbar-pf-results",opts.toolbarSelector),ctx._pfFilter.filterCaseInsensitive=opts.filterCaseInsensitive,ctx._pfFilter.filterResults=$(".toolbar-pf-results h5",opts.toolbarSelector),ctx._pfFilter.filterCols!==undefined){for(i=0;i"+selectedRows+" of "+totalRows+" selected")}var DataTable=$.fn.dataTable;return DataTable.pfSelect={},DataTable.pfSelect.init=function(dt){var ctx=dt.settings()[0],opts=ctx.oInit.pfConfig?ctx.oInit.pfConfig:{},select=ctx.oInit.select?ctx.oInit.select:{},style=dt.select.style();ctx._pfSelect={},ctx._pfSelect.selectAllSelector=opts.selectAllSelector!==undefined?opts.selectAllSelector:'th:first-child input[type="checkbox"]',ctx._pfSelect.selector=select.selector!==undefined?select.selector:'td:first-child input[type="checkbox"]',ctx._pfSelect.results=$(".table-view-pf-select-results",opts.toolbarSelector),"api"===style?($(dt.table().container()).on("click",ctx._pfSelect.selectAllSelector,function(evt){evt.preventDefault()}),$(dt.table().container()).on("click",ctx._pfSelect.selector,function(evt){evt.preventDefault()}),dt.table().on("select.dt",function(){syncSelectCheckboxes(dt)})):($(dt.table().container()).on("click",ctx._pfSelect.selectAllSelector,function(evt){selectAllRows(dt,evt.target.checked)}),$(dt.table().container()).on("click",ctx._pfSelect.selector,function(evt){"multi"!==style||"multi+shift"!==style?syncSelectCheckboxes(dt):syncSelectAllCheckbox(dt)})),dt.table().on("draw.dt",function(){syncSelectCheckboxes(dt)}),updateSelectedRowsText(dt)},DataTable.Api.register("pfSelect.selectAllRows()",function(select){return this.iterator("table",function(ctx){selectAllRows(new DataTable.Api(ctx),select)})}),$(document).on("preInit.dt.dtSelect",function(e,ctx){"dt"===e.namespace&&DataTable.pfSelect.init(new DataTable.Api(ctx))}),DataTable.pfSelect}); 2 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {title} 4 | 5 | 6 | 7 | 8 | 9 | 10 |
    11 |
    12 |
    13 |
    14 | GSSAPI demo 15 |
    16 |
    17 | 47 |
    48 |

    Login with Kerberos credentials

    49 |
    50 |
    51 | 54 |
    55 | 56 | 57 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/ui/render.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {title} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
    12 | 15 |
    16 |
    17 | {envvars} 18 |
    19 |
    20 | 23 |
    24 | 25 | 26 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/files/wsgi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | import os 3 | from pprint import pformat 4 | 5 | HERE = os.path.dirname(os.path.abspath(__file__)) 6 | CONTENT = os.path.join(HERE, 'ui', 'render.html') 7 | LOGIN = os.path.join(HERE, 'ui', 'login.html') 8 | ERROR = os.path.join(HERE, 'ui', 'error.html') 9 | 10 | PREFIXES = ('REMOTE_USER', 'REMOTE_GROUPS', 'MELLON_') 11 | 12 | 13 | def render(environ): 14 | kwargs = dict( 15 | title='Demo App', 16 | env=pformat(environ), 17 | ) 18 | 19 | if environ.get('REMOTE_USER') is None: 20 | status = '401 Unauthorized' 21 | if (environ.get('REDIRECT_REMOTE_USER') is None and 22 | environ.get('SHOW_LOGIN')): 23 | template_file = LOGIN 24 | else: 25 | kwargs['strongmsg'] = environ.get('REDIRECT_EXTERNAL_AUTH_ERROR', 26 | 'No REMOTE_USER') 27 | kwargs['msg'] = environ.get('REDIRECT_REMOTE_USER', '') 28 | template_file = ERROR 29 | else: 30 | status = '200 OK' 31 | template_file = CONTENT 32 | 33 | envvars = [] 34 | for k, v in sorted(environ.iteritems()): 35 | if not k.startswith(PREFIXES): 36 | continue 37 | envvars.append('
    {0}
    '.format(k)) 38 | if k.lower().endswith('groups'): 39 | envvars.append('
      ') 40 | for group in sorted(v.split(':')): 41 | envvars.append('
    • {0}
    • '.format(group)) 42 | envvars.append('
    ') 43 | else: 44 | envvars.append('
    {0}
    '.format(v)) 45 | 46 | kwargs['envvars'] = '\n'.join(envvars) 47 | 48 | with open(template_file) as f: 49 | template = f.read() 50 | output = template.format(**kwargs) 51 | return status, output 52 | 53 | 54 | def application(environ, start_response): 55 | try: 56 | status, output = render(environ) 57 | except Exception as e: 58 | status = '500 Server Error' 59 | output = str(e) 60 | 61 | response_headers = [ 62 | ('Content-type', 'text/html'), 63 | ('Content-Length', str(len(output))) 64 | ] 65 | start_response(status, response_headers) 66 | return [output] 67 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart httpd 3 | service: name=httpd state=restarted 4 | 5 | - name: restart sssd 6 | service: name=sssd state=restarted 7 | 8 | - name: flush sssd 9 | command: sss_cache -E 10 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - ipa-modssl 4 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/tasks/cert.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get ipa-getcert list 3 | tags: 4 | - ipa-wwwdemo 5 | command: 6 | ipa-getcert list 7 | register: 8 | ipa_getcert 9 | changed_when: false 10 | 11 | - name: Set has_server_cert and CA unreachable facts 12 | tags: 13 | - ipa-wwwdemo 14 | set_fact: 15 | has_server_cert: "{{ cert in ipa_getcert.stdout }}" 16 | ca_unreachable: "{{ 'CA_UNREACHABLE' in ipa_getcert.stdout }}" 17 | changed_when: false 18 | 19 | - name: Restart certmonger when in state CA_UNREACHABLE 20 | tags: 21 | - ipa-wwwdemo 22 | service: name=certmonger.service enabled=yes state=restarted 23 | when: ca_unreachable 24 | 25 | - name: Request certificate with ipa-getcert 26 | tags: 27 | - ipa-wwwdemo 28 | ipa: 29 | cmd=ipa-getcert 30 | args="request -w -k {{ private_key }} -f {{ cert }} -D {{ ansible_fqdn }} -K HTTP/{{ ansible_fqdn }} -T caIPAserviceCert -C 'systemctl reload httpd.service'" 31 | keytab=/etc/krb5.keytab 32 | when: not has_server_cert 33 | notify: 34 | - restart httpd 35 | 36 | # Also a workaround for https://fedorahosted.org/freeipa/ticket/5653 37 | - name: Wait for certmonger 38 | tags: 39 | - ipa-wwwdemo 40 | waitforcertmonger: 41 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/tasks/httpdconf.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create Apache config for demo app (default) 3 | tags: 4 | - ipa-wwwdemo 5 | template: 6 | src=wwwdemo.conf 7 | dest=/etc/httpd/conf.d/wwwdemo.conf 8 | when: deploy_service 9 | notify: 10 | - restart httpd 11 | 12 | - name: Set default facts for config 13 | tags: 14 | - ipa-wwwdemo 15 | set_fact: 16 | auth_gssapi=true 17 | auth_gssapi_cookie=false 18 | authnz_pam=false 19 | lookup_identity=false 20 | intercept_form=false 21 | 22 | - name: Create Apache config for demo app (1) 23 | tags: 24 | - ipa-wwwdemo 25 | template: 26 | src=wwwdemo.conf 27 | dest=/etc/httpd/conf.d/wwwdemo.conf.1 28 | 29 | - name: With lookup_identity 30 | tags: 31 | - ipa-wwwdemo 32 | set_fact: 33 | auth_gssapi=true 34 | lookup_identity=true 35 | 36 | - name: Create Apache config for demo app (2) 37 | tags: 38 | - ipa-wwwdemo 39 | template: 40 | src=wwwdemo.conf 41 | dest=/etc/httpd/conf.d/wwwdemo.conf.2 42 | 43 | - name: With authnz_pam 44 | tags: 45 | - ipa-wwwdemo 46 | set_fact: 47 | auth_gssapi=true 48 | lookup_identity=true 49 | authnz_pam=true 50 | 51 | - name: Create Apache config for demo app (3) 52 | tags: 53 | - ipa-wwwdemo 54 | template: 55 | src=wwwdemo.conf 56 | dest=/etc/httpd/conf.d/wwwdemo.conf.3 57 | 58 | - name: With intercept form 59 | tags: 60 | - ipa-wwwdemo 61 | set_fact: 62 | auth_gssapi=true 63 | lookup_identity=true 64 | authnz_pam=true 65 | intercept_form=true 66 | 67 | - name: Create Apache config for demo app (4) 68 | tags: 69 | - ipa-wwwdemo 70 | template: 71 | src=wwwdemo.conf 72 | dest=/etc/httpd/conf.d/wwwdemo.conf.4 73 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/tasks/ipaconf.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Add www demo groups 3 | tags: 4 | - ipa-wwwdemo 5 | ipa: 6 | args="{{ item }}" 7 | password="{{ ipa_admin_password }}" 8 | ignore_no_modifications=true 9 | ignore_already_exists=true 10 | with_items: 11 | - group-add webadmins 12 | - group-add webusers 13 | - hostgroup-add webservers 14 | - hostgroup-add-member webservers --hosts={{ ansible_fqdn }} 15 | - hostgroup-add usermachines 16 | 17 | - name: Add HBAC allow_admin 18 | tags: 19 | - ipa-wwwdemo 20 | ipa: 21 | args="{{ item }}" 22 | password="{{ ipa_admin_password }}" 23 | ignore_no_modifications=true 24 | ignore_already_exists=true 25 | with_items: 26 | - hbacrule-add allow_admin --servicecat=all --hostcat=all 27 | - hbacrule-add-user allow_admin --groups=admins 28 | 29 | - name: Add HABC rule for webadmins 30 | tags: 31 | - ipa-wwwdemo 32 | ipa: 33 | args="{{ item }}" 34 | password="{{ ipa_admin_password }}" 35 | ignore_no_modifications=true 36 | ignore_already_exists=true 37 | with_items: 38 | - hbacrule-add allow_webadmins --servicecat=all 39 | - hbacrule-add-user allow_webadmins --groups=webadmins 40 | - hbacrule-add-host allow_webadmins --hostgroups=webservers 41 | 42 | - name: Add HABC rule for webusers 43 | tags: 44 | - ipa-wwwdemo 45 | ipa: 46 | args="{{ item }}" 47 | password="{{ ipa_admin_password }}" 48 | ignore_no_modifications=true 49 | ignore_already_exists=true 50 | with_items: 51 | - hbacsvc-add websvc 52 | - hbacrule-add allow_webusers 53 | - hbacrule-add-user allow_webusers --groups=webusers 54 | - hbacrule-add-host allow_webusers --hostgroups=webservers 55 | - hbacrule-add-service allow_webusers --hbacsvcs=websvc 56 | 57 | - name: Disable allow_all HABC 58 | tags: 59 | - ipa-wwwdemo 60 | ipa: 61 | args="hbacrule-disable allow_all" 62 | password="{{ ipa_admin_password }}" 63 | ignore_no_modifications=true 64 | ignore_already_exists=true 65 | 66 | - name: Add SUDO role for wwwdemo 67 | tags: 68 | - ipa-wwwdemo 69 | ipa: 70 | args="{{ item }}" 71 | password="{{ ipa_admin_password }}" 72 | ignore_no_modifications=true 73 | ignore_already_exists=true 74 | with_items: 75 | - sudorule-add sudo_webadmins --cmdcat=all --runasusercat=all --runasgroupcat=all 76 | - sudorule-add-option sudo_webadmins --sudooption '!authenticate' 77 | - sudorule-add-user sudo_webadmins --groups=webadmins 78 | - sudorule-add-host sudo_webadmins --hostgroups=webservers --hostgroups=usermachines 79 | 80 | - name: Add privilege for wwwdemo 81 | tags: 82 | - ipa-wwwdemo 83 | ipa: 84 | args="{{ item }}" 85 | password="{{ ipa_admin_password }}" 86 | ignore_no_modifications=true 87 | ignore_already_exists=true 88 | with_items: 89 | - role-add 'Service Admin' 90 | - role-add-privilege 'Service Admin' --privileges='Service Administrators' 91 | - role-add-member 'Service Admin' --groups=webadmins 92 | 93 | - name: Add demo user cheimes (webadmins, webusers) 94 | tags: 95 | - ipa-wwwdemo 96 | ipa: 97 | args="{{ item }}" 98 | password="{{ ipa_admin_password }}" 99 | ignore_no_modifications=true 100 | ignore_already_exists=true 101 | with_items: 102 | - user-add cheimes --first=Christian --last=Heimes --email='christian@python.org' 103 | - group-add-member webadmins --users=cheimes 104 | - group-add-member webusers --users=cheimes 105 | 106 | - name: Add demo user bob (webusers) 107 | tags: 108 | - ipa-wwwdemo 109 | ipa: 110 | args="{{ item }}" 111 | password="{{ ipa_admin_password }}" 112 | ignore_no_modifications=true 113 | ignore_already_exists=true 114 | with_items: 115 | - user-add bob --first=Bob --last=Smith 116 | 117 | - name: Create script to set passwords 118 | tags: 119 | - ipa-wwwdemo 120 | template: 121 | src=userpasswd.sh 122 | dest=/root/userpasswd.sh 123 | mode=0750 124 | owner=root 125 | group=root 126 | 127 | - name: Set passwords 128 | tags: 129 | - ipa-wwwdemo 130 | command: /root/userpasswd.sh 131 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/tasks/keytab.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get keytab content 3 | tags: 4 | - ipa-wwwdemo 5 | command: klist -ke {{ http_keytab }} 6 | register: keytab 7 | changed_when: false 8 | failed_when: "keytab.rc != 0 and 'not found' not in keytab.stderr" 9 | 10 | - name: Check for principal in keytab 11 | tags: 12 | - ipa-wwwdemo 13 | changed_when: false 14 | set_fact: 15 | keytab_http_principal: "{{ 'HTTP/{{ ansible_fqdn }}' in keytab.stdout }}" 16 | 17 | - name: Create HTTP service 18 | tags: 19 | - ipa-wwwdemo 20 | ipa: 21 | args="service-add --force HTTP/{{ ansible_fqdn }}" 22 | keytab=/etc/krb5.keytab 23 | ignore_already_exists=true 24 | when: not keytab_http_principal 25 | 26 | - name: Add HTTP service to keytab 27 | tags: 28 | - ipa-wwwdemo 29 | ipa: 30 | cmd=ipa-getkeytab 31 | args="-s $IPA_SERVER -p HTTP/{{ ansible_fqdn }} -k {{ http_keytab }}" 32 | keytab=/etc/krb5.keytab 33 | when: not keytab_http_principal 34 | notify: 35 | - restart httpd 36 | 37 | - name: chown http.keytab 38 | tags: 39 | - ipa-wwwdemo 40 | file: 41 | path={{ http_keytab }} 42 | owner=apache 43 | group=apache 44 | mode=0600 45 | seuser=unconfined_u 46 | serole=object_r 47 | setype=httpd_config_t 48 | selevel=s0 49 | notify: 50 | - restart httpd 51 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install Apache HTTPD and modules 3 | tags: 4 | - ipa-wwwdemo 5 | - package-install 6 | - network 7 | package: name={{ item }} state=present 8 | with_items: 9 | - httpd 10 | - ipsilon-client 11 | - mod_ssl 12 | - mod_wsgi 13 | - mod_auth_gssapi 14 | - mod_authnz_pam 15 | - mod_intercept_form_submit 16 | - mod_lookup_identity 17 | - libsss_simpleifp 18 | - sssd-dbus 19 | - mod_session 20 | - mod_auth_mellon 21 | - mod_authnz_pam 22 | when: package_install 23 | notify: 24 | - restart httpd 25 | - restart sssd 26 | 27 | - name: Remove welcome.conf 28 | tags: 29 | - ipa-wwwdemo 30 | file: dest=/etc/httpd/conf.d/welcome.conf state=absent 31 | notify: 32 | - restart httpd 33 | 34 | - name: Enable Apache HTTPD service 35 | tags: 36 | - ipa-wwwdemo 37 | service: name=httpd.service enabled=yes 38 | 39 | - name: Create PAM service file for Apache example app 40 | tags: 41 | - ipa-wwwdemo 42 | copy: 43 | src=pam_websvc 44 | dest=/etc/pam.d/websvc 45 | notify: 46 | - restart httpd 47 | 48 | - name: setsebool allow_httpd_mod_auth_pam on 49 | tags: 50 | - ipa-wwwdemo 51 | seboolean: name=httpd_mod_auth_pam state=yes persistent=yes 52 | notify: 53 | - restart httpd 54 | 55 | - name: Template local scripts 56 | tags: 57 | - ipa-wwwdemo 58 | become: no 59 | local_action: 60 | template 61 | src={{ item }} 62 | dest={{ ipa_script_dir }}/{{ item }} 63 | mode=0755 64 | run_once: true 65 | with_items: 66 | - ipa_demossh 67 | - ipa_democheck 68 | 69 | - include: keytab.yml 70 | when: deploy_service 71 | - include: cert.yml 72 | when: deploy_service 73 | - include: undeploy.yml 74 | when: undeploy_service 75 | - include: sssd_ifp.yml 76 | - include: ipaconf.yml 77 | - include: usermachine.yml 78 | - include: httpdconf.yml 79 | 80 | - name: Create directory for demo app 81 | tags: 82 | - ipa-wwwdemo 83 | file: 84 | path=/srv/www/demo/ui 85 | state=directory 86 | mode=0755 87 | owner=root 88 | group=root 89 | seuser=system_u 90 | serole=object_r 91 | setype=httpd_sys_content_t 92 | selevel=s0 93 | 94 | - name: Copy Apache demo app files 95 | tags: 96 | - ipa-wwwdemo 97 | copy: 98 | src=ui/ 99 | dest=/srv/www/demo/ui/ 100 | mode=0644 101 | directory_mode=0755 102 | owner=root 103 | group=root 104 | seuser=system_u 105 | serole=object_r 106 | setype=httpd_sys_content_t 107 | selevel=s0 108 | notify: 109 | - restart httpd 110 | when: false 111 | 112 | - name: Copy Apache demo app files 113 | tags: 114 | - ipa-wwwdemo 115 | synchronize: 116 | src=ui/ 117 | dest=/srv/www/demo/ui/ 118 | owner=false 119 | group=false 120 | recursive=true 121 | delete=true 122 | times=true 123 | 124 | - name: Copy WSGI app for demo app 125 | tags: 126 | - ipa-wwwdemo 127 | copy: 128 | src=wsgi.py 129 | dest=/srv/www/demo/wsgi.py 130 | mode=0644 131 | directory_mode=0755 132 | owner=root 133 | group=root 134 | seuser=system_u 135 | serole=object_r 136 | setype=httpd_sys_content_t 137 | selevel=s0 138 | notify: 139 | - restart httpd 140 | 141 | - name: Create helper scripts 142 | tags: 143 | - ipa-wwwdemo 144 | template: 145 | src={{ item }} 146 | dest=/root/{{ item }} 147 | mode=0750 148 | owner=root 149 | group=root 150 | with_items: 151 | - demostep.sh 152 | - getcert.sh 153 | - getkeytab.sh 154 | - rekeycert.sh 155 | - rmcert.sh 156 | - ocsp.sh 157 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/tasks/sssd_ifp.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setsebool httpd_dbus_sssd on 3 | tags: 4 | - ipa-wwwdemo 5 | seboolean: name=httpd_dbus_sssd state=yes persistent=yes 6 | notify: 7 | - restart httpd 8 | 9 | - name: Add ldap_user_extra_attrs to sssd.conf 10 | tags: 11 | - ipa-wwwdemo 12 | - ipa-install 13 | ini_file: 14 | dest=/etc/sssd/sssd.conf 15 | section="domain/{{ ipa.domain }}" 16 | option=ldap_user_extra_attrs 17 | value="mail, givenname, sn" 18 | notify: 19 | - restart sssd 20 | - flush sssd 21 | 22 | - name: Add [ifp]allowed_uids to sssd.conf 23 | tags: 24 | - ipa-wwwdemo 25 | ini_file: 26 | dest=/etc/sssd/sssd.conf 27 | section="ifp" 28 | option=allowed_uids 29 | value="apache, root" 30 | notify: 31 | - restart sssd 32 | - flush sssd 33 | 34 | - name: Add [ifp]user_attributes to sssd.conf 35 | tags: 36 | - ipa-wwwdemo 37 | ini_file: 38 | dest=/etc/sssd/sssd.conf 39 | section="ifp" 40 | option=user_attributes 41 | value="+mail, +givenname, +sn" 42 | notify: 43 | - restart sssd 44 | - flush sssd 45 | 46 | - name: Add [ifp]user_attributes to sssd.conf 47 | tags: 48 | - ipa-wwwdemo 49 | ini_file: 50 | dest=/etc/sssd/sssd.conf 51 | section="sssd" 52 | option=services 53 | value="nss, sudo, pam, autofs, ssh, ifp" 54 | notify: 55 | - restart sssd 56 | - flush sssd 57 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/tasks/undeploy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Undeploy, remove IPA services/groups/... 3 | tags: 4 | - ipa-wwwdemo 5 | - ipa-wwwdemo-undeploy 6 | ipa: 7 | args="{{ item }}" 8 | password="{{ ipa_admin_password }}" 9 | ignore_no_modifications=true 10 | ignore_already_exists=true 11 | with_items: 12 | - service-del HTTP/{{ ansible_fqdn }} 13 | - group-remove-member webusers --users=bob 14 | failed_when: false 15 | 16 | - name: Untrack certificate 17 | tags: 18 | - ipa-wwwdemo 19 | - ipa-wwwdemo-undeploy 20 | command: ipa-getcert stop-tracking -k {{ private_key }} -f {{ cert }} 21 | failed_when: false 22 | 23 | - name: Remove keytab and certs 24 | tags: 25 | - ipa-wwwdemo 26 | - ipa-wwwdemo-undeploy 27 | file: 28 | path={{ item }} 29 | state=absent 30 | with_items: 31 | - "{{ cert }}" 32 | - "{{ private_key }}" 33 | - "{{ http_keytab }}" 34 | - /etc/httpd/conf.d/wwwdemo.conf 35 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/tasks/usermachine.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Add usermachine (GUI) 3 | tags: 4 | - ipa-wwwdemo 5 | ipa: 6 | args="{{ item }}" 7 | password="{{ ipa_admin_password }}" 8 | ignore_no_modifications=true 9 | ignore_already_exists=true 10 | with_items: 11 | - host-add --force usermachine.{{ ipa_domain }} 12 | - hostgroup-add-member usermachines --hosts=usermachine.{{ ipa_domain }} 13 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/templates/demostep.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | CONF=/etc/httpd/conf.d/wwwdemo.conf 5 | 6 | if [ "$#" -ne 1 ] || [ ! -f "${CONF}.${1}" ]; then 7 | echo "Usage: $0 step" >&2 8 | exit 1 9 | fi 10 | 11 | if [ ! -f "{{ http_keytab }}" ]; then 12 | echo "{{ http_keytab }} missing" 13 | exit 2 14 | fi 15 | 16 | if [ ! -f "{{ cert }}" ]; then 17 | echo "{{ cert }} missing" 18 | exit 3 19 | fi 20 | 21 | set -x 22 | cp ${CONF}.${1} ${CONF} 23 | systemctl reload httpd.service 24 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/templates/getcert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | kinit -kt /etc/krb5.keytab 5 | ipa service-show HTTP/{{ ansible_fqdn }} > /dev/null 6 | rm -f {{ private_key }} {{ cert }} 7 | 8 | set -x 9 | 10 | ipa-getcert request -w \ 11 | -k {{ private_key }} \ 12 | -f {{ cert }} \ 13 | -D {{ ansible_fqdn }} \ 14 | -K HTTP/{{ ansible_fqdn }} \ 15 | -C 'systemctl reload httpd.service' 16 | 17 | set +x 18 | 19 | read -p next 20 | 21 | ipa-getcert list 22 | 23 | read -p next 24 | 25 | openssl x509 -noout -text -in {{ cert }} 26 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/templates/getkeytab.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | kinit -kt /etc/krb5.keytab 5 | ipa service-show HTTP/{{ ansible_fqdn }} > /dev/null 6 | 7 | rm -f {{ http_keytab }} 8 | 9 | set -x 10 | ipa-getkeytab -p HTTP/{{ ansible_fqdn }} -k {{ http_keytab }} 11 | chown apache:apache {{ http_keytab }} 12 | chmod 600 {{ http_keytab }} 13 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/templates/ipa_democheck: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | ADMIN_PASSWD="{{ ipa_admin_password }}" 5 | 6 | if [ -z "$IPA_INVENTORY" ]; then 7 | echo "ERROR" > /dev/stderr 8 | echo ". {{ ipa_data_dir }}/ipaenv" > /dev/stderr 9 | exit 1 10 | fi 11 | 12 | echo "server=/{{ ipa.domain }}/{{ hostvars[groups['ipaserver_master'][0]].ansible_default_ipv4.address }}" 13 | host {{ hostvars[groups['ipaserver_master'][0]].ansible_fqdn }} 14 | 15 | rm -f ~/.ssh/knownhosts_ipa 16 | 17 | echo "${ADMIN_PASSWD}" | kinit admin 18 | 19 | {% for host in hostvars %} 20 | ping -c1 {{ hostvars[host].ansible_fqdn }} 21 | dig -t sshfp {{ hostvars[host].ansible_fqdn }} > /dev/null 22 | ssh admin@{{ hostvars[host].ansible_fqdn }} -- hostname 23 | {% endfor %} 24 | 25 | echo "${ADMIN_PASSWD}" | kinit cheimes 26 | 27 | ssh cheimes@{{ ansible_fqdn }} -- hostname 28 | 29 | echo "${ADMIN_PASSWD}" | kinit bob 30 | 31 | kdestroy -A 32 | 33 | echo 34 | echo "Demo setup is working." 35 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/templates/ipa_demossh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | ssh-keygen -R {{ ansible_fqdn }} -f ~/.ssh/knownhosts_ipa 4 | 5 | set -x 6 | ssh -o "VerifyHostKeyDNS yes" -o "StrictHostKeyChecking ask" cheimes@{{ ansible_fqdn }} $@ 7 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/templates/ocsp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ex 3 | 4 | openssl s_client \ 5 | -connect {{ ansible_fqdn }}:443 \ 6 | -verify_hostname {{ ansible_fqdn }} \ 7 | -CAfile /etc/pki/tls/certs/ca-bundle.crt \ 8 | -status | egrep --color=always '.*Status.*|$' | less -R 9 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/templates/rekeycert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | ipa-getcert rekey -w -f {{ cert }} 5 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/templates/rmcert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | rm -f {{ private_key }} {{ cert }} 5 | ipa-getcert stop-tracking 6 | -k {{ private_key }} \ 7 | -f {{ cert }} 8 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/templates/userpasswd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | ADMIN_PASSWD="{{ ipa_admin_password }}" 5 | PASSWD="{{ ipa_admin_password }}" 6 | TMPCCACHE="/tmp/ccache.tmp" 7 | 8 | export KRB5CCNAME=/tmp/ccache.admin 9 | rm -f "${KRB5CCNAME}" 10 | 11 | echo "${ADMIN_PASSWD}" | kinit admin 12 | 13 | echo -e "${PASSWD}\n${PASSWD}" | ipa passwd cheimes 14 | echo -e "${PASSWD}\n${PASSWD}\n${PASSWD}" | kinit -c "${TMPCCACHE}" cheimes 15 | 16 | echo -e "${PASSWD}\n${PASSWD}" | ipa passwd bob 17 | echo -e "${PASSWD}\n${PASSWD}\n${PASSWD}" | kinit -c "${TMPCCACHE}" bob 18 | 19 | rm -f "${KRB5CCNAME}" "${TMPCCACHE}" 20 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/templates/wwwdemo.conf: -------------------------------------------------------------------------------- 1 | LoadModule lookup_identity_module modules/mod_lookup_identity.so 2 | LoadModule intercept_form_submit_module modules/mod_intercept_form_submit.so 3 | LoadModule authnz_pam_module modules/mod_authnz_pam.so 4 | 5 | SSLStaplingCache shmcb:/var/run/httpd/stapling.cache(512000) 6 | 7 | 8 | ServerName {{ ansible_fqdn }} 9 | Redirect permanent / https://{{ ansible_fqdn }}/ 10 | 11 | 12 | 13 | ServerName {{ ansible_fqdn }} 14 | 15 | LogLevel info 16 | 17 | SSLEngine on 18 | SSLProtocol all -SSLv3 19 | SSLCipherSuite PROFILE=SYSTEM 20 | SSLCertificateFile /etc/pki/tls/certs/{{ ansible_fqdn }}.crt 21 | SSLCertificateKeyFile /etc/pki/tls/private/{{ ansible_fqdn }}.key 22 | 23 | SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt 24 | SSLUseStapling on 25 | # 5 seconds timeout for demo 26 | SSLStaplingStandardCacheTimeout 5 27 | SSLStaplingErrorCacheTimeout 5 28 | 29 | WSGIDaemonProcess wwwdemo display-name=%{GROUP} 30 | WSGIImportScript /srv/www/demo/wsgi.py process-group=wwwdemo application-group=wwwdemo 31 | WSGIScriptAlias / /srv/www/demo/wsgi.py 32 | 33 | 34 | WSGIProcessGroup wwwdemo 35 | WSGIApplicationGroup wwwdemo 36 | 37 | {% if auth_gssapi | default(true) %} 38 | # mod_auth_gssapi (Kerberos) 39 | AuthType GSSAPI 40 | AuthName "GSSAPI Single Sign On Login" 41 | GssapiCredStore keytab:/etc/httpd/{{ ansible_fqdn }}.keytab 42 | {% endif %} 43 | 44 | # Require account 45 | {% if authnz_pam | default(true) %} 46 | # mod_authnz_pam (PAM servie wwwsvc) 47 | Require pam-account websvc 48 | {% elif auth_gssapi | default(true) %} 49 | Require valid-user 50 | {% else %} 51 | Require all granted 52 | {% endif %} 53 | {% if intercept_form | default(true) %} 54 | SetEnv SHOW_LOGIN 1 55 | {% else %} 56 | UnSetEnv SHOW_LOGIN 57 | {% endif %} 58 | 59 | {% if auth_gssapi_cookie | default(false) %} 60 | # Cookie session: mod_session + mod_auth_gssapi (default: FALSE) 61 | Session On 62 | SessionCookieName session path=/;httponly;secure; 63 | SessionMaxAge 1800 64 | GssapiUseSessions On 65 | GssapiSessionKey file:/var/run/httpd/{{ ansible_fqdn }}.sessionkey 66 | {% endif %} 67 | 68 | {% if lookup_identity | default(true) %} 69 | # mod_lookup_identity 70 | LookupUserGECOS REMOTE_USER_FULLNAME 71 | LookupUserGroups REMOTE_USER_GROUPS : 72 | LookupUserAttr uidNumber REMOTE_USER_UID 73 | LookupUserAttr mail REMOTE_USER_EMAIL 74 | LookupUserAttr sn REMOTE_USER_SN 75 | LookupUserAttr givenname REMOTE_USER_GIVENNAME 76 | {% endif %} 77 | 78 | 79 | WSGIErrorOverride Off 80 | ErrorDocument 401 /login 81 | 82 | Require all granted 83 | Order Allow,Deny 84 | Allow from All 85 | 86 | 87 | {% if intercept_form | default(true) %} 88 | 89 | # mod_intercept_form_submit 90 | InterceptFormPAMService websvc 91 | InterceptFormLogin username 92 | InterceptFormPassword password 93 | 94 | RewriteCond %{REQUEST_METHOD} !POST 95 | RewriteRule ^/.* / [R] 96 | 97 | {% endif %} 98 | 99 | Alias /ui "/srv/www/demo/ui" 100 | 101 | Require all granted 102 | Order Allow,Deny 103 | Allow from All 104 | ExpiresActive On 105 | ExpiresDefault "access plus 1 hour" 106 | 107 | -------------------------------------------------------------------------------- /ansible/roles/ipa-wwwdemo/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | cert: /etc/pki/tls/certs/{{ ansible_fqdn }}.crt 3 | private_key: /etc/pki/tls/private/{{ ansible_fqdn }}.key 4 | http_keytab: /etc/httpd/{{ ansible_fqdn }}.keytab 5 | deploy_service: true 6 | undeploy_service: false 7 | -------------------------------------------------------------------------------- /ansible/roles/ipa/files/ipa-client.tmpfiles.conf: -------------------------------------------------------------------------------- 1 | # workaround https://pagure.io/freeipa/issue/7048 2 | d /var/run/ipa 0711 root root 3 | -------------------------------------------------------------------------------- /ansible/roles/ipa/files/replaced: -------------------------------------------------------------------------------- 1 | # This configuration file has been replaced with an empty file for FreeIPA. 2 | -------------------------------------------------------------------------------- /ansible/roles/ipa/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart httpd 3 | service: name=httpd state=restarted 4 | 5 | - name: restart gssproxy 6 | service: name=gssproxy state=restarted 7 | -------------------------------------------------------------------------------- /ansible/roles/ipa/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - common 4 | 5 | -------------------------------------------------------------------------------- /ansible/roles/ipa/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # we modify the file later but need the original DNS forwarder 3 | - name: make a copy of original resolv.conf 4 | tags: 5 | - ipa 6 | command: cp /etc/resolv.conf /etc/resolv.conf.orig 7 | args: 8 | creates: /etc/resolv.conf.orig 9 | 10 | - name: Get default DNS 11 | tags: 12 | - ipa 13 | resolver: resolvconf=/etc/resolv.conf.orig 14 | register: dns_forwarder 15 | changed_when: false 16 | 17 | - name: Get reverse zone 18 | tags: 19 | - ipa 20 | - setup 21 | reversezone: ipaddress={{ ansible_default_ipv4.address }} 22 | register: reversezone 23 | changed_when: false 24 | 25 | - name: Remove chrony (FreeIPA uses ntpd) 26 | tags: 27 | - ipa 28 | - package-install 29 | package: name=chrony state=absent 30 | when: package_install 31 | 32 | - name: install FreeIPA client package 33 | tags: 34 | - ipa 35 | - package-install 36 | - network 37 | package: name={{ item }} state=present 38 | with_items: 39 | - ipa-client 40 | - ipa-admintools 41 | when: package_install 42 | 43 | - name: Copy workaround tmpfiles.d for /var/run/ipa 44 | tags: 45 | - ipa 46 | copy: 47 | src=ipa-client.tmpfiles.conf 48 | dest=/etc/tmpfiles.d/ipa-client.conf 49 | owner=root 50 | group=root 51 | mode=0644 52 | 53 | - name: Gather IPA facts 54 | tags: 55 | - ipa 56 | - setup 57 | ipa_facts: domain={{ ipa_domain }} 58 | 59 | - name: Set install facts 60 | tags: 61 | - ipa 62 | - setup 63 | changed_when: false 64 | set_fact: 65 | install_ipa_nfsserver: "{{ 'ipa_nfsserver' in groups and groups['ipa_nfsserver'] }}" 66 | install_ipa_replica: "{{ 'ipaserver_replica' in groups and groups['ipaserver_replica'] }}" 67 | -------------------------------------------------------------------------------- /ansible/roles/ipaserver-replica/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: replica43.yml 3 | when: ipa.version.version_info >= [4, 3, 0] 4 | 5 | - include: replica42.yml 6 | when: ipa.version.version_info < [4, 3, 0] 7 | 8 | - name: Update IPA facts 9 | tags: 10 | - ipaserver-replica 11 | ipa_facts: domain={{ ipa_domain }} 12 | 13 | - name: Install CA on FreeIPA replica (3-4 minutes) 14 | tags: 15 | - ipaserver-replica 16 | - ipa-install 17 | command: > 18 | ipa-ca-install -U 19 | -p {{ ipa_dm_password }} 20 | when: not ipa.configured.ca and (ipa_replica_ca or ipa_replica_kra) 21 | 22 | - name: Install KRA on FreeIPA replica (2-3 minutes) 23 | tags: 24 | - ipaserver-replica 25 | - ipa-install 26 | command: > 27 | ipa-kra-install -U 28 | -p {{ ipa_dm_password }} 29 | when: not ipa.configured.kra and ipa_replica_kra 30 | 31 | - name: Make sure named-pkcs11 DNS is restarted 32 | tags: 33 | - ipaserver-replica 34 | - ipa-install 35 | service: name=named-pkcs11 state=restarted 36 | changed_when: false 37 | when: ipa_replica_ca or ipa_replica_kra 38 | 39 | - name: Update IPA facts 40 | tags: 41 | - ipaserver-replica 42 | ipa_facts: domain={{ ipa_domain }} 43 | when: ipa_replica_ca or ipa_replica_kra 44 | -------------------------------------------------------------------------------- /ansible/roles/ipaserver-replica/tasks/replica42.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Prepare replication 3 | tags: 4 | - ipaserver-replica 5 | - ipa-install 6 | command: > 7 | ipa-replica-prepare 8 | --password={{ ipa_dm_password }} 9 | --ip-address={{ ansible_default_ipv4.address }} 10 | {{ ansible_fqdn }} 11 | args: 12 | creates: /var/lib/ipa/replica-info-{{ ansible_fqdn }}.gpg 13 | delegate_to: "{{item}}" 14 | with_items: "{{ groups['ipaserver_master'] }}" 15 | 16 | - name: Fetch replication file 17 | tags: 18 | - ipaserver-replica 19 | - ipa-install 20 | - fetch 21 | fetch: 22 | src=/var/lib/ipa/replica-info-{{ ansible_fqdn }}.gpg 23 | dest={{ ipa_data_dir }}/replica-info-{{ ansible_fqdn }}.gpg 24 | flat=yes 25 | delegate_to: "{{item}}" 26 | with_items: "{{ groups['ipaserver_master'] }}" 27 | 28 | - name: Copy replication file 29 | tags: 30 | - ipaserver-replica 31 | - ipa-install 32 | synchronize: 33 | src={{ ipa_data_dir }}/replica-info-{{ ansible_fqdn }}.gpg 34 | dest=/var/lib/ipa/replica-info-{{ ansible_fqdn }}.gpg 35 | 36 | - name: install replica 37 | tags: 38 | - ipaserver-replica 39 | - ipa-install 40 | command: > 41 | ipa-replica-install -U 42 | --password {{ ipa_dm_password }} 43 | --admin-password {{ ipa_admin_password }} 44 | --mkhomedir 45 | --setup-dns 46 | --ip-address {{ ansible_default_ipv4.address }} 47 | --allow-zone-overlap 48 | {{ '--forwarder=%s' % dns_forwarder['nameservers'][0] if enable_network else '--no-forwarders' }} 49 | /var/lib/ipa/replica-info-{{ ansible_fqdn }}.gpg 50 | when: not ipa.configured.server 51 | -------------------------------------------------------------------------------- /ansible/roles/ipaserver-replica/tasks/replica43.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # configure as client first, then promote to replica 3 | - include: ../../ipa-client/tasks/main.yml 4 | 5 | # workaround for https://pagure.io/freeipa/issue/6704 6 | - name: Stop Apache HTTPD to free port 8443 for installation 7 | tags: 8 | - ipaserver-replica 9 | - ipa-install 10 | service: 11 | name=httpd 12 | state=stopped 13 | when: not ipa.configured.server 14 | 15 | - name: install replica 16 | tags: 17 | - ipaserver-replica 18 | - ipa-install 19 | command: > 20 | ipa-replica-install -U 21 | --admin-password {{ ipa_admin_password }} 22 | --mkhomedir 23 | --ip-address {{ ansible_default_ipv4.address }} 24 | --setup-dns 25 | --allow-zone-overlap 26 | --skip-conncheck 27 | {{ '--forwarder=%s' % dns_forwarder['nameservers'][0] if enable_forwarders else '--no-forwarders' }} 28 | when: not ipa.configured.server 29 | -------------------------------------------------------------------------------- /ansible/roles/ipaserver-replica/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ipa_replica_ca: false 3 | ipa_replica_kra: false -------------------------------------------------------------------------------- /ansible/roles/ipaserver/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart firewalld 3 | service: name=firewalld 4 | enabled=yes 5 | state=restarted 6 | 7 | -------------------------------------------------------------------------------- /ansible/roles/ipaserver/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - ipa-modnss 4 | -------------------------------------------------------------------------------- /ansible/roles/ipaserver/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install FreeIPA server package (RHEL / CentOS) 3 | tags: 4 | - ipaserver 5 | - package-install 6 | - network 7 | package: name={{ item }} state=present 8 | with_items: 9 | - bind-pkcs11 10 | - bind-pkcs11-utils 11 | - bind-dyndb-ldap 12 | - ipa-server 13 | - ipa-server-dns 14 | when: package_install 15 | 16 | - name: Open Firewall for services 17 | tags: 18 | - ipaserver 19 | - firewall 20 | firewalld: 21 | service={{ item }} 22 | permanent=true 23 | state=enabled 24 | immediate=yes 25 | with_items: 26 | - freeipa-ldap 27 | - freeipa-ldaps 28 | - dns 29 | when: has_firewalld.stat.exists 30 | -------------------------------------------------------------------------------- /ansible/roles/pki-389ds/handlers/main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/pki-389ds/handlers/main.yml -------------------------------------------------------------------------------- /ansible/roles/pki-389ds/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - common 4 | 5 | -------------------------------------------------------------------------------- /ansible/roles/pki-389ds/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install 389-DS LDAP server 3 | tags: 4 | - 389ds 5 | - package-install 6 | - network 7 | package: name=389-ds-base state=present 8 | 9 | - name: create 389-DS instance 10 | tags: 11 | - 389ds 12 | command: setup-ds.pl \ 13 | --silent \ 14 | General.FullMachineName='{{ ansible_fqdn }}' \ 15 | General.SuiteSpotUserID=nobody \ 16 | General.SuiteSpotGroup=nobody \ 17 | slapd.ServerPort={{ldap_port}} \ 18 | slapd.ServerIdentifier='{{pki_instance_name}}' \ 19 | slapd.Suffix='{{suffix}}' \ 20 | slapd.RootDN='cn=Directory Manager' \ 21 | slapd.RootDNPwd='{{ dm_password }}' 22 | args: 23 | creates: /etc/dirsrv/slapd-{{pki_instance_name}} 24 | -------------------------------------------------------------------------------- /ansible/roles/pki-ca/handlers/main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/pki-ca/handlers/main.yml -------------------------------------------------------------------------------- /ansible/roles/pki-ca/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - pki 4 | -------------------------------------------------------------------------------- /ansible/roles/pki-ca/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install pki-ca package 3 | tags: 4 | - pkica 5 | - package-install 6 | - network 7 | package: name=pki-ca state=present 8 | when: package_install 9 | 10 | - name: Write CA config template 11 | tags: 12 | - pkica 13 | template: src=../../pki/templates/pki.cfg dest=/tmp/{{pki_instance_name}}-pkica.cfg 14 | 15 | - name: create CA 16 | tags: 17 | - pkica 18 | - ipa-install 19 | command: pkispawn -f /tmp/{{pki_instance_name}}-pkica.cfg -s CA 20 | args: 21 | creates: /etc/pki/{{pki_instance_name}}/ca/CS.cfg 22 | 23 | - include: ../../pki/tasks/limitmemory.yml 24 | - include: ../../pki/tasks/fetchadmincert.yml 25 | -------------------------------------------------------------------------------- /ansible/roles/pki-kra/handlers/main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/pki-kra/handlers/main.yml -------------------------------------------------------------------------------- /ansible/roles/pki-kra/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - pki 4 | -------------------------------------------------------------------------------- /ansible/roles/pki-kra/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install pki-kra package 3 | tags: 4 | - pkikra 5 | - package-install 6 | - network 7 | package: name=pki-kra state=present 8 | when: package_install 9 | 10 | - name: Write KRA config template 11 | tags: 12 | - pkikra 13 | template: src=../../pki/templates/pki.cfg dest=/tmp/{{pki_instance_name}}-pkikra.cfg 14 | 15 | - name: create KRA 16 | tags: 17 | - pkikra 18 | - ipa-install 19 | command: pkispawn -f /tmp/{{pki_instance_name}}-pkikra.cfg -s KRA 20 | args: 21 | creates: /etc/pki/{{pki_instance_name}}/kra/CS.cfg 22 | 23 | - include: ../../pki/tasks/limitmemory.yml 24 | - include: ../../pki/tasks/fetchadmincert.yml 25 | -------------------------------------------------------------------------------- /ansible/roles/pki/handlers/main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiran/pki-vagans/070b2c6d7538ed07d09cdb95e06b9b2d457c9e86/ansible/roles/pki/handlers/main.yml -------------------------------------------------------------------------------- /ansible/roles/pki/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - common 4 | - pki-389ds 5 | 6 | -------------------------------------------------------------------------------- /ansible/roles/pki/tasks/fetchadmincert.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: dump admin PKCS12 file to PEM file 3 | tags: 4 | - pki 5 | - pki-install 6 | command: openssl pkcs12 \ 7 | -in /root/.dogtag/{{pki_instance_name}}/ca_admin_cert.p12 \ 8 | -out /root/.dogtag/{{pki_instance_name}}/ca_admin_cert.pem \ 9 | -nodes -passin pass:{{pkcs12_password}} 10 | args: 11 | creates: 12 | /root/.dogtag/{{pki_instance_name}}/ca_admin_cert.pem 13 | 14 | - name: fetch admin cert as /tmp/{{pki_instance_name}}_admin.pem 15 | tags: 16 | - pki 17 | - pki-install 18 | fetch: src=/root/.dogtag/{{pki_instance_name}}/ca_admin_cert.pem 19 | dest=/tmp/{{pki_instance_name}}_admin.pem 20 | flat=yes 21 | -------------------------------------------------------------------------------- /ansible/roles/pki/tasks/limitmemory.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check for tomcat memory limit 3 | tags: 4 | - pki 5 | - pki-install 6 | shell: grep -P '^JAVA_OPTS=.*-Xmx.*' /etc/sysconfig/{{pki_instance_name}} || true 7 | register: tomcat_memorylimit 8 | 9 | - name: limit tomcat memory 10 | tags: 11 | - pki 12 | - ipa-install 13 | lineinfile: dest=/etc/sysconfig/{{pki_instance_name}} 14 | regexp='^JAVA_OPTS="(.*?)(-Xm.*)?"$' 15 | line='JAVA_OPTS="\1 -Xmx256M -Xms256M"' 16 | backrefs=yes 17 | backup=yes 18 | when: "{{ 'Xmx' not in tomcat_memorylimit.stdout }}" 19 | 20 | - name: restart tomcat 21 | tags: 22 | - pki 23 | - pki-install 24 | service: name=pki-tomcatd@{{pki_instance_name}} state=restarted 25 | when: "{{ 'Xmx' not in tomcat_memorylimit.stdout }}" 26 | 27 | - name: wait for tomcat 28 | tags: 29 | - pki 30 | - pki-install 31 | wait_for: port={{https_port}} delay=0 timeout=60 32 | -------------------------------------------------------------------------------- /ansible/roles/pki/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install pki-server packages and dependencies 3 | tags: 4 | - pki 5 | - package-install 6 | - network 7 | package: name={{ item }} state=present 8 | with_items: 9 | - pki-server 10 | - dogtag-pki-server-theme 11 | - openssl 12 | when: package_install 13 | 14 | - name: Open Firewall for services 15 | tags: 16 | - pki 17 | - firewall 18 | firewalld: 19 | service={{ item }} 20 | permanent=true 21 | state=enabled 22 | immediate=yes 23 | with_items: 24 | - ssh 25 | - ldap 26 | - ldaps 27 | when: has_firewalld.stat.exists 28 | 29 | - name: Open Firewall for ports 30 | tags: 31 | - pki 32 | - firewall 33 | firewalld: 34 | port={{ item }} 35 | permanent=true 36 | state=enabled 37 | immediate=yes 38 | with_items: 39 | - 8080/tcp 40 | - 8443/tcp 41 | when: has_firewalld.stat.exists 42 | -------------------------------------------------------------------------------- /ansible/roles/pki/templates/pki.cfg: -------------------------------------------------------------------------------- 1 | # based on 2 | # https://fedorapeople.org/cgit/edewata/public_git/pki-dev.git/tree/scripts/ca.cfg 3 | # https://fedorapeople.org/cgit/edewata/public_git/pki-dev.git/tree/scripts/kra.cfg 4 | 5 | [DEFAULT] 6 | pki_instance_name={{pki_instance_name}} 7 | pki_https_port={{https_port}} 8 | pki_http_port={{http_port}} 9 | pki_master_https_port={{https_port}} 10 | pki_security_domain_https_port={{https_port}} 11 | pki_ds_bind_dn=cn=Directory Manager 12 | pki_ds_ldap_port={{ldap_port}} 13 | pki_ds_password={{dm_password}} 14 | pki_backup_keys=True 15 | pki_backup_password={{backup_password}} 16 | pki_client_database_password={{client_db_password}} 17 | pki_client_database_purge=False 18 | pki_client_pkcs12_password={{pkcs12_password}} 19 | pki_clone_pkcs12_password={{pkcs12_password}} 20 | pki_security_domain_name={{security_domain}} 21 | pki_security_domain_user=caadmin 22 | pki_security_domain_password={{security_domain_password}} 23 | pki_token_password={{token_password}} 24 | 25 | [CA] 26 | pki_admin_email=caadmin@{{ansible_domain}} 27 | pki_admin_name=caadmin 28 | pki_admin_nickname=caadmin 29 | pki_admin_password={{ca_password}} 30 | pki_admin_uid=caadmin 31 | pki_ds_base_dn=dc=ca,{{suffix}} 32 | pki_ds_database=ca 33 | 34 | [KRA] 35 | pki_admin_cert_file=/root/.dogtag/{{pki_instance_name}}/ca_admin.cert 36 | pki_admin_email=kraadmin@{{ansible_domain}} 37 | pki_admin_name=kraadmin 38 | pki_admin_nickname=kraadmin 39 | pki_admin_password={{kra_password}} 40 | pki_admin_uid=kraadmin 41 | pki_ds_base_dn=dc=kra,{{suffix}} 42 | pki_ds_database=kra 43 | 44 | [OCSP] 45 | pki_admin_cert_file=/root/.dogtag/{{pki_instance_name}}/ca_admin.cert 46 | pki_admin_email=ocspadmin@{{ansible_domain}} 47 | pki_admin_name=ocspadmin 48 | pki_admin_nickname=ocspadmin 49 | pki_admin_password={{ocsp_password}} 50 | pki_admin_uid=ocspadmin 51 | pki_ds_base_dn=dc=ocsp,{{suffix}} 52 | pki_ds_database=ocsp 53 | -------------------------------------------------------------------------------- /ipa-tags.txt: -------------------------------------------------------------------------------- 1 | 2 | playbook: ansible/ipa-playbook.yml 3 | 4 | play #1 (all): install IPA base system TAGS: [] 5 | TASK TAGS: [bootstrap, common, custom-rpms, dummy, firewall, ipa, network, package-copr, package-install, package-upgrade, pki, setup] 6 | 7 | play #2 (ipaserver_master,ipaserver_replica): install IPA server system TAGS: [] 8 | TASK TAGS: [firewall, ipa-modnss, ipaserver, network, package-install] 9 | 10 | play #3 (ipaserver_master): install FreeIPA server master TAGS: [] 11 | TASK TAGS: [fetch, ipa-install, ipaserver-master] 12 | 13 | play #4 (ipaserver_master): create local inventory files TAGS: [] 14 | TASK TAGS: [fetch, ipa-install, ipa-inventory] 15 | 16 | play #5 (ipaserver_replica): install FreeIPA server replica TAGS: [] 17 | TASK TAGS: [fetch, ipa-client, ipa-install, ipaserver-replica] 18 | 19 | play #6 (ipa_client,ipa_nfsserver,ipa_smbserver,ipa_vpnserver,ipa_httpexample,ipa_ipsilon_idp,ipa_wwwdemo): install FreeIPA client TAGS: [] 20 | TASK TAGS: [ipa-client, ipa-install] 21 | 22 | play #7 (ipa_vpnserver): install OpenConnect VPN server for FreeIPA TAGS: [] 23 | TASK TAGS: [fetch, firewall, ipa-install, ipa-vpnserver, network, package-install] 24 | 25 | play #8 (ipa_nfsserver): install FreeIPA NFS server TAGS: [] 26 | TASK TAGS: [firewall, ipa-install, ipa-nfs-homedirs, ipa-nfsserver, network, package-install] 27 | 28 | play #9 (ipa_smbserver): install FreeIPA Samba server TAGS: [] 29 | TASK TAGS: [firewall, ipa-install, ipa-smbserver, network, package-install] 30 | 31 | play #10 (ipa_httpexample): install FreeIPA HTTP example app TAGS: [] 32 | TASK TAGS: [firewall, ipa-http, ipa-httpd, ipa-httpexample, ipa-install, ipa-modnss, network, package-install] 33 | 34 | play #11 (ipa_ipsilon_idp): install Ipsilon Identity Provider TAGS: [] 35 | TASK TAGS: [firewall, ipa-http, ipa-httpd, ipa-install, ipa-ipsilon-idp, ipa-modnss, network, package-install] 36 | 37 | play #12 (ipa_sp_example): install Ipsilon SP example TAGS: [] 38 | TASK TAGS: [firewall, ipa-http, ipa-httpd, ipa-install, ipa-modnss, ipa-sp-example, network, package-install] 39 | 40 | play #13 (ipa_wwwdemo): install WWW demo TAGS: [] 41 | TASK TAGS: [firewall, ipa-install, ipa-modssk, ipa-modssl, ipa-wwwdemo, ipa-wwwdemo-undeploy, network, package-install] 42 | 43 | play #14 (ipa_tests): Create integration test files TAGS: [] 44 | TASK TAGS: [ipa-tests] 45 | 46 | play #15 (all): Tidy up TAGS: [] 47 | TASK TAGS: [ipa-install, ipa-tidy] 48 | -------------------------------------------------------------------------------- /ipa/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.require_version ">= 1.6.0" 5 | 6 | DOMAIN="ipa.example" 7 | INSTALL_IDP = true 8 | INSTALL_NFS = false 9 | INSTALL_VPN = false 10 | 11 | HERE = File.dirname(__FILE__) 12 | ENV['ANSIBLE_CONFIG'] = "#{HERE}/../ansible/ansible.cfg" 13 | 14 | # Workaround for ssh problem with ED25519 curve 15 | # SSH not up: # ["ipamaster"], 83 | "ipaserver_replica" => ["ipareplica1"], 84 | "ipa_client" => ["ipaclient1"], 85 | "ipa_smbserver" => ["ipafileserver"], 86 | "ipa_httpexample" => ["ipafileserver"], 87 | } 88 | if INSTALL_NFS 89 | ansible.groups.update({ 90 | "ipa_nfsserver" => ["ipafileserver"], 91 | "ipa_nfsclient" => ["ipamaster", "ipareplica1", "ipaclient1"], 92 | }) 93 | end 94 | if INSTALL_IDP 95 | ansible.groups.update({ 96 | "ipa_ipsilon_idp" => ["ipaidpserver"], 97 | "ipa_sp_example" => ["ipafileserver"], 98 | }) 99 | end 100 | if INSTALL_VPN 101 | ansible.groups.update({ 102 | "ipa_vpnserver" => ["ipavpnserver"], 103 | }) 104 | end 105 | 106 | ansible.verbose = 'v' 107 | # network: Don't use network (no DNS forwarder, no package installations) 108 | # ipa-install: skip installation (ipa-server-install, ipa-client-install) 109 | ansible.skip_tags = [ 110 | #'network', 111 | #'ipa-install', 112 | 'dummy', 113 | ] 114 | # ansible.tags = ['bootstrap', 'common'] 115 | ansible.extra_vars = { 116 | "ipa_data_dir" => HERE + '/inventory', 117 | "ipa_script_dir" => HERE + '/bin', 118 | "ipa_rpm_dir" => HERE + '/rpms', 119 | # XXX SELinux policies for FreeIPA 4.5.0 are missing. 120 | "selinux_state" => 'permissive', 121 | "package_install" => false, 122 | "package_upgrade" => false, 123 | "custom_rpms" => false, 124 | "coprs_enabled" => [ 125 | # "@freeipa/freeipa-master", 126 | ], 127 | } 128 | end 129 | end 130 | end 131 | -------------------------------------------------------------------------------- /ipa/rpms/README: -------------------------------------------------------------------------------- 1 | Place your RPMs here 2 | 3 | Ansible will install all RPMS in this folder and any sub folder. You can 4 | even symlink files or directories into this folder. 5 | 6 | -------------------------------------------------------------------------------- /ipa/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | vagrant up --no-provision 5 | vagrant provision 6 | 7 | echo 8 | echo "Run 'bin/ipa_kinit admin' to acquire a Kerberos ticket" 9 | echo "The admin password is 'Secret123'" 10 | echo "The DM password is 'DMSecret456'" 11 | echo 12 | 13 | -------------------------------------------------------------------------------- /ipademo/demo.txt: -------------------------------------------------------------------------------- 1 | Before: 2 | 3 | * edit /etc/NetworkManager/dnsmasq.d/ipa.example.conf 4 | * systemctl reload NetworkManager 5 | * three konsole tabs: 6 | * . inventory/ipaenv 7 | * 1) ssh 8 | * 2) kdestroy / kinit 9 | * 3) ipa_firefox 10 | * bin/ipa_democheck 11 | * bin/ipa_firefox & 12 | 13 | ~/.ssh/config 14 | 15 | --- 16 | Host *.ipa.example 17 | GSSAPIAuthentication yes 18 | GSSAPIDelegateCredentials yes 19 | PreferredAuthentications gssapi-with-mic 20 | VerifyHostKeyDNS yes 21 | # pubkey auth slows us down 22 | PubkeyAuthentication no 23 | IdentitiesOnly yes 24 | IdentityFile /dev/null 25 | # don't use host key validation for the demo 26 | UserKnownHostsFile ~/.ssh/knownhosts_ipa 27 | # UserKnownHostsFile /dev/null 28 | StrictHostKeyChecking no 29 | --- 30 | 31 | Demo: 32 | 33 | * kinit admin 34 | * Firefox: master IPA 35 | * kinit cheimes 36 | * klist 37 | * bin/ipa_demossh 38 | * klist 39 | * demo: 40 | * ipa service-add HTTP/demo.ipa.example 41 | * sudo -s 42 | * kinit -kt /etc/krb5.keytab 43 | * /root/getkeytab.sh 44 | * /root/getcert.sh 45 | 46 | 47 | * /root/demostep.sh 1 48 | * firefox: demo.ipa.example 49 | * /root/demostep.sh 2 50 | * kdestroy 51 | * firefox: demo.ipa.example 52 | * kinit bob 53 | * firefox: demo.ipa.example 54 | * /root/demostep.sh 3 55 | * IPA: add user to webusers 56 | * firefox: demo.ipa.example 57 | * kdestroy 58 | * /root/demostep.sh 4 59 | * firefox: demo.ipa.example 60 | 61 | 62 | * /root/ocsp.sh 63 | * firefox: revoke certificate 64 | * /root/ocsp.sh 65 | * firefox: new private window: demo 66 | * /root/rekeycert.sh 67 | * firefox: new private window: demo 68 | 69 | * add OTP 70 | -------------------------------------------------------------------------------- /ipademo/rpms/README: -------------------------------------------------------------------------------- 1 | Place your RPMs here 2 | 3 | Ansible will install all RPMS in this folder and any sub folder. You can 4 | even symlink files or directories into this folder. 5 | 6 | -------------------------------------------------------------------------------- /ipademo/rpms/rpms: -------------------------------------------------------------------------------- 1 | /home/heimes/redhat/freeipa/dist/rpms -------------------------------------------------------------------------------- /ipademo/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | vagrant up --no-provision 5 | vagrant provision 6 | 7 | echo 8 | echo "Run 'bin/ipa_kinit admin' to acquire a Kerberos ticket" 9 | echo "The admin password is 'Secret123'" 10 | echo "The DM password is 'DMSecret456'" 11 | echo 12 | 13 | -------------------------------------------------------------------------------- /ipatests/.gitignore: -------------------------------------------------------------------------------- 1 | /inventory 2 | /bin 3 | -------------------------------------------------------------------------------- /ipatests/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.require_version ">= 1.6.0" 5 | 6 | HERE = File.dirname(__FILE__) 7 | ENV['ANSIBLE_CONFIG'] = "#{HERE}/../ansible/ansible.cfg" 8 | 9 | # Workaround for ssh problem with ED25519 curve 10 | # SSH not up: # ["ipatestmaster"], 42 | "ipa_tests" => ["ipatestmaster"], 43 | } 44 | ansible.verbose = 'vv' 45 | ansible.skip_tags = [ 46 | 'dummy', 47 | ] 48 | # ansible.tags = ['bootstrap', 'common', 'ipa-tests'] 49 | ansible.extra_vars = { 50 | "ipa_data_dir" => HERE + '/inventory', 51 | "ipa_script_dir" => HERE + '/bin', 52 | "ipa_rpm_dir" => HERE + '/rpms', 53 | "package_install" => false, 54 | "package_upgrade" => false, 55 | "custom_rpms" => false, 56 | "coprs_enabled" => [ 57 | # "@freeipa/freeipa-master", 58 | ], 59 | } 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /ipatests/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | vagrant up --no-provision 5 | vagrant provision 6 | 7 | mkdir -p ~/.ipa 8 | 9 | cat << EOF 10 | 11 | Now prepare the FreeIPA test enviroment: 12 | cp -ru ./inventory/dotipa/* ~/.ipa/ 13 | export KRB5_CONFIG=~/.ipa/krb5.conf 14 | export MASTER_env1=master.ipatests.local 15 | kinit admin 16 | EOF 17 | -------------------------------------------------------------------------------- /pki-tags.txt: -------------------------------------------------------------------------------- 1 | 2 | playbook: ansible/pki-playbook.yml 3 | 4 | play #1 (pki_server): install Dogtag PKI CA TAGS: [] 5 | TASK TAGS: [389ds, bootstrap, common, custom-rpms, dummy, firewall, ipa-install, network, package-copr, package-install, package-upgrade, pki, pki-install, pkica, pkikra, setup] 6 | -------------------------------------------------------------------------------- /pki/.gitignore: -------------------------------------------------------------------------------- 1 | /inventory 2 | -------------------------------------------------------------------------------- /pki/README: -------------------------------------------------------------------------------- 1 | rm -rf /etc/sysconfig/pki/tomcat/pki-tomcat-tests /etc/pki/pki-tomcat-tests /var/lib/pki/pki-tomcat-tests/ /var/log/pki/pki-tomcat-tests/ 2 | -------------------------------------------------------------------------------- /pki/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.require_version ">= 1.6.0" 5 | 6 | HERE = File.dirname(__FILE__) 7 | ENV['ANSIBLE_CONFIG'] = "#{HERE}/../ansible/ansible.cfg" 8 | # virtual env for Ansible 2 9 | # ENV['PATH'] = "#{HERE}/../venv/bin:" + ENV['PATH'] 10 | 11 | # Workaround for ssh problem with ED25519 curve 12 | # SSH not up: # ["pki_server"], 45 | } 46 | #ansible.verbose = 'vv' 47 | # pki-install: skip installation (setup-ds, pkispawn) 48 | ansible.skip_tags = [ 49 | #'pki-install', 50 | 'dummy', 51 | ] 52 | ansible.extra_vars = { 53 | "ipa_data_dir" => HERE + '/inventory', 54 | "ipa_script_dir" => HERE + '/bin', 55 | "ipa_rpm_dir" => HERE + '/rpms', 56 | "package_install" => false, 57 | "package_upgrade" => false, 58 | "coprs_enabled" => [], 59 | } 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /pki/rpms/README: -------------------------------------------------------------------------------- 1 | Place your RPMs here 2 | 3 | Ansible will install all RPMS in this folder and any sub folder. You can 4 | even symlink files or directories into this folder. 5 | 6 | -------------------------------------------------------------------------------- /pki/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | vagrant up --no-provision 5 | vagrant provision 6 | 7 | echo 8 | echo "Rrun 'bin/ipa_kinit admin' to acquire a Kerberos ticket" 9 | echo "The admin password is 'Secret123'" 10 | echo "The DM password is 'DMSecret456'" 11 | echo 12 | 13 | -------------------------------------------------------------------------------- /vagrantbuilder/.gitignore: -------------------------------------------------------------------------------- 1 | .atlas_token 2 | tmp/ 3 | basebox/ 4 | output/ 5 | -------------------------------------------------------------------------------- /vagrantbuilder/README: -------------------------------------------------------------------------------- 1 | vagrantbuilder 2 | -------------- 3 | 4 | Take a Fedora box and create a Vagrant box with updates and customizations. 5 | 6 | Atlas upload 7 | ------------ 8 | 9 | 1) Create new version 10 | 2) Create libvirt provider for the new version 11 | 3) Request an upload token 12 | $ curl "https://atlas.hashicorp.com/api/v1/box/cheimes/freeipa-f25/version/$VERSION/provider/libvirt/upload?access_token=$ATLAS_TOKEN" 13 | 4) Upload the box file: 14 | $ curl -o /dev/stdout -X PUT --upload-file freeipa-f25.box UPLOAD_PATH 15 | 5) Release the new version 16 | 17 | -------------------------------------------------------------------------------- /vagrantbuilder/scripts/ipa-firstboot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # bind-dyndb-ldap package sets named_write_master_zones=1 in its postin 4 | # script. Since virt-customize disables SELinux, the operation fails with 5 | # setsebool: SELinux is disabled. 6 | 7 | if [ -x /usr/sbin/setsebool ] && $(rpm -q bind-dyndb-ldap >/dev/null); then 8 | echo "setsebool named_write_master_zones=1 for bind-dyndb-ldap" 9 | /usr/sbin/setsebool -P named_write_master_zones=1 10 | fi 11 | -------------------------------------------------------------------------------- /vagrantbuilder/scripts/puiterwijk-ipsilon-epel-7.repo: -------------------------------------------------------------------------------- 1 | [puiterwijk-ipsilon] 2 | name=Copr repo for ipsilon owned by puiterwijk 3 | baseurl=https://copr-be.cloud.fedoraproject.org/results/puiterwijk/ipsilon/epel-7-$basearch/ 4 | type=rpm-md 5 | skip_if_unavailable=True 6 | gpgcheck=1 7 | gpgkey=https://copr-be.cloud.fedoraproject.org/results/puiterwijk/ipsilon/pubkey.gpg 8 | repo_gpgcheck=0 9 | enabled=1 10 | enabled_metadata=1 -------------------------------------------------------------------------------- /vagrantbuilder/scripts/vagrantsetup: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Modify a Fedora image for Vagrant 3 | # 4 | # Christian Heimes 5 | # 6 | set -e 7 | 8 | # On some systems cleanup seems to remove this directory. This causes 9 | # package install to fail with dangling symlink /var/lock. 10 | mkdir -p -m 0755 /run/lock 11 | 12 | # don't keep rescue kernel images 13 | cat > /etc/dracut.conf.d/norescue.conf << EOF 14 | dracut_rescue_image="no" 15 | EOF 16 | 17 | # limit installed kernel 18 | if [ -f /etc/yum.conf ]; then 19 | sed -i 's/^installonly_limit=.*/installonly_limit=2/' /etc/yum.conf 20 | fi 21 | if [ -f /etc/dnf/dnf.conf ]; then 22 | sed -i 's/^installonly_limit=.*/installonly_limit=2/' /etc/dnf/dnf.conf 23 | fi 24 | 25 | # harden sshd 26 | sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' \ 27 | /etc/ssh/sshd_config 28 | 29 | # remove old network interface 30 | # Vagrant / libvirt DHCP will take care of network 31 | rm -f /etc/sysconfig/network-scripts/ifcfg-eth* 32 | rm -f /etc/sysconfig/network-scripts/ifcfg-en* 33 | 34 | # Vagrant user and group 35 | getent group vagrant >/dev/null || groupadd --gid 1001 vagrant 36 | getent passwd vagrant >/dev/null || useradd \ 37 | --create-home \ 38 | --home-dir /home/vagrant \ 39 | --password '\$6\$Irp4RRc2RM9hETN0\$v.zFsy9PGLW1m3MKnUSHn3lQYJWcLls/TCo4XnFaE5U1IHO.eb.TrXx3NLBuHHZUwrzonh0.ZhqzU3tHPS5el1' \ 40 | --gid vagrant \ 41 | --uid 1001 \ 42 | --shell /bin/bash \ 43 | vagrant 44 | 45 | # ssh login for Vagrant user 46 | if [ ! -f ~vagrant/.ssh/authorized_keys ]; then 47 | mkdir -p -m 0700 ~vagrant/.ssh 48 | cat > ~vagrant/.ssh/authorized_keys << EOF 49 | ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key 50 | EOF 51 | chmod 0600 ~vagrant/.ssh/authorized_keys 52 | chown -R vagrant:vagrant ~vagrant/ 53 | restorecon -Rv ~vagrant/.ssh || true 54 | fi 55 | 56 | # sudoers for Vagrant user 57 | cat > /etc/sudoers.d/vagrant-nopasswd << EOF 58 | vagrant ALL=NOPASSWD: ALL 59 | Defaults:vagrant !requiretty 60 | EOF 61 | chmod 600 /etc/sudoers.d/vagrant-nopasswd 62 | restorecon -Rv /etc/sudoers.d || true 63 | 64 | exit 0 65 | --------------------------------------------------------------------------------