Apply non-core changes in CORD-912 to master
remove vestigial templates
create admin-openrc.sh in cord_profile_dir and home dir
Change-Id: I52a7cef1ea9e0dc7a37d9888fcfdc093434777ef
diff --git a/roles/dhcpd/defaults/main.yml b/roles/dhcpd/defaults/main.yml
new file mode 100644
index 0000000..b1fd226
--- /dev/null
+++ b/roles/dhcpd/defaults/main.yml
@@ -0,0 +1,27 @@
+---
+# dhcpd/defaults/main.yml
+
+dns_search: []
+dns_servers: []
+
+# http://serverfault.com/questions/40712/what-range-of-mac-addresses-can-i-safely-use-for-my-virtual-machines
+hwaddr_prefix: "c2a4"
+
+dhcpd_subnets: []
+
+# example dhcpd_subnets:
+#
+# dhcpd_subnets:
+# - interface: eth1
+# cidr: 192.168.200.1/24
+# dhcp_first: 129
+# dhcp_last: 254
+# tftp_server: 192.168.200.1
+# static_nodes:
+# - name: node1
+# ipv4_last_octet: 30
+# filename: boot.tftp
+# other_static:
+# - head_lxd_list
+
+
diff --git a/roles/dhcpd/handlers/main.yml b/roles/dhcpd/handlers/main.yml
new file mode 100644
index 0000000..38a25c5
--- /dev/null
+++ b/roles/dhcpd/handlers/main.yml
@@ -0,0 +1,8 @@
+---
+# dhcpd/handlers/main.yml
+
+- name: restart-dhcpd
+ service:
+ name: isc-dhcp-server
+ state: restarted
+
diff --git a/roles/dhcpd/tasks/main.yml b/roles/dhcpd/tasks/main.yml
new file mode 100644
index 0000000..8c103de
--- /dev/null
+++ b/roles/dhcpd/tasks/main.yml
@@ -0,0 +1,32 @@
+---
+# dhcpd/tasks/main.yml
+
+- name: Install dhcpd
+ apt:
+ name: "{{ item }}"
+ update_cache: yes
+ cache_valid_time: 3600
+ with_items:
+ - isc-dhcp-server
+
+- name: Create /etc/dhcp/dhcpd.conf from template
+ template:
+ src: dhcpd.conf.j2
+ dest: /etc/dhcp/dhcpd.conf
+ mode: "0644"
+ owner: root
+ group: root
+ # validate: 'dhcpd -t -cf %s'
+ notify:
+ - restart-dhcpd
+
+- name: Set interfaces for dhcpd to listen on
+ template:
+ src: isc-dhcp-server.j2
+ dest: /etc/default/isc-dhcp-server
+ mode: "0644"
+ owner: root
+ group: root
+ notify:
+ - restart-dhcpd
+
diff --git a/roles/dhcpd/templates/dhcpd.conf.j2 b/roles/dhcpd/templates/dhcpd.conf.j2
new file mode 100644
index 0000000..bbf9d8b
--- /dev/null
+++ b/roles/dhcpd/templates/dhcpd.conf.j2
@@ -0,0 +1,65 @@
+# dhcpd.conf
+# Managed by Ansible!
+
+{% if dns_search %}
+option domain-name "{{ dns_search[0] }}";
+option domain-search "{{ dns_search | join('", "') }}";
+{% endif %}
+
+{% if dns_servers %}
+option domain-name-servers {{ dns_servers | join(", ") }};
+{% endif %}
+
+{% for subnet in dhcpd_subnets %}
+subnet {{ subnet.cidr | ipaddr('network') }} netmask {{ subnet.cidr | ipaddr('netmask') }} {
+ option routers {{ subnet.router | default(subnet.cidr | ipaddr('1') | ipaddr('address')) }};
+ range {{ subnet.cidr | ipaddr(subnet.dhcp_first | default("129")) | ipaddr('address') }} {{ subnet.cidr | ipaddr(subnet.dhcp_last | default("254")) | ipaddr('address') }};
+{% if subnet.dns_search is defined %}
+ option domain-name {{ subnet.dns_search [0] }};
+ option domain-search {{ subnet.dns_search| join(", ") }};
+{% endif %}
+{% if subnet.dns_servers is defined %}
+ option domain-name-servers {{ subnet.dns_servers | join(", ") }};
+{% endif %}
+ default-lease-time {{ subnet.lease_time | default("240") }};
+ max-lease-time {{ subnet.max_lease_time | default("480") }};
+{% if subnet.pxe_filename is defined %}
+ filename "{{ subnet.pxe_filename }}";
+ next-server {{ subnet.tftp_server | default(subnet.cidr | ipaddr('1') | ipaddr('address')) }};
+{% endif %}
+{% if subnet.static_nodes is defined %}
+ # hosts from list: static_nodes
+{% for node in subnet.static_nodes %}
+ host {{ node.name }} {
+ option host-name "{{ node.name }}";
+{% set host_ipaddr = (subnet.cidr | ipaddr(node.ipv4_last_octet) | ipaddr('address')) %}
+ fixed-address {{ host_ipaddr }};
+ hardware ethernet {{ node.hwaddr | default(hwaddr_prefix ~ (host_ipaddr | ip4_hex)) | hwaddr('unix') }};
+{% if node.pxe_filename is defined %}
+ filename "{{ node.pxe_filename }}";
+ next-server {{ subnet.tftp_server | default(subnet.cidr | ipaddr('1') | ipaddr('address')) }};
+{% endif %}
+ }
+{% endfor %}
+{% endif %}
+{% if subnet.other_static is defined %}
+{% for hostlist in subnet.other_static %}
+ # hosts from list: {{ hostlist }}
+{% set nodes = vars[hostlist] %}
+{% for node in nodes %}
+ host {{ node.name }} {
+ option host-name "{{ node.name }}";
+{% set host_ipaddr = (subnet.cidr | ipaddr(node.ipv4_last_octet) | ipaddr('address')) %}
+ fixed-address {{ host_ipaddr }};
+ hardware ethernet {{ node.hwaddr | default(hwaddr_prefix ~ (host_ipaddr | ip4_hex)) | hwaddr('unix') }};
+{% if node.pxe_filename is defined %}
+ filename "{{ subnet.pxe_filename }}";
+ next-server {{ subnet.tftp_server | default(subnet.cidr | ipaddr('1') | ipaddr('address')) }};
+{% endif %}
+ }
+{% endfor %}
+{% endfor %}
+{% endif %}
+}
+
+{% endfor %}
diff --git a/roles/dhcpd/templates/isc-dhcp-server.j2 b/roles/dhcpd/templates/isc-dhcp-server.j2
new file mode 100644
index 0000000..98efb1d
--- /dev/null
+++ b/roles/dhcpd/templates/isc-dhcp-server.j2
@@ -0,0 +1,22 @@
+# Defaults for isc-dhcp-server initscript
+# sourced by /etc/init.d/isc-dhcp-server
+# installed at /etc/default/isc-dhcp-server by the maintainer scripts
+
+#
+# This is a POSIX shell fragment
+#
+
+# Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf).
+#DHCPD_CONF=/etc/dhcp/dhcpd.conf
+
+# Path to dhcpd's PID file (default: /var/run/dhcpd.pid).
+#DHCPD_PID=/var/run/dhcpd.pid
+
+# Additional options to start dhcpd with.
+# Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead
+#OPTIONS=""
+
+# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
+# Separate multiple interfaces with spaces, e.g. "eth0 eth1".
+INTERFACES="{{ dhcpd_subnets | map(attribute='interface') | join(' ') }}"
+
diff --git a/roles/dns-configure/defaults/main.yml b/roles/dns-configure/defaults/main.yml
index defbf98..0101eb7 100644
--- a/roles/dns-configure/defaults/main.yml
+++ b/roles/dns-configure/defaults/main.yml
@@ -9,3 +9,5 @@
# Set this to search domain suffixes
# dns_search: {}
+unbound_listen_on_default: False
+
diff --git a/roles/dns-configure/tasks/main.yml b/roles/dns-configure/tasks/main.yml
index 07b0d5d..792748e 100644
--- a/roles/dns-configure/tasks/main.yml
+++ b/roles/dns-configure/tasks/main.yml
@@ -1,15 +1,34 @@
---
# roles/dns-configure/tasks.yml
-- name: Configure resolv.conf to use nameservers
+- name: Make sure resolvconf is doing DNS resolver mangling
+ apt:
+ name: resolvconf
+ update_cache: yes
+ cache_valid_time: 3600
+
+- name: Create resolvconf configuration files
template:
- src="resolv.conf.j2"
- dest="/etc/resolv.conf"
- mode=0644 owner=root group=root
+ src: "{{ item }}.j2"
+ dest: "/etc/resolvconf/resolv.conf.d/{{ item }}"
+ mode: 0644
+ owner: root
+ group: root
+ with_items:
+ - base
+ - head
+ register: resolvconf_configured
+
+- name: Tell resolvconf to refresh /etc/resolv.conf file if changed
+ become: yes
+ command: resolvconf -u
+ when: resolvconf_configured.changed
+ tags:
+ - skip_ansible_lint # needs to run before the DNS check which happens next, so can't be a handler
- name: Check that VM's can be found in DNS
shell: "dig +short {{ item.name }}.{{ site_suffix }} | grep {{ item.ipv4_last_octet }}"
- with_items: "{{ head_vm_list }}"
+ with_items: "{{ head_lxd_list }}"
tags:
- skip_ansible_lint # purely a way to pass/fail config done so far. Ansible needs a "dns_query" module
diff --git a/roles/dns-configure/templates/base.j2 b/roles/dns-configure/templates/base.j2
new file mode 100644
index 0000000..7eadcf1
--- /dev/null
+++ b/roles/dns-configure/templates/base.j2
@@ -0,0 +1,3 @@
+{% if dns_search is defined %}
+search{% for searchdom in dns_search %} {{ searchdom }}{% endfor %}
+{% endif %}
diff --git a/roles/dns-configure/templates/head.j2 b/roles/dns-configure/templates/head.j2
new file mode 100644
index 0000000..f19e8cc
--- /dev/null
+++ b/roles/dns-configure/templates/head.j2
@@ -0,0 +1,14 @@
+# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
+# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
+# Make changes to /etc/resolvconf/resolv.conf.d instead
+# Modified by Ansible
+{% if unbound_listen_on_default %}
+{% for host in groups['head'] %}
+nameserver {{ hostvars[host].ansible_default_ipv4.address }}
+{% endfor %}
+{% endif %}
+{% if dns_servers is defined %}
+{% for ns in dns_servers %}
+nameserver {{ ns }}
+{% endfor %}
+{% endif %}
diff --git a/roles/dns-nsd/templates/nsd.conf.j2 b/roles/dns-nsd/templates/nsd.conf.j2
index 29ba41a..46813bb 100644
--- a/roles/dns-nsd/templates/nsd.conf.j2
+++ b/roles/dns-nsd/templates/nsd.conf.j2
@@ -12,7 +12,7 @@
zonesdir: {{ nsd_zonesdir }}
remote-control:
- control-enable: yes
+ control-enable: no
# zones to load
{% for zone in nsd_zones %}
diff --git a/roles/dns-nsd/templates/zone.forward.j2 b/roles/dns-nsd/templates/zone.forward.j2
index 895d8a3..129fa7c 100644
--- a/roles/dns-nsd/templates/zone.forward.j2
+++ b/roles/dns-nsd/templates/zone.forward.j2
@@ -1,5 +1,6 @@
;## NSD authoritative only DNS
;## FORWARD Zone
+;# created by ansible
$ORIGIN {{ item.name }}. ; default zone domain
$TTL {{ item.ttl | default(dns_ttl) }} ; default time to live
@@ -27,8 +28,9 @@
{% endfor %}
{% endif %}
-; Set from list of nodes
-{% set nodes = vars[item.nodelist] %}
+{% for nodelist in item.nodelists %}
+; Created from nodelist: {{ nodelist }}
+{% set nodes = vars[nodelist] %}
{% for node in nodes %}
{{ node.name }} IN A {{ item.ipv4_first_octets ~ "." ~ node.ipv4_last_octet }}
{% if node.aliases is defined %}
@@ -37,4 +39,5 @@
{% endfor %}
{% endif %}
{% endfor %}
+{% endfor %}
diff --git a/roles/dns-nsd/templates/zone.reverse.j2 b/roles/dns-nsd/templates/zone.reverse.j2
index f327d4b..1ebdcd3 100644
--- a/roles/dns-nsd/templates/zone.reverse.j2
+++ b/roles/dns-nsd/templates/zone.reverse.j2
@@ -1,10 +1,10 @@
;## NSD authoritative only DNS
;## REVERSE Zone for {{ item.name }}
+;# created by ansible
$ORIGIN {{ item.name }}. ; default zone domain
$TTL {{ item.ttl | default(dns_ttl) }} ; default time to live
-
{{ (item.ipv4_first_octets ~ ".0") | ipaddr('revdns') | regex_replace('^0\.','') }} IN SOA {{ item.soa }}.{{ item.name }}. admin.{{ item.name }}. (
{{ item.serial | default(ansible_date_time.epoch) }} ; Serial, must be incremented every time you change this file
3600 ; Refresh [1hr]
@@ -13,9 +13,13 @@
60 ; Min TTL [1m]
)
-{% set nodes = vars[item.nodelist] %}
+; -- PTR records --
-;PTR records
+{% for nodelist in item.nodelists %}
+; Created from nodelist: {{ nodelist }}
+{% set nodes = vars[nodelist] %}
{% for node in nodes %}
{{ (item.ipv4_first_octets ~ "." ~ node.ipv4_last_octet) | ipaddr('revdns') }} IN PTR {{ node.name }}
{% endfor %}
+{% endfor %}
+
diff --git a/roles/dns-unbound/defaults/main.yml b/roles/dns-unbound/defaults/main.yml
index d0553b1..c462ba0 100644
--- a/roles/dns-unbound/defaults/main.yml
+++ b/roles/dns-unbound/defaults/main.yml
@@ -1,5 +1,11 @@
---
+# dns-unbound/defaults/main.yml
unbound_conf: "/var/unbound/etc/unbound.conf"
unbound_group: "wheel"
+unbound_listen_on_default: False
+
+unbound_listen_all: False
+
+unbound_interfaces: []
diff --git a/roles/dns-unbound/templates/unbound.conf.j2 b/roles/dns-unbound/templates/unbound.conf.j2
index ff5ccbd..d82a45f 100644
--- a/roles/dns-unbound/templates/unbound.conf.j2
+++ b/roles/dns-unbound/templates/unbound.conf.j2
@@ -18,6 +18,11 @@
# allow from localhost
access-control: 127.0.0.0/24 allow
+{% if unbound_listen_all %}
+ # allow from everywhere
+ access-control: 0.0.0.0/0 allow
+{% endif %}
+
{% if unbound_listen_on_default %}
# allow from default interfaces
access-control: {{ ansible_default_ipv4.address }}/{{ (ansible_default_ipv4.address ~ "/" ~ ansible_default_ipv4.netmask) | ipaddr('prefix') }} allow
@@ -26,7 +31,7 @@
{% if unbound_interfaces is defined %}
# allow from local networks
{% for cidr_ipv4 in unbound_interfaces %}
- access-control: {{ cidr_ipv4 }} allow
+ access-control: {{ cidr_ipv4 | ipaddr('0') }} allow
{% endfor %}
{% endif %}
diff --git a/roles/interface-config/defaults/main.yml b/roles/interface-config/defaults/main.yml
new file mode 100644
index 0000000..f9056b0
--- /dev/null
+++ b/roles/interface-config/defaults/main.yml
@@ -0,0 +1,9 @@
+---
+# interface-config/defaults/main.yml
+
+mgmt_interface: eth1
+
+mgmt_ipv4_first_octets: "192.168.200"
+
+physical_node_list: []
+
diff --git a/roles/interface-config/tasks/main.yml b/roles/interface-config/tasks/main.yml
new file mode 100644
index 0000000..3954696
--- /dev/null
+++ b/roles/interface-config/tasks/main.yml
@@ -0,0 +1,18 @@
+---
+# interface-config/tasks/main.yml
+
+- name: Create network interface for management network
+ template:
+ src: eth.cfg.j2
+ dest: "/etc/network/interfaces.d/{{ mgmt_interface }}.cfg"
+ owner: root
+ group: root
+ mode: 0644
+ register: mgmtint_config
+
+- name: Bring up management network if reconfigured
+ when: mgmtint_config.changed
+ command: "ifup {{ mgmt_interface }}"
+ tags:
+ - skip_ansible_lint # needs to be run before next steps
+
diff --git a/roles/interface-config/templates/eth.cfg.j2 b/roles/interface-config/templates/eth.cfg.j2
new file mode 100644
index 0000000..2376335
--- /dev/null
+++ b/roles/interface-config/templates/eth.cfg.j2
@@ -0,0 +1,12 @@
+{% for node in physical_node_list if node.name == ansible_hostname %}
+auto {{ node.interface | default(mgmt_interface) }}
+
+iface {{ node.interface | default(mgmt_interface) }} inet static
+ address {{ mgmt_ipv4_first_octets }}.{{ node.ipv4_last_octet }}
+ network {{ mgmt_ipv4_first_octets }}.0
+ netmask 255.255.255.0
+ broadcast {{ mgmt_ipv4_first_octets }}.255
+{% if node.gateway_enabled is defined and node.gateway_enabled %}
+ gateway {{ mgmt_ipv4_first_octets }}.1
+{% endif %}
+{% endfor %}
diff --git a/roles/juju-compute-setup/tasks/main.yml b/roles/juju-compute-setup/tasks/main.yml
index d061697..f4e3918 100644
--- a/roles/juju-compute-setup/tasks/main.yml
+++ b/roles/juju-compute-setup/tasks/main.yml
@@ -9,12 +9,6 @@
# list of active juju_machines names: juju_machines.keys()
# list of active juju_services names: juju_services.keys()
-# FIXME: Need to add firewall rules to head node or compute machines won't be
-# able to talk to head node VM's. iptables cmd's look like this:
-#
-# iptables -A FORWARD -i eth0 -o mgmtbr -s <extnet> -d <vmnet> -j ACCEPT
-# iptables -A FORWARD -i mgmtbr -o eth0 -s <vmnet> -d <extnet> -j ACCEPT
-
- name: Add machines to Juju
when: "{{ groups['compute'] | difference( juju_machines.keys() ) | length }}"
command: "juju add-machine ssh:{{ item }}"
@@ -56,20 +50,20 @@
prompt="Waiting for Juju..."
seconds=20
-# 160*15s = 2400s = 40m max wait
+# 100*30s = 3000s = 50m max wait
- name: Wait for nova-compute nodes to come online
juju_facts:
until: item in juju_compute_nodes.keys() and juju_compute_nodes[item]['workload-status']['message'] == "Unit is ready"
- retries: 160
- delay: 15
+ retries: 100
+ delay: 30
with_items: "{{ groups['compute'] }}"
- name: verify that the nodes appear in nova
action: shell bash -c "source ~/admin-openrc.sh; nova hypervisor-list | grep '{{ item }}'"
register: result
until: result | success
- retries: 10
- delay: 10
+ retries: 20
+ delay: 15
with_items: "{{ groups['compute'] }}"
tags:
- skip_ansible_lint # this really should be the os_server module, but ansible doesn't know about juju created openstack
diff --git a/roles/juju-finish/tasks/main.yml b/roles/juju-finish/tasks/main.yml
index e173e0c..6a8c8a0 100644
--- a/roles/juju-finish/tasks/main.yml
+++ b/roles/juju-finish/tasks/main.yml
@@ -29,10 +29,3 @@
tags:
- skip_ansible_lint # checking/waiting on a system to be up
-- name: Create admin-openrc.sh credentials file
- template:
- src=admin-openrc.sh.j2
- dest="{{ item }}/admin-openrc.sh"
- with_items:
- - "{{ ansible_user_dir }}"
- - "{{ cord_profile_dir }}"
diff --git a/roles/juju-setup/tasks/main.yml b/roles/juju-setup/tasks/main.yml
index 69b13bf..159bd1b 100644
--- a/roles/juju-setup/tasks/main.yml
+++ b/roles/juju-setup/tasks/main.yml
@@ -41,7 +41,7 @@
- name: Check that Juju is actually ready
juju_facts:
- until: juju_machines["juju.cord.lab"] is defined and juju_machines["juju.cord.lab"]["agent_state"] == "started"
+ until: 'juju_machines["juju.{{ site_suffix }}"] is defined and juju_machines["juju.{{ site_suffix }}"]["agent_state"] == "started"'
retries: 40
delay: 15
@@ -66,12 +66,12 @@
retries: 3
delay: 15
-- name: Deploy services that are hosted in their own VM
+- name: Deploy services that are hosted in their own LXD container
when: "{{ lxd_service_list | difference( juju_services.keys() ) | length }}"
command: "juju deploy {{ charm_versions[item] | default(item) }} --to {{ juju_machines[item~'.'~site_suffix]['machine_id'] }} --config={{ juju_config_path }}"
with_items: "{{ lxd_service_list | difference( juju_services.keys() ) }}"
-- name: Deploy services that don't have their own VM
+- name: Deploy services that don't have their own container
when: "{{ standalone_service_list | difference( juju_services.keys() ) | length }}"
command: "juju deploy {{ charm_versions[item] | default(item) }} --config={{ juju_config_path }}"
with_items: "{{ standalone_service_list | difference( juju_services.keys() ) }}"
@@ -85,3 +85,12 @@
- relations
tags:
- skip_ansible_lint # benign to do this more than once, hard to check for
+
+- name: Create admin-openrc.sh OpenStack credentials file
+ template:
+ src: admin-openrc.sh.j2
+ dest: "{{ item }}/admin-openrc.sh"
+ with_items:
+ - "{{ ansible_user_dir }}"
+ - "{{ cord_profile_dir }}"
+
diff --git a/roles/juju-finish/templates/admin-openrc.sh.j2 b/roles/juju-setup/templates/admin-openrc.sh.j2
similarity index 100%
rename from roles/juju-finish/templates/admin-openrc.sh.j2
rename to roles/juju-setup/templates/admin-openrc.sh.j2
diff --git a/roles/pki-cert/defaults/main.yml b/roles/pki-cert/defaults/main.yml
index bbd9c5f..4d55149 100644
--- a/roles/pki-cert/defaults/main.yml
+++ b/roles/pki-cert/defaults/main.yml
@@ -5,6 +5,7 @@
cert_digest: "sha256"
cert_days: 180
-# list of server certificates to create
+# lists of certificates to create
server_certs: []
+client_certs: []
diff --git a/roles/pki-cert/tasks/main.yml b/roles/pki-cert/tasks/main.yml
index f162f2f..b7cbdd3 100644
--- a/roles/pki-cert/tasks/main.yml
+++ b/roles/pki-cert/tasks/main.yml
@@ -43,12 +43,12 @@
with_items: "{{ server_certs }}"
tags:
- skip_ansible_lint # diagnostic command
- register: chain_verify
+ register: server_chain_verify
- name: Assert that verify of cert succeeded
assert:
that: "'OK' in '{{ item.stdout }}'"
- with_items: "{{ chain_verify.results }}"
+ with_items: "{{ server_chain_verify.results }}"
- name: Get the intermediate cert into im_cert var
command: >
@@ -57,7 +57,7 @@
tags:
- skip_ansible_lint # concat of files
-- name: Get the cert into server_cert var
+- name: Get the certs into server_certs var
command: >
openssl x509 -in {{ pki_dir }}/intermediate_ca/certs/{{ item.cn }}_cert.pem
with_items: "{{ server_certs }}"
@@ -65,9 +65,72 @@
- skip_ansible_lint # concat of files
register: server_certs_raw
-- name: Create chained server cert
+- name: Create chained server certs
copy:
dest: "{{ pki_dir }}/intermediate_ca/certs/{{ item.item.cn }}_cert_chain.pem"
content: "{{ item.stdout }}\n{{ im_cert.stdout }}"
with_items: "{{ server_certs_raw.results }}"
+- name: Generate client private key (no pw)
+ command: >
+ openssl genrsa
+ -out {{ pki_dir }}/intermediate_ca/private/{{ item.cn }}_key.pem
+ args:
+ creates: "{{ pki_dir }}/intermediate_ca/private/{{ item.cn }}_key.pem"
+ with_items: "{{ client_certs }}"
+
+- name: Generate client CSR
+ command: >
+ openssl req -config {{ pki_dir }}/intermediate_ca/openssl.cnf
+ -key {{ pki_dir }}/intermediate_ca/private/{{ item.cn }}_key.pem
+ -new -sha256 -subj "{{ item.subj }}"
+ -out {{ pki_dir }}/intermediate_ca/csr/{{ item.cn }}_csr.pem
+ args:
+ creates: "{{ pki_dir }}/intermediate_ca/csr/{{ item.cn }}_csr.pem"
+ environment:
+ KEY_ALTNAMES: "{{ item.altnames | join(', ') }}"
+ with_items: "{{ client_certs }}"
+
+- name: Sign client cert
+ command: >
+ openssl ca -config {{ pki_dir }}/intermediate_ca/openssl.cnf -batch
+ -passin file:{{ pki_dir }}/intermediate_ca/private/ca_im_phrase
+ -extensions user_cert
+ -days {{ cert_days }} -md {{ cert_digest }}
+ -in {{ pki_dir }}/intermediate_ca/csr/{{ item.cn }}_csr.pem
+ -out {{ pki_dir }}/intermediate_ca/certs/{{ item.cn }}_cert.pem
+ args:
+ creates: "{{ pki_dir }}/intermediate_ca/certs/{{ item.cn }}_cert.pem"
+ environment:
+ KEY_ALTNAMES: "{{ item.altnames | join(', ') }}"
+ with_items: "{{ client_certs }}"
+
+- name: Verify cert against root + im chain
+ command: >
+ openssl verify -purpose sslclient
+ -CAfile {{ pki_dir }}/intermediate_ca/certs/im_cert_chain.pem
+ {{ pki_dir }}/intermediate_ca/certs/{{ item.cn }}_cert.pem
+ with_items: "{{ client_certs }}"
+ tags:
+ - skip_ansible_lint # diagnostic command
+ register: client_chain_verify
+
+- name: Assert that verify of cert succeeded
+ assert:
+ that: "'OK' in '{{ item.stdout }}'"
+ with_items: "{{ client_chain_verify.results }}"
+
+- name: Get the certs into client_certs var
+ command: >
+ openssl x509 -in {{ pki_dir }}/intermediate_ca/certs/{{ item.cn }}_cert.pem
+ with_items: "{{ client_certs }}"
+ tags:
+ - skip_ansible_lint # concat of files
+ register: client_certs_raw
+
+- name: Create chained client cert
+ copy:
+ dest: "{{ pki_dir }}/intermediate_ca/certs/{{ item.item.cn }}_cert_chain.pem"
+ content: "{{ item.stdout }}\n{{ im_cert.stdout }}"
+ with_items: "{{ client_certs_raw.results }}"
+
diff --git a/roles/pki-intermediate-ca/defaults/main.yml b/roles/pki-intermediate-ca/defaults/main.yml
index feecca8..c8ec9c9 100644
--- a/roles/pki-intermediate-ca/defaults/main.yml
+++ b/roles/pki-intermediate-ca/defaults/main.yml
@@ -10,7 +10,7 @@
ca_im_days: 730
# passphrases for the certificate
-ca_im_phrase: "{{ lookup('password', credentials_dir+'/ca_im_phrase length=64') }}"
+ca_im_phrase: "{{ lookup('password', credentials_dir ~ '/ca_im_phrase length=64') }}"
# noninteractive csr subject
ca_im_subj: "/C=US/ST=California/L=Menlo Park/O=ON.Lab/OU=Test Deployment/CN=CORD Test Deployment Intermediate CA"
diff --git a/roles/pki-root-ca/defaults/main.yml b/roles/pki-root-ca/defaults/main.yml
index 8f6888c..9fc4952 100644
--- a/roles/pki-root-ca/defaults/main.yml
+++ b/roles/pki-root-ca/defaults/main.yml
@@ -10,7 +10,7 @@
ca_root_days: 3650
# passphrases for the key
-ca_root_phrase: "{{ lookup('password', credentials_dir+'/ca_root_phrase length=64') }}"
+ca_root_phrase: "{{ lookup('password', credentials_dir ~ '/ca_root_phrase length=64') }}"
# noninteractive csr subject
ca_root_subj: "/C=US/ST=California/L=Menlo Park/O=ON.Lab/OU=Test Deployment/CN=CORD Test Deployment Root CA"
diff --git a/roles/ssh-pki/defaults/main.yml b/roles/ssh-pki/defaults/main.yml
new file mode 100644
index 0000000..1e8574e
--- /dev/null
+++ b/roles/ssh-pki/defaults/main.yml
@@ -0,0 +1,20 @@
+---
+# ssh-pki/tasks/main.yml
+
+pki_dir: "/opt/pki"
+ssh_pki_dir: "/opt/ssh_pki"
+credentials_dir: "/opt/credentials"
+
+# password on SSH CA
+ssh_ca_phrase: "{{ lookup('password', credentials_dir ~ '/ssh_ca_phrase length=64') }}"
+
+# ssh-keygen parameters
+ssh_keytype: rsa
+ssh_keysize: 4096
+
+# lists of keys to generate
+ssh_client_genkeys:
+ - name: headnode
+
+ssh_host_genkeys: []
+
diff --git a/roles/ssh-pki/tasks/main.yml b/roles/ssh-pki/tasks/main.yml
new file mode 100644
index 0000000..44dbe64
--- /dev/null
+++ b/roles/ssh-pki/tasks/main.yml
@@ -0,0 +1,76 @@
+---
+# ssh-pki/tasks/main.yml
+
+- name: Create SSH CA Directory
+ file:
+ dest: "{{ item }}"
+ state: directory
+ owner: "{{ ansible_user_id }}"
+ mode: 0700
+ with_items:
+ - "{{ ssh_pki_dir }}"
+ - "{{ ssh_pki_dir }}/ca"
+ - "{{ ssh_pki_dir }}/client_certs"
+ - "{{ ssh_pki_dir }}/host_certs"
+
+- name: Generate SSH CA Cert
+ command: >
+ ssh-keygen
+ -q -N "{{ ssh_ca_phrase }}"
+ -t {{ ssh_keytype }}
+ -b {{ ssh_keysize }}
+ -C "CORD SSH CA"
+ -f {{ ssh_pki_dir }}/ca/cord_ssh_ca_cert
+ args:
+ creates: "{{ ssh_pki_dir }}/ca/cord_ssh_ca_cert.pub"
+
+- name: Generate SSH Client Certs
+ command: >
+ ssh-keygen
+ -q -N ""
+ -t {{ item.keytype | default(ssh_keytype) }}
+ -b {{ item.keysize | default(ssh_keysize) }}
+ -C "CORD SSH client key for {{ item.name }}"
+ -f {{ ssh_pki_dir }}/client_certs/{{ item.name }}_sshkey
+ args:
+ creates: "{{ ssh_pki_dir }}/client_certs/{{ item.name }}_sshkey.pub"
+ with_items: "{{ ssh_client_genkeys }}"
+ register: client_ssh_key_generated
+
+- name: Sign SSH Client Certs with SSH CA
+ command: >
+ ssh-keygen
+ -q -P "{{ ssh_ca_phrase }}"
+ -I "{{ item.name }}"
+ -n "{{ item.name }}"
+ -s {{ ssh_pki_dir }}/ca/cord_ssh_ca_cert
+ {{ ssh_pki_dir }}/client_certs/{{ item.name }}_sshkey.pub
+ args:
+ creates: "{{ ssh_pki_dir }}/client_certs/{{ item.name }}_sshkey-cert.pub"
+ with_items: "{{ ssh_client_genkeys }}"
+
+- name: Generate SSH Host Certs
+ command: >
+ ssh-keygen
+ -q -N ""
+ -t {{ item.keytype | default(ssh_keytype) }}
+ -b {{ item.keysize | default(ssh_keysize) }}
+ -C "CORD SSH host key for {{ item.name }}"
+ -f {{ ssh_pki_dir }}/host_certs/{{ item.name }}_sshkey
+ args:
+ creates: "{{ ssh_pki_dir }}/host_certs/{{ item.name }}_sshkey.pub"
+ with_items: "{{ ssh_host_genkeys }}"
+ register: host_ssh_keys_generated
+
+- name: Generate SSH Host Certs
+ command: >
+ ssh-keygen
+ -q -P "{{ ssh_ca_phrase }}" -h
+ -I "{{ item.name }}"
+ -n "{{ item.name }},{{ item.name }}.{{ site_suffix }}"
+ -s {{ ssh_pki_dir }}/ca/cord_ssh_ca_cert
+ {{ ssh_pki_dir }}/host_certs/{{ item.name }}_sshkey.pub
+ args:
+ creates: "{{ ssh_pki_dir }}/host_certs/{{ item.name }}_sshkey-cert.pub"
+ with_items: "{{ ssh_host_genkeys }}"
+
diff --git a/ssh_pki/.gitignore b/ssh_pki/.gitignore
new file mode 100644
index 0000000..6b76b18
--- /dev/null
+++ b/ssh_pki/.gitignore
@@ -0,0 +1,4 @@
+ca
+client_certs
+host_certs
+
diff --git a/ssh_pki/README.md b/ssh_pki/README.md
new file mode 100644
index 0000000..f760962
--- /dev/null
+++ b/ssh_pki/README.md
@@ -0,0 +1,5 @@
+# ssh_pki
+
+This folder contains files uses to manage SSH certificate authority (CA), so
+handle with care.
+
diff --git a/templates/admin-openrc-cord.sh.j2 b/templates/admin-openrc-cord.sh.j2
deleted file mode 100644
index eb1c3df..0000000
--- a/templates/admin-openrc-cord.sh.j2
+++ /dev/null
@@ -1,5 +0,0 @@
-export OS_USERNAME=admin
-export OS_PASSWORD=ADMIN_PASS
-export OS_TENANT_NAME=admin
-export OS_AUTH_URL=http://keystone:5000/v2.0/
-export OS_REGION_NAME=RegionOne
diff --git a/templates/admin-openrc.sh.j2 b/templates/admin-openrc.sh.j2
deleted file mode 100644
index 260f035..0000000
--- a/templates/admin-openrc.sh.j2
+++ /dev/null
@@ -1,5 +0,0 @@
-export OS_USERNAME=admin
-export OS_PASSWORD={{ keystone_password.stdout }}
-export OS_TENANT_NAME=admin
-export OS_AUTH_URL=https://{{ keystone_ip.stdout }}:5000/v2.0
-export OS_REGION_NAME=RegionOne
diff --git a/templates/cord.yml b/templates/cord.yml
deleted file mode 100644
index 065bea1..0000000
--- a/templates/cord.yml
+++ /dev/null
@@ -1,221 +0,0 @@
-machines:
- '1':
- constraints: arch=amd64
- '2':
- constraints: arch=amd64
- '3':
- constraints: arch=amd64
- '4':
- constraints: arch=amd64
- '5':
- constraints: arch=amd64
- '6':
- constraints: arch=amd64
- '7':
- constraints: arch=amd64
- '8':
- constraints: arch=amd64
- '9':
- constraints: arch=amd64
- '10':
- constraints: arch=amd64
-relations:
-- - nova-compute:amqp
- - rabbitmq-server:amqp
-- - keystone:shared-db
- - mysql:shared-db
-- - nova-cloud-controller:identity-service
- - keystone:identity-service
-- - glance:identity-service
- - keystone:identity-service
-- - neutron-api:identity-service
- - keystone:identity-service
-- - neutron-api:shared-db
- - mysql:shared-db
-- - neutron-api:amqp
- - rabbitmq-server:amqp
-- - glance:shared-db
- - mysql:shared-db
-- - glance:amqp
- - rabbitmq-server:amqp
-- - nova-cloud-controller:image-service
- - glance:image-service
-- - nova-compute:image-service
- - glance:image-service
-- - nova-cloud-controller:cloud-compute
- - nova-compute:cloud-compute
-- - nova-cloud-controller:amqp
- - rabbitmq-server:amqp
-- - openstack-dashboard:identity-service
- - keystone:identity-service
-- - nova-cloud-controller:shared-db
- - mysql:shared-db
-- - nova-cloud-controller:neutron-api
- - neutron-api:neutron-api
-- - ntp:juju-info
- - nova-compute:juju-info
-- - nagios
- - nrpe
-- - mysql:juju-info
- - nrpe:general-info
-- - rabbitmq-server
- - nrpe
-- - keystone
- - nrpe
-- - glance
- - nrpe
-- - nova-cloud-controller
- - nrpe
-- - openstack-dashboard
- - nrpe
-- - neutron-api
- - nrpe
-- - ceilometer
- - mongodb
-- - ceilometer
- - rabbitmq-server
-- - ceilometer:identity-service
- - keystone:identity-service
-- - ceilometer:ceilometer-service
- - ceilometer-agent:ceilometer-service
-- - ceilometer
- - nagios
-- - ceilometer
- - nrpe
-- - nova-compute
- - nagios
-- - nova-compute
- - nrpe
-- - nova-compute:nova-ceilometer
- - ceilometer-agent:nova-ceilometer
-series: trusty
-services:
- ceilometer:
- charm: cs:trusty/ceilometer-17
- num_units: 1
- options:
- openstack-origin: cloud:trusty-kilo
- to:
- - '7'
- ceilometer-agent:
- charm: cs:trusty/ceilometer-agent-13
- num_units: 0
- glance:
- annotations:
- gui-x: '250'
- gui-y: '0'
- charm: cs:trusty/glance-28
- num_units: 1
- options:
- ha-mcastport: 5402
- openstack-origin: cloud:trusty-kilo
- to:
- - '4'
- keystone:
- annotations:
- gui-x: '500'
- gui-y: '0'
- charm: cs:trusty/keystone-33
- num_units: 1
- options:
- admin-password: 'ADMIN_PASS'
- ha-mcastport: 5403
- https-service-endpoints: False
- openstack-origin: cloud:trusty-kilo
- use-https: no
- to:
- - '3'
- mongodb:
- charm: cs:trusty/mongodb-33
- num_units: 1
- to:
- - '7'
- mysql:
- annotations:
- gui-x: '0'
- gui-y: '250'
- charm: cs:trusty/percona-cluster-31
- num_units: 1
- options:
- max-connections: 20000
- to:
- - '1'
- nagios:
- charm: cs:trusty/nagios-10
- num_units: 1
- to:
- - '8'
- neutron-api:
- annotations:
- gui-x: '500'
- gui-y: '500'
- charm: cs:~cordteam/trusty/neutron-api-3
- num_units: 1
- options:
- neutron-plugin: onosvtn
- onos-vtn-ip: onos-cord
- onos-vtn-port: 8182
- neutron-security-groups: true
- openstack-origin: cloud:trusty-kilo
- overlay-network-type: vxlan
- to:
- - '9'
- nova-cloud-controller:
- annotations:
- gui-x: '0'
- gui-y: '500'
- charm: cs:trusty/nova-cloud-controller-64
- num_units: 1
- options:
- config-flags: "force_config_drive=always"
- console-access-protocol: novnc
- network-manager: Neutron
- openstack-origin: cloud:trusty-kilo
- #quantum-security-groups: 'yes'
- to:
- - '5'
- nova-compute:
- annotations:
- gui-x: '250'
- gui-y: '250'
- charm: cs:~cordteam/trusty/nova-compute-2
- num_units: 1
- options:
- config-flags: firewall_driver=nova.virt.firewall.NoopFirewallDriver
- disable-neutron-security-groups: True
- #enable-live-migration: true
- #enable-resize: true
- #migration-auth-type: ssh
- openstack-origin: cloud:trusty-kilo
- #manage-neutron-plugin-legacy-mode: False
- to:
- - '10'
- nrpe:
- charm: cs:trusty/nrpe-4
- num_units: 0
- ntp:
- annotations:
- gui-x: '1000'
- gui-y: '0'
- charm: cs:trusty/ntp-14
- num_units: 0
- openstack-dashboard:
- annotations:
- gui-x: '500'
- gui-y: '-250'
- charm: cs:trusty/openstack-dashboard-19
- num_units: 1
- options:
- openstack-origin: cloud:trusty-kilo
- to:
- - '6'
- rabbitmq-server:
- annotations:
- gui-x: '500'
- gui-y: '250'
- charm: cs:trusty/rabbitmq-server-42
- num_units: 1
- options:
- ssl: 'off'
- to:
- - '2'
diff --git a/templates/environments.yaml.j2 b/templates/environments.yaml.j2
deleted file mode 100644
index 4daeba1..0000000
--- a/templates/environments.yaml.j2
+++ /dev/null
@@ -1,7 +0,0 @@
-default: manual
-environments:
- manual:
- type: manual
- bootstrap-host: juju
- bootstrap-user: ubuntu
- default-series: trusty
diff --git a/templates/etc/ansible/cord-hosts.j2 b/templates/etc/ansible/cord-hosts.j2
deleted file mode 100644
index 6379422..0000000
--- a/templates/etc/ansible/cord-hosts.j2
+++ /dev/null
@@ -1,16 +0,0 @@
-[localhost]
-127.0.0.1 hostname={{ ansible_fqdn }}
-
-[services]
-juju
-mysql
-rabbitmq-server
-keystone
-glance
-nova-cloud-controller
-openstack-dashboard
-ceilometer
-nagios
-neutron-api
-xos
-onos-cord
diff --git a/templates/etc/ansible/hosts.j2 b/templates/etc/ansible/hosts.j2
deleted file mode 100644
index 007b456..0000000
--- a/templates/etc/ansible/hosts.j2
+++ /dev/null
@@ -1,15 +0,0 @@
-[localhost]
-127.0.0.1 hostname={{ ansible_fqdn }}
-
-[services]
-juju
-mysql
-rabbitmq-server
-keystone
-glance
-nova-cloud-controller
-neutron-gateway
-openstack-dashboard
-ceilometer
-nagios
-neutron-api
diff --git a/templates/etc/cord-hosts.j2 b/templates/etc/cord-hosts.j2
deleted file mode 100644
index 3dc570e..0000000
--- a/templates/etc/cord-hosts.j2
+++ /dev/null
@@ -1,22 +0,0 @@
-127.0.0.1 localhost
-127.0.1.1 ubuntu
-{{ juju_ip.stdout }} juju
-{{ mysql_ip.stdout }} mysql
-{{ rabbitmq_ip.stdout }} rabbitmq-server
-{{ keystone_ip.stdout }} keystone
-{{ glance_ip.stdout }} glance
-{{ novacc_ip.stdout }} nova-cloud-controller
-{{ horizon_ip.stdout }} openstack-dashboard
-{{ ceilometer_ip.stdout }} ceilometer
-{{ nagios_ip.stdout }} nagios
-{{ neutron_api_ip.stdout}} neutron-api
-{{ xos_ip.stdout }} xos
-{{ onos_cord_ip.stdout }} onos-cord
-{% if test_setup is defined %}
-{{ nova_compute_ip.stdout }} nova-compute
-{% endif %}
-
-# The following lines are desirable for IPv6 capable hosts
-::1 localhost ip6-localhost ip6-loopback
-ff02::1 ip6-allnodes
-ff02::2 ip6-allrouters
diff --git a/templates/etc/cron.d/ansible-pull.j2 b/templates/etc/cron.d/ansible-pull.j2
deleted file mode 100644
index 73d3cd4..0000000
--- a/templates/etc/cron.d/ansible-pull.j2
+++ /dev/null
@@ -1,2 +0,0 @@
-# Cron job to git clone/pull a repo and then run locally
-{{ schedule }} {{ cron_user }} ansible-pull -o -d {{ workdir }} -U {{ repo_url }} -C {{ repo_version }} >>{{ logfile }} 2>&1
diff --git a/templates/etc/hosts.j2 b/templates/etc/hosts.j2
deleted file mode 100644
index b095c5c..0000000
--- a/templates/etc/hosts.j2
+++ /dev/null
@@ -1,18 +0,0 @@
-127.0.0.1 localhost
-127.0.1.1 ubuntu
-{{ juju_ip.stdout }} juju
-{{ mysql_ip.stdout }} mysql
-{{ rabbitmq_ip.stdout }} rabbitmq-server
-{{ keystone_ip.stdout }} keystone
-{{ glance_ip.stdout }} glance
-{{ novacc_ip.stdout }} nova-cloud-controller
-{{ neutron_ip.stdout }} neutron-gateway
-{{ horizon_ip.stdout }} openstack-dashboard
-{{ ceilometer_ip.stdout }} ceilometer
-{{ nagios_ip.stdout }} nagios
-{{ neutron_api_ip.stdout}} neutron-api
-
-# The following lines are desirable for IPv6 capable hosts
-::1 localhost ip6-localhost ip6-loopback
-ff02::1 ip6-allnodes
-ff02::2 ip6-allrouters
diff --git a/templates/etc/libvirt/qemu/networks/default.xml.j2 b/templates/etc/libvirt/qemu/networks/default.xml.j2
deleted file mode 100644
index 64b88c3..0000000
--- a/templates/etc/libvirt/qemu/networks/default.xml.j2
+++ /dev/null
@@ -1,10 +0,0 @@
-<network>
- <name>default</name>
- <bridge name="virbr0"/>
- <forward/>
- <ip address="{{ mgmt_net_prefix }}.1" netmask="255.255.255.0">
- <dhcp>
- <range start="{{ mgmt_net_prefix }}.2" end="{{ mgmt_net_prefix }}.254"/>
- </dhcp>
- </ip>
-</network>
diff --git a/templates/etc/logrotate.d/ansible-pull.j2 b/templates/etc/logrotate.d/ansible-pull.j2
deleted file mode 100644
index e396f31..0000000
--- a/templates/etc/logrotate.d/ansible-pull.j2
+++ /dev/null
@@ -1,7 +0,0 @@
-{{ logfile }} {
- rotate 7
- daily
- compress
- missingok
- notifempty
-}
diff --git a/templates/etc/rc.local b/templates/etc/rc.local
deleted file mode 100644
index 7eb7ab1..0000000
--- a/templates/etc/rc.local
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh -e
-#
-# rc.local
-#
-# This script is executed at the end of each multiuser runlevel.
-# Make sure that the script will "exit 0" on success or any other
-# value on error.
-#
-# In order to enable or disable this script just change the execution
-# bits.
-
-route add -net {{ control_net }} gw {{ gateway }} || true
-
-exit 0
\ No newline at end of file
diff --git a/templates/etc/rc.local.cloudlab b/templates/etc/rc.local.cloudlab
deleted file mode 100755
index a28ab65..0000000
--- a/templates/etc/rc.local.cloudlab
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2004-2014 University of Utah and the Flux Group.
-#
-# This file is part of the Emulab network testbed software.
-#
-# This file is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or (at
-# your option) any later version.
-#
-# This file is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this file. If not, see <http://www.gnu.org/licenses/>.
-#
-
-#
-# This script will be executed *after* all the other init scripts.
-# You can put your own initialization stuff in here if you don't
-# want to do the full Sys V style init stuff.
-
-# XXX compat with RedHat feature
-if [ ! -d /var/lock/subsys ]; then
- mkdir /var/lock/subsys
-fi
-
-# XXX serial console seems to be in raw mode, makes our messages ugly :-)
-if [ ! -e /dev/hvc0 -a -c /dev/ttyS0 ]; then
- stty -F /dev/ttyS0 opost onlcr
-fi
-
-#
-# Testbed Setup.
-#
-if [ -f /usr/local/etc/emulab/rc/rc.testbed ] ; then
- echo -n 'testbed config: '
- /usr/local/etc/emulab/rc/rc.testbed
- touch /var/lock/subsys/testbed
-fi
-
-route add -net {{ control_net }} gw {{ gateway }} || true
-
-echo "Boot Complete"
-
-exit 0