diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 864cadde550bf02f43bcc579b96cf08ca2db3553..7080c7c6751da797f9db7b4649f1d826851ca644 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -366,6 +366,8 @@ before_script:
 
 .ubuntu_vault_sep_variables: &ubuntu_vault_sep_variables
 # stage: deploy-gce-part1
+  AUTHORIZATION_MODES: "{ 'authorization_modes':  [ 'RBAC' ] }"
+  CLOUD_MACHINE_TYPE: "n1-standard-2"
   KUBE_NETWORK_PLUGIN: canal
   CERT_MGMT: vault
   CLOUD_IMAGE: ubuntu-1604-xenial
diff --git a/roles/etcd/tasks/gen_certs_vault.yml b/roles/etcd/tasks/gen_certs_vault.yml
index 4f27eff86495988352a735fad95227b04bef1d3a..0048a70030483bc8544fdebb62744ac00b36cc06 100644
--- a/roles/etcd/tasks/gen_certs_vault.yml
+++ b/roles/etcd/tasks/gen_certs_vault.yml
@@ -7,51 +7,14 @@
   when: inventory_hostname in etcd_node_cert_hosts
   tags: etcd-secrets
 
-- name: gen_certs_vault | Read in the local credentials
-  command: cat /etc/vault/roles/etcd/userpass
-  register: etcd_vault_creds_cat
-  delegate_to: "{{ groups['vault'][0] }}"
-
-- name: gen_certs_vault | Set facts for read Vault Creds
-  set_fact:
-    etcd_vault_creds: "{{ etcd_vault_creds_cat.stdout|from_json }}"
-  delegate_to: "{{ groups['vault'][0] }}"
-
-- name: gen_certs_vault | Log into Vault and obtain an token
-  uri:
-    url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}/v1/auth/userpass/login/{{ etcd_vault_creds.username }}"
-    headers:
-      Accept: application/json
-      Content-Type: application/json
-    method: POST
-    body_format: json
-    body:
-      password: "{{ etcd_vault_creds.password }}"
-  register: etcd_vault_login_result
-  delegate_to: "{{ groups['vault'][0] }}"
-
-- name: gen_certs_vault | Set fact for vault_client_token
-  set_fact:
-    vault_client_token: "{{ etcd_vault_login_result.get('json', {}).get('auth', {}).get('client_token') }}"
-  run_once: true
-
-- name: gen_certs_vault | Set fact for Vault API token
-  set_fact:
-    etcd_vault_headers:
-      Accept: application/json
-      Content-Type: application/json
-      X-Vault-Token: "{{ vault_client_token }}"
-  run_once: true
-  when: vault_client_token != ""
-
 # Issue master certs to Etcd nodes
 - include: ../../vault/tasks/shared/issue_cert.yml
   vars:
+    issue_cert_common_name: "etcd:master:{{ item.rsplit('/', 1)[1].rsplit('.', 1)[0] }}"
     issue_cert_alt_names: "{{ groups.etcd + ['localhost'] }}"
     issue_cert_copy_ca: "{{ item == etcd_master_certs_needed|first }}"
     issue_cert_file_group: "{{ etcd_cert_group }}"
     issue_cert_file_owner: kube
-    issue_cert_headers: "{{ etcd_vault_headers }}"
     issue_cert_hosts: "{{ groups.etcd }}"
     issue_cert_ip_sans: >-
         [
@@ -74,11 +37,11 @@
 # Issue node certs to everyone else
 - include: ../../vault/tasks/shared/issue_cert.yml
   vars:
+    issue_cert_common_name: "etcd:node:{{ item.rsplit('/', 1)[1].rsplit('.', 1)[0] }}"
     issue_cert_alt_names: "{{ etcd_node_cert_hosts }}"
     issue_cert_copy_ca: "{{ item == etcd_node_certs_needed|first }}"
     issue_cert_file_group: "{{ etcd_cert_group }}"
     issue_cert_file_owner: kube
-    issue_cert_headers: "{{ etcd_vault_headers }}"
     issue_cert_hosts: "{{ etcd_node_cert_hosts }}"
     issue_cert_ip_sans: >-
         [
diff --git a/roles/kubernetes/secrets/tasks/gen_certs_vault.yml b/roles/kubernetes/secrets/tasks/gen_certs_vault.yml
index 31abdbf5b093e937ca2519d369d12441188a5e7f..8cad8cc662ed05baace6dd8f085bad819eeed508 100644
--- a/roles/kubernetes/secrets/tasks/gen_certs_vault.yml
+++ b/roles/kubernetes/secrets/tasks/gen_certs_vault.yml
@@ -1,56 +1,23 @@
 ---
 - include: sync_kube_master_certs.yml
   when: inventory_hostname in groups['kube-master']
-  tags: k8s-secrets
 
 - include: sync_kube_node_certs.yml
   when: inventory_hostname in groups['k8s-cluster']
-  tags: k8s-secrets
 
-- name: gen_certs_vault | Read in the local credentials
-  command: cat /etc/vault/roles/kube/userpass
-  register: kube_vault_creds_cat
-  delegate_to: "{{ groups['k8s-cluster'][0] }}"
-
-- name: gen_certs_vault | Set facts for read Vault Creds
-  set_fact:
-    kube_vault_creds: "{{ kube_vault_creds_cat.stdout|from_json }}"
-  delegate_to: "{{ groups['k8s-cluster'][0] }}"
-
-- name: gen_certs_vault | Log into Vault and obtain an token
-  uri:
-    url: "{{ hostvars[groups['vault'][0]]['vault_leader_url'] }}/v1/auth/userpass/login/{{ kube_vault_creds.username }}"
-    headers:
-      Accept: application/json
-      Content-Type: application/json
-    method: POST
-    body_format: json
-    body:
-      password: "{{ kube_vault_creds.password }}"
-  register: kube_vault_login_result
-  delegate_to: "{{ groups['k8s-cluster'][0] }}"
-
-- name: gen_certs_vault | Set fact for Vault API token
-  set_fact:
-    kube_vault_headers:
-      Accept: application/json
-      Content-Type: application/json
-      X-Vault-Token: "{{ kube_vault_login_result.get('json',{}).get('auth', {}).get('client_token') }}"
-  run_once: true
-
-# Issue certs to kube-master nodes
+# Issue admin certs to kube-master hosts
 - include: ../../../vault/tasks/shared/issue_cert.yml
   vars:
-    issue_cert_copy_ca: "{{ item == kube_master_certs_needed|first }}"
+    issue_cert_common_name: "admin"
+    issue_cert_copy_ca: "{{ item == kube_admin_certs_needed|first }}"
     issue_cert_file_group: "{{ kube_cert_group }}"
     issue_cert_file_owner: kube
-    issue_cert_headers: "{{ kube_vault_headers }}"
     issue_cert_hosts: "{{ groups['kube-master'] }}"
     issue_cert_path: "{{ item }}"
-    issue_cert_role: kube
+    issue_cert_role: kube-master
     issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}"
     issue_cert_mount_path: "{{ kube_vault_mount_path }}"
-  with_items: "{{ kube_master_certs_needed|d([]) }}"
+  with_items: "{{ kube_admin_certs_needed|d([]) }}"
   when: inventory_hostname in groups['kube-master']
 
 - name: gen_certs_vault | Set fact about certificate alt names
@@ -69,12 +36,13 @@
   when: loadbalancer_apiserver is defined and apiserver_loadbalancer_domain_name is defined
   run_once: true
 
+# Issue master components certs to kube-master hosts
 - include: ../../../vault/tasks/shared/issue_cert.yml
   vars:
+    issue_cert_common_name: "kubernetes"
     issue_cert_alt_names: "{{ kube_cert_alt_names }}"
     issue_cert_file_group: "{{ kube_cert_group }}"
     issue_cert_file_owner: kube
-    issue_cert_headers: "{{ kube_vault_headers }}"
     issue_cert_hosts: "{{ groups['kube-master'] }}"
     issue_cert_ip_sans: >-
         [
@@ -87,7 +55,7 @@
         "127.0.0.1","::1","{{ kube_apiserver_ip }}"
         ]
     issue_cert_path: "{{ item }}"
-    issue_cert_role: kube
+    issue_cert_role: kube-master
     issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}"
     issue_cert_mount_path: "{{ kube_vault_mount_path }}"
   with_items: "{{ kube_master_components_certs_needed|d([]) }}"
@@ -97,27 +65,28 @@
 # Issue node certs to k8s-cluster nodes
 - include: ../../../vault/tasks/shared/issue_cert.yml
   vars:
+    issue_cert_common_name: "system:node:{{ item.rsplit('/', 1)[1].rsplit('.', 1)[0] }}"
     issue_cert_copy_ca: "{{ item == kube_node_certs_needed|first }}"
     issue_cert_file_group: "{{ kube_cert_group }}"
     issue_cert_file_owner: kube
-    issue_cert_headers: "{{ kube_vault_headers }}"
     issue_cert_hosts: "{{ groups['k8s-cluster'] }}"
     issue_cert_path: "{{ item }}"
-    issue_cert_role: kube
+    issue_cert_role: kube-node
     issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}"
     issue_cert_mount_path: "{{ kube_vault_mount_path }}"
   with_items: "{{ kube_node_certs_needed|d([]) }}"
   when: inventory_hostname in groups['k8s-cluster']
 
+# Issue proxy certs to k8s-cluster nodes
 - include: ../../../vault/tasks/shared/issue_cert.yml
   vars:
+    issue_cert_common_name: "system:kube-proxy"
     issue_cert_copy_ca: "{{ item == kube_proxy_certs_needed|first }}"
     issue_cert_file_group: "{{ kube_cert_group }}"
     issue_cert_file_owner: kube
-    issue_cert_headers: "{{ kube_vault_headers }}"
     issue_cert_hosts: "{{ groups['k8s-cluster'] }}"
     issue_cert_path: "{{ item }}"
-    issue_cert_role: kube
+    issue_cert_role: kube-proxy
     issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}"
     issue_cert_mount_path: "{{ kube_vault_mount_path }}"
   with_items: "{{ kube_proxy_certs_needed|d([]) }}"
diff --git a/roles/kubernetes/secrets/tasks/sync_kube_master_certs.yml b/roles/kubernetes/secrets/tasks/sync_kube_master_certs.yml
index 6fa861a36996fe6e06a1cd863e562ceb9647a547..277038612ba9dfc99e9410a4cd6043044d6135d8 100644
--- a/roles/kubernetes/secrets/tasks/sync_kube_master_certs.yml
+++ b/roles/kubernetes/secrets/tasks/sync_kube_master_certs.yml
@@ -2,7 +2,7 @@
 
 - name: sync_kube_master_certs | Create list of needed kube admin certs
   set_fact:
-    kube_master_cert_list: "{{ kube_master_cert_list|d([]) + ['admin-' + item + '.pem'] }}"
+    kube_admin_cert_list: "{{ kube_admin_cert_list|d([]) + ['admin-' + item + '.pem'] }}"
   with_items: "{{ groups['kube-master'] }}"
 
 - include: ../../../vault/tasks/shared/sync_file.yml
@@ -13,11 +13,11 @@
     sync_file_hosts: "{{ groups['kube-master'] }}"
     sync_file_is_cert: true
     sync_file_owner: kube
-  with_items: "{{ kube_master_cert_list|d([]) }}"
+  with_items: "{{ kube_admin_cert_list|d([]) }}"
 
 - name: sync_kube_master_certs | Set facts for kube admin sync_file results
   set_fact:
-    kube_master_certs_needed: "{{ kube_master_certs_needed|default([]) + [item.path] }}"
+    kube_admin_certs_needed: "{{ kube_admin_certs_needed|default([]) + [item.path] }}"
   with_items: "{{ sync_file_results|d([]) }}"
   when: item.no_srcs|bool
 
diff --git a/roles/kubespray-defaults/defaults/main.yaml b/roles/kubespray-defaults/defaults/main.yaml
index 5405e2577cb074b62f449901f41fa4909f3d127f..c86f322fcb681e141edb8da96ceafcc46dbe189e 100644
--- a/roles/kubespray-defaults/defaults/main.yaml
+++ b/roles/kubespray-defaults/defaults/main.yaml
@@ -135,3 +135,10 @@ rbac_enabled: "{{ 'RBAC' in authorization_modes }}"
 ## List of key=value pairs that describe feature gates for
 ## the k8s cluster.
 kube_feature_gates: []
+
+# Vault data dirs.
+vault_base_dir: /etc/vault
+vault_cert_dir: "{{ vault_base_dir }}/ssl"
+vault_config_dir: "{{ vault_base_dir }}/config"
+vault_roles_dir: "{{ vault_base_dir }}/roles"
+vault_secrets_dir: "{{ vault_base_dir }}/secrets"
diff --git a/roles/vault/defaults/main.yml b/roles/vault/defaults/main.yml
index eb2ffd1229d99654d4b695b8565ec5f946f89c3e..2320ae862fc77b57a57bd3bd06ff96cf03af2e9b 100644
--- a/roles/vault/defaults/main.yml
+++ b/roles/vault/defaults/main.yml
@@ -1,4 +1,6 @@
 ---
+vault_bootstrap: false
+vault_deployment_type: docker
 
 vault_adduser_vars:
   comment: "Hashicorp Vault User"
@@ -6,41 +8,18 @@ vault_adduser_vars:
   name: vault
   shell: /sbin/nologin
   system: yes
+
+# This variables redefined in kubespray-defaults for using shared tasks
+# in etcd and kubernetes/secrets roles
 vault_base_dir: /etc/vault
-# https://releases.hashicorp.com/vault/0.6.4/vault_0.6.4_SHA256SUMS
-vault_version: 0.6.4
-vault_binary_checksum: 04d87dd553aed59f3fe316222217a8d8777f40115a115dac4d88fac1611c51a6
-vault_bootstrap: false
-vault_ca_options:
-  common_name: vault
-  format: pem
-  ttl: 87600h
 vault_cert_dir: "{{ vault_base_dir }}/ssl"
-vault_client_headers:
-  Accept: "application/json"
-  Content-Type: "application/json"
-vault_config:
-  backend:
-    etcd:
-      address: "{{ vault_etcd_url }}"
-      ha_enabled: "true"
-      redirect_addr: "https://{{ ansible_default_ipv4.address }}:{{ vault_port }}"
-      tls_ca_file: "{{ vault_etcd_cert_dir }}/ca.pem"
-  cluster_name: "kubernetes-vault"
-  default_lease_ttl: "{{ vault_default_lease_ttl }}"
-  listener:
-    tcp:
-      address: "0.0.0.0:{{ vault_port }}"
-      tls_cert_file: "{{ vault_cert_dir }}/api.pem"
-      tls_key_file: "{{ vault_cert_dir }}/api-key.pem"
-  max_lease_ttl: "{{ vault_max_lease_ttl }}"
 vault_config_dir: "{{ vault_base_dir }}/config"
-vault_container_name: kube-hashicorp-vault
-# This variable is meant to match the GID of vault inside Hashicorp's official Vault Container
-vault_default_lease_ttl: 720h
-vault_default_role_permissions:
-  allow_any_name: true
-vault_deployment_type: docker
+vault_roles_dir: "{{ vault_base_dir }}/roles"
+vault_secrets_dir: "{{ vault_base_dir }}/secrets"
+vault_log_dir: "/var/log/vault"
+
+vault_version: 0.8.1
+vault_binary_checksum: 3c4d70ba71619a43229e65c67830e30e050eab7a81ac6b28325ff707e5914188
 vault_download_url: "https://releases.hashicorp.com/vault/{{ vault_version }}/vault_{{ vault_version }}_linux_amd64.zip"
 vault_download_vars:
   container: "{{ vault_deployment_type != 'host' }}"
@@ -55,17 +34,19 @@ vault_download_vars:
   unarchive: true
   url: "{{ vault_download_url }}"
   version: "{{ vault_version }}"
-vault_etcd_url: "https://{{ hostvars[groups.etcd[0]]['ip']|d(hostvars[groups.etcd[0]]['ansible_default_ipv4']['address']) }}:2379"
+
+vault_container_name: kube-hashicorp-vault
+vault_temp_container_name: vault-temp
 vault_image_repo: "vault"
 vault_image_tag: "{{ vault_version }}"
-vault_log_dir: "/var/log/vault"
-vault_max_lease_ttl: 87600h
-vault_needs_gen: false
+
+vault_bind_address: 0.0.0.0
 vault_port: 8200
-vault_roles_dir: "{{ vault_base_dir }}/roles"
-vault_secret_shares: 1
-vault_secret_threshold: 1
-vault_secrets_dir: "{{ vault_base_dir }}/secrets"
+vault_etcd_url: "https://{{ hostvars[groups.etcd[0]]['ip']|d(hostvars[groups.etcd[0]]['ansible_default_ipv4']['address']) }}:2379"
+
+vault_default_lease_ttl: 720h
+vault_max_lease_ttl: 87600h
+
 vault_temp_config:
   backend:
     file:
@@ -73,29 +54,109 @@ vault_temp_config:
   default_lease_ttl: "{{ vault_default_lease_ttl }}"
   listener:
     tcp:
-      address: "0.0.0.0:{{ vault_port }}"
+      address: "{{ vault_bind_address }}:{{ vault_port }}"
       tls_disable: "true"
   max_lease_ttl: "{{ vault_max_lease_ttl }}"
-vault_temp_container_name: vault-temp
-# etcd pki mount options
+
+vault_config:
+  backend:
+    etcd:
+      address: "{{ vault_etcd_url }}"
+      ha_enabled: "true"
+      redirect_addr: "https://{{ ansible_default_ipv4.address }}:{{ vault_port }}"
+      tls_ca_file: "{{ vault_etcd_cert_dir }}/ca.pem"
+  cluster_name: "kubernetes-vault"
+  default_lease_ttl: "{{ vault_default_lease_ttl }}"
+  max_lease_ttl: "{{ vault_max_lease_ttl }}"
+  listener:
+    tcp:
+      address: "{{ vault_bind_address }}:{{ vault_port }}"
+      tls_cert_file: "{{ vault_cert_dir }}/api.pem"
+      tls_key_file: "{{ vault_cert_dir }}/api-key.pem"
+
+vault_secret_shares: 1
+vault_secret_threshold: 1
+
+vault_ca_options:
+  vault:
+    common_name: vault
+    format: pem
+    ttl: "{{ vault_max_lease_ttl }}"
+    exclude_cn_from_sans: true
+  etcd:
+    common_name: etcd
+    format: pem
+    ttl: "{{ vault_max_lease_ttl }}"
+    exclude_cn_from_sans: true
+  kube:
+    common_name: kube
+    format: pem
+    ttl: "{{ vault_max_lease_ttl }}"
+    exclude_cn_from_sans: true
+
+vault_client_headers:
+  Accept: "application/json"
+  Content-Type: "application/json"
+
 vault_etcd_cert_dir: /etc/ssl/etcd/ssl
-vault_etcd_mount_path: etcd
-vault_etcd_default_lease_ttl: 720h
-vault_etcd_max_lease_ttl: 87600h
-vault_etcd_role:
-  name: etcd
-  group: etcd
-  policy_rules: default
-  role_options: default
-  mount_path: "{{ vault_etcd_mount_path }}"
-# kubernetes pki mount options
-vault_kube_cert_dir: "{{ kube_cert_dir }}"
-vault_kube_mount_path: kube
-vault_kube_default_lease_ttl: 720h
-vault_kube_max_lease_ttl: 87600h
-vault_kube_role:
-  name: kube
-  group: k8s-cluster
-  policy_rules: default
-  role_options: default
-  mount_path: "{{ vault_kube_mount_path }}"
+vault_kube_cert_dir: /etc/kubernetes/ssl
+
+vault_pki_mounts:
+  vault:
+    name: vault
+    default_lease_ttl: "{{ vault_default_lease_ttl }}"
+    max_lease_ttl: "{{ vault_max_lease_ttl }}"
+    description: "Vault Root CA"
+    cert_dir: "{{ vault_cert_dir }}"
+    roles:
+      - name: vault
+        group: vault
+        password: "{{ lookup('pipe','date +%Y%m%d%H%M%S' + cluster_name + 'vault') | to_uuid }}"
+        policy_rules: default
+        role_options: default
+  etcd:
+    name: etcd
+    default_lease_ttl: "{{ vault_default_lease_ttl }}"
+    max_lease_ttl: "{{ vault_max_lease_ttl }}"
+    description: "Etcd Root CA"
+    cert_dir: "{{ vault_etcd_cert_dir }}"
+    roles:
+      - name: etcd
+        group: etcd
+        password: "{{ lookup('pipe','date +%Y%m%d%H%M%S' + cluster_name + 'etcd') | to_uuid }}"
+        policy_rules: default
+        role_options:
+          allow_any_name: true
+          enforce_hostnames: false
+          organization: "kube:etcd"
+  kube:
+    name: kube
+    default_lease_ttl: "{{ vault_default_lease_ttl }}"
+    max_lease_ttl: "{{ vault_max_lease_ttl }}"
+    description: "Kubernetes Root CA"
+    cert_dir: "{{ vault_kube_cert_dir }}"
+    roles:
+      - name: kube-master
+        group: kube-master
+        password: "{{ lookup('pipe','date +%Y%m%d%H%M%S' + cluster_name + 'kube-master') | to_uuid }}"
+        policy_rules: default
+        role_options:
+          allow_any_name: true
+          enforce_hostnames: false
+          organization: "system:masters"
+      - name: kube-node
+        group: k8s-cluster
+        password: "{{ lookup('pipe','date +%Y%m%d%H%M%S' + cluster_name + 'kube-node') | to_uuid }}"
+        policy_rules: default
+        role_options:
+          allow_any_name: true
+          enforce_hostnames: false
+          organization: "system:nodes"
+      - name: kube-proxy
+        group: k8s-cluster
+        password: "{{ lookup('pipe', 'date +%Y%m%d%H%M%S' + cluster_name + 'kube-proxy') | to_uuid }}"
+        policy_rules: default
+        role_options:
+          allow_any_name: true
+          enforce_hostnames: false
+          organization: "system:node-proxier"
diff --git a/roles/vault/tasks/bootstrap/create_etcd_role.yml b/roles/vault/tasks/bootstrap/create_etcd_role.yml
deleted file mode 100644
index 74cd5fc2fe3b476d2a3e2506fe4c319759eedf92..0000000000000000000000000000000000000000
--- a/roles/vault/tasks/bootstrap/create_etcd_role.yml
+++ /dev/null
@@ -1,17 +0,0 @@
----
-- include: ../shared/auth_backend.yml
-  vars:
-    auth_backend_description: A Username/Password Auth Backend primarily used for services needing to issue certificates
-    auth_backend_path: userpass
-    auth_backend_type: userpass
-  delegate_to: "{{ groups.vault|first }}"
-  run_once: true
-
-- include: ../shared/create_role.yml
-  vars:
-    create_role_name: "{{ vault_etcd_role.name }}"
-    create_role_group: "{{ vault_etcd_role.group }}"
-    create_role_policy_rules: "{{ vault_etcd_role.policy_rules }}"
-    create_role_options: "{{ vault_etcd_role.role_options }}"
-    create_role_mount_path: "{{ vault_etcd_role.mount_path }}"
-  when: inventory_hostname in groups.etcd
diff --git a/roles/vault/tasks/bootstrap/create_mounts.yml b/roles/vault/tasks/bootstrap/create_mounts.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0010c35c54b840f0fa36adad2f4fabb5ea4b6b88
--- /dev/null
+++ b/roles/vault/tasks/bootstrap/create_mounts.yml
@@ -0,0 +1,12 @@
+---
+- include: ../shared/create_mount.yml
+  vars:
+    create_mount_path: "{{ item.name }}"
+    create_mount_default_lease_ttl: "{{ item.default_lease_ttl }}"
+    create_mount_max_lease_ttl: "{{ item.max_lease_ttl }}"
+    create_mount_description: "{{ item.description }}"
+    create_mount_cert_dir: "{{ item.cert_dir }}"
+    create_mount_config_ca_needed: "{{ item.config_ca }}"
+  with_items:
+    - "{{ vault_pki_mounts.vault|combine({'config_ca': not vault_ca_cert_needed}) }}"
+    - "{{ vault_pki_mounts.etcd|combine({'config_ca': not vault_etcd_ca_cert_needed}) }}"
diff --git a/roles/vault/tasks/bootstrap/create_roles.yml b/roles/vault/tasks/bootstrap/create_roles.yml
new file mode 100644
index 0000000000000000000000000000000000000000..11411d23682e06ebe4fd1449747ed7a913b9dc33
--- /dev/null
+++ b/roles/vault/tasks/bootstrap/create_roles.yml
@@ -0,0 +1,10 @@
+---
+- include: ../shared/create_role.yml
+  vars:
+    create_role_name: "{{ item.name }}"
+    create_role_group: "{{ item.group }}"
+    create_role_policy_rules: "{{ item.policy_rules }}"
+    create_role_password: "{{ item.password }}"
+    create_role_options: "{{ item.role_options }}"
+    create_role_mount_path: "{{ mount.name }}"
+  with_items: "{{ mount.roles }}"
diff --git a/roles/vault/tasks/bootstrap/gen_vault_certs.yml b/roles/vault/tasks/bootstrap/gen_vault_certs.yml
index 651c2ac49456360b89346ae3115f0a7d120b25c2..ce45385716ac4e0a5b21107968f3fe88ade4c2d4 100644
--- a/roles/vault/tasks/bootstrap/gen_vault_certs.yml
+++ b/roles/vault/tasks/bootstrap/gen_vault_certs.yml
@@ -1,29 +1,21 @@
 ---
-
-- name: boostrap/gen_vault_certs | Add the vault role
-  uri:
-    url: "{{ vault_leader_url }}/v1/{{ vault_ca_options.common_name }}/roles/vault"
-    headers: "{{ vault_headers }}"
-    method: POST
-    body_format: json
-    body: "{{ vault_default_role_permissions }}"
-    status_code: 204
-  when: inventory_hostname == groups.vault|first and vault_api_cert_needed
-
 - include: ../shared/issue_cert.yml
   vars:
+    issue_cert_common_name: "{{ vault_pki_mounts.vault.roles[0].name }}"
     issue_cert_alt_names: "{{ groups.vault + ['localhost'] }}"
     issue_cert_hosts: "{{ groups.vault }}"
     issue_cert_ip_sans: >-
         [
         {%- for host in groups.vault -%}
         "{{ hostvars[host]['ansible_default_ipv4']['address'] }}",
+        {%- if hostvars[host]['ip'] is defined -%}
+        "{{ hostvars[host]['ip'] }}",
+        {%- endif -%}
         {%- endfor -%}
         "127.0.0.1","::1"
         ]
-    issue_cert_mount_path: "{{ vault_ca_options.common_name }}"
+    issue_cert_mount_path: "{{ vault_pki_mounts.vault.name }}"
     issue_cert_path: "{{ vault_cert_dir }}/api.pem"
-    issue_cert_headers: "{{ hostvars[groups.vault|first]['vault_headers'] }}"
-    issue_cert_role: vault
+    issue_cert_role: "{{ vault_pki_mounts.vault.roles[0].name }}"
     issue_cert_url: "{{ vault_leader_url }}"
   when: vault_api_cert_needed
diff --git a/roles/vault/tasks/bootstrap/main.yml b/roles/vault/tasks/bootstrap/main.yml
index 768d9e03befd02307e7e7cdad81654647c8ce4e1..b87954ca7554fe33fc2cce5a7ced0d0257c59a49 100644
--- a/roles/vault/tasks/bootstrap/main.yml
+++ b/roles/vault/tasks/bootstrap/main.yml
@@ -1,5 +1,4 @@
 ---
-
 - include: ../shared/check_vault.yml
   when: inventory_hostname in groups.vault
 
@@ -7,9 +6,7 @@
   when: inventory_hostname in groups.vault
 
 - include: ../shared/find_leader.yml
-  when: inventory_hostname in groups.vault and vault_cluster_is_initialized|d()
-
-## Sync Certs
+  when: inventory_hostname in groups.vault and vault_cluster_is_initialized
 
 - include: sync_vault_certs.yml
   when: inventory_hostname in groups.vault
@@ -17,64 +14,52 @@
 - include: sync_etcd_certs.yml
   when: inventory_hostname in groups.etcd
 
-## Generate Certs
-
-# Start a temporary instance of Vault
 - include: start_vault_temp.yml
-  when: >-
-        inventory_hostname == groups.vault|first and
-        not vault_cluster_is_initialized
+  when: inventory_hostname == groups.vault|first and not vault_cluster_is_initialized
 
-# Set vault_leader_url for all nodes based on above
-- name: vault | bootstrap
+- name: vault | Set fact about vault leader url
   set_fact:
     vault_leader_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}"
   when: not vault_cluster_is_initialized
 
-# Ensure vault PKI mounts exists
-- include: ../shared/create_mount.yml
-  vars:
-    create_mount_path: "{{ vault_ca_options.common_name }}"
-    create_mount_default_lease_ttl: "{{ vault_default_lease_ttl }}"
-    create_mount_max_lease_ttl: "{{ vault_max_lease_ttl }}"
-    create_mount_description: "Vault Root CA"
-    create_mount_cert_dir: "{{ vault_cert_dir }}"
-    create_mount_config_ca_needed: "{{ not vault_ca_cert_needed }}"
+- include: create_mounts.yml
   when: inventory_hostname == groups.vault|first
 
-# Generate root CA certs for Vault if none exist
-- include: ../shared/gen_ca.yml
+- include: ../shared/auth_backend.yml
   vars:
-    gen_ca_cert_dir: "{{ vault_cert_dir }}"
-    gen_ca_mount_path: "{{ vault_ca_options.common_name }}"
-  when: >-
-        inventory_hostname in groups.vault and
-        not vault_cluster_is_initialized and
-        vault_ca_cert_needed
+    auth_backend_description: A Username/Password Auth Backend primarily used for services needing to issue certificates
+    auth_backend_path: userpass
+    auth_backend_type: userpass
+  when: inventory_hostname == groups.vault|first
 
-# Generate Vault API certs
-- include: gen_vault_certs.yml
-  when: inventory_hostname in groups.vault and vault_api_cert_needed
+- include: create_roles.yml
+  with_items:
+    - "{{ vault_pki_mounts.vault }}"
+    - "{{ vault_pki_mounts.etcd }}"
+  loop_control:
+    loop_var: mount
+  when: inventory_hostname in groups.vault
 
-# Ensure etcd PKI mounts exists
-- include: ../shared/create_mount.yml
+- include: ../shared/gen_ca.yml
   vars:
-    create_mount_path: "{{ vault_etcd_mount_path }}"
-    create_mount_default_lease_ttl: "{{ vault_etcd_default_lease_ttl }}"
-    create_mount_max_lease_ttl: "{{ vault_etcd_max_lease_ttl }}"
-    create_mount_description: "Etcd Root CA"
-    create_mount_cert_dir: "{{ vault_etcd_cert_dir }}"
-    create_mount_config_ca_needed: "{{ not vault_etcd_ca_cert_needed }}"
-  when: inventory_hostname == groups.vault|first
+    gen_ca_cert_dir: "{{ vault_pki_mounts.vault.cert_dir }}"
+    gen_ca_mount_path: "{{ vault_pki_mounts.vault.name }}"
+    gen_ca_vault_headers: "{{ vault_headers }}"
+    gen_ca_vault_options: "{{ vault_ca_options.vault }}"
+  when: >-
+        inventory_hostname in groups.vault
+        and not vault_cluster_is_initialized
+        and vault_ca_cert_needed
 
-# Generate root CA certs for etcd if none exist
 - include: ../shared/gen_ca.yml
   vars:
-    gen_ca_cert_dir: "{{ vault_etcd_cert_dir }}"
-    gen_ca_mount_path: "{{ vault_etcd_mount_path }}"
+    gen_ca_cert_dir: "{{ vault_pki_mounts.etcd.cert_dir }}"
+    gen_ca_mount_path: "{{ vault_pki_mounts.etcd.name }}"
+    gen_ca_vault_headers: "{{ vault_headers }}"
+    gen_ca_vault_options: "{{ vault_ca_options.etcd }}"
   when: inventory_hostname in groups.etcd and vault_etcd_ca_cert_needed
 
-- include: create_etcd_role.yml
+- include: gen_vault_certs.yml
+  when: inventory_hostname in groups.vault and vault_api_cert_needed
 
-# Update all host's CA bundle, etcd CA will be added in etcd role
 - include: ca_trust.yml
diff --git a/roles/vault/tasks/cluster/create_mounts.yml b/roles/vault/tasks/cluster/create_mounts.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b1be8c9fe3e2fd570d469f975229a482509880b0
--- /dev/null
+++ b/roles/vault/tasks/cluster/create_mounts.yml
@@ -0,0 +1,13 @@
+---
+- include: ../shared/create_mount.yml
+  vars:
+    create_mount_path: "{{ item.name }}"
+    create_mount_default_lease_ttl: "{{ item.default_lease_ttl }}"
+    create_mount_max_lease_ttl: "{{ item.max_lease_ttl }}"
+    create_mount_description: "{{ item.description }}"
+    create_mount_cert_dir: "{{ item.cert_dir }}"
+    create_mount_config_ca_needed: "{{ item.name != vault_pki_mounts.kube.name }}"
+  with_items:
+    - "{{ vault_pki_mounts.vault }}"
+    - "{{ vault_pki_mounts.etcd }}"
+    - "{{ vault_pki_mounts.kube }}"
diff --git a/roles/vault/tasks/cluster/create_roles.yml b/roles/vault/tasks/cluster/create_roles.yml
index 54aae815d96c37a1759abd6d6fa641133ec196a6..9314bfa8411f72267e781ef249c35a60ec9571d2 100644
--- a/roles/vault/tasks/cluster/create_roles.yml
+++ b/roles/vault/tasks/cluster/create_roles.yml
@@ -1,18 +1,10 @@
 ---
-- include: ../shared/auth_backend.yml
-  vars:
-    auth_backend_description: A Username/Password Auth Backend primarily used for services needing to issue certificates
-    auth_backend_path: userpass
-    auth_backend_type: userpass
-  when: inventory_hostname == groups.vault|first
-
 - include: ../shared/create_role.yml
   vars:
     create_role_name: "{{ item.name }}"
     create_role_group: "{{ item.group }}"
+    create_role_password: "{{ item.password }}"
     create_role_policy_rules: "{{ item.policy_rules }}"
     create_role_options: "{{ item.role_options }}"
-    create_role_mount_path: "{{ item.mount_path }}"
-  with_items:
-    - "{{ vault_etcd_role }}"
-    - "{{ vault_kube_role }}"
+    create_role_mount_path: "{{ vault_pki_mounts.kube.name }}"
+  with_items: "{{ vault_pki_mounts.kube.roles }}"
diff --git a/roles/vault/tasks/cluster/main.yml b/roles/vault/tasks/cluster/main.yml
index 7a5acba0a8cd09bd878ecf04b1bc0ffbc2800db6..9c7c83aaf5acc5487b294f5006e09004e2288d6f 100644
--- a/roles/vault/tasks/cluster/main.yml
+++ b/roles/vault/tasks/cluster/main.yml
@@ -5,8 +5,6 @@
 - include: ../shared/check_etcd.yml
   when: inventory_hostname in groups.vault
 
-## Vault Cluster Setup
-
 - include: configure.yml
   when: inventory_hostname in groups.vault
 
@@ -25,42 +23,23 @@
 - include: ../shared/find_leader.yml
   when: inventory_hostname in groups.vault
 
-- include: ../shared/create_mount.yml
-  vars:
-    create_mount_path: "{{ vault_ca_options.common_name }}"
-    create_mount_default_lease_ttl: "{{ vault_default_lease_ttl }}"
-    create_mount_max_lease_ttl: "{{ vault_max_lease_ttl }}"
-    create_mount_description: "Vault Root CA"
-    create_mount_cert_dir: "{{ vault_cert_dir }}"
-    create_mount_config_ca_needed: true
-  when: inventory_hostname == groups.vault|first
-
-- include: ../shared/create_mount.yml
-  vars:
-    create_mount_path: "{{ vault_etcd_mount_path }}"
-    create_mount_default_lease_ttl: "{{ vault_etcd_default_lease_ttl }}"
-    create_mount_max_lease_ttl: "{{ vault_etcd_max_lease_ttl }}"
-    create_mount_description: "Etcd Root CA"
-    create_mount_cert_dir: "{{ vault_etcd_cert_dir }}"
-    create_mount_config_ca_needed: true
-  when: inventory_hostname == groups.vault|first
-
-- include: ../shared/create_mount.yml
-  vars:
-    create_mount_path: "{{ vault_kube_mount_path }}"
-    create_mount_default_lease_ttl: "{{ vault_kube_default_lease_ttl }}"
-    create_mount_max_lease_ttl: "{{ vault_kube_max_lease_ttl }}"
-    create_mount_description: "Kubernetes Root CA"
-    create_mount_cert_dir: "{{ vault_kube_cert_dir }}"
-    create_mount_config_ca_needed: false
+- include: create_mounts.yml
   when: inventory_hostname == groups.vault|first
 
 - include: ../shared/gen_ca.yml
   vars:
-    gen_ca_cert_dir: "{{ vault_kube_cert_dir }}"
-    gen_ca_mount_path: "{{ vault_kube_mount_path }}"
+    gen_ca_cert_dir: "{{ vault_pki_mounts.kube.cert_dir }}"
+    gen_ca_mount_path: "{{ vault_pki_mounts.kube.name }}"
+    gen_ca_vault_headers: "{{ vault_headers }}"
+    gen_ca_vault_options: "{{ vault_ca_options.kube }}"
   when: inventory_hostname in groups.vault
 
-## Vault Policies, Roles, and Auth Backends
+- include: ../shared/auth_backend.yml
+  vars:
+    auth_backend_description: A Username/Password Auth Backend primarily used for services needing to issue certificates
+    auth_backend_path: userpass
+    auth_backend_type: userpass
+  when: inventory_hostname == groups.vault|first
 
 - include: create_roles.yml
+  when: inventory_hostname in groups.vault
diff --git a/roles/vault/tasks/shared/create_role.yml b/roles/vault/tasks/shared/create_role.yml
index fae45207ab6586f5b683e69b91f37882f729a503..d76e73f13aa6512b3c91244db1db5a6fc73d3f7c 100644
--- a/roles/vault/tasks/shared/create_role.yml
+++ b/roles/vault/tasks/shared/create_role.yml
@@ -1,5 +1,4 @@
 ---
-
 # The JSON inside JSON here is intentional (Vault API wants it)
 - name: create_role | Create a policy for the new role allowing issuing
   uri:
@@ -20,9 +19,10 @@
              {{ create_role_policy_rules | to_json + '\n' }}
              {%- endif -%}
     status_code: 204
-  when: inventory_hostname == groups[create_role_group]|first
+  delegate_to: "{{ groups.vault|first }}"
+  run_once: true
 
-- name: create_role | Create the new role in the {{ create_role_mount_path }} pki mount
+- name: create_role | Create {{ create_role_name }} role in the {{ create_role_mount_path }} pki mount
   uri:
     url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}/v1/{{ create_role_mount_path }}/roles/{{ create_role_name }}"
     headers: "{{ hostvars[groups.vault|first]['vault_headers'] }}"
@@ -35,15 +35,14 @@
           {{ create_role_options }}
           {%- endif -%}
     status_code: 204
-  when: inventory_hostname == groups[create_role_group]|first
+  delegate_to: "{{ groups.vault|first }}"
+  run_once: true
 
 ## Userpass based auth method
 
 - include: gen_userpass.yml
   vars:
-    gen_userpass_group: "{{ create_role_group }}"
-    gen_userpass_password: "{{ create_role_password|d(''|to_uuid) }}"
+    gen_userpass_password: "{{ create_role_password }}"
     gen_userpass_policies: "{{ create_role_name }}"
     gen_userpass_role: "{{ create_role_name }}"
     gen_userpass_username: "{{ create_role_name }}"
-  when: inventory_hostname in groups[create_role_group]
diff --git a/roles/vault/tasks/shared/gen_ca.yml b/roles/vault/tasks/shared/gen_ca.yml
index b80ebeb6b4f584b29c6b0e61bc5f594b5d2de183..291f42734f4932cddca85f0bdba5d711b0c68728 100644
--- a/roles/vault/tasks/shared/gen_ca.yml
+++ b/roles/vault/tasks/shared/gen_ca.yml
@@ -8,10 +8,10 @@
 - name: "bootstrap/gen_ca | Generate {{ gen_ca_mount_path }} root CA"
   uri:
     url: "{{ vault_leader_url }}/v1/{{ gen_ca_mount_path }}/root/generate/exported"
-    headers: "{{ vault_headers }}"
+    headers: "{{ gen_ca_vault_headers }}"
     method: POST
     body_format: json
-    body: "{{ vault_ca_options }}"
+    body: "{{ gen_ca_vault_options }}"
   register: vault_ca_gen
   delegate_to: "{{ groups.vault|first }}"
   run_once: true
diff --git a/roles/vault/tasks/shared/gen_userpass.yml b/roles/vault/tasks/shared/gen_userpass.yml
index 4ef3011717804dbfb81197ba726ddf0c21689814..5def39d0e468a1bdbc5f45b7eebde543cd19b9d4 100644
--- a/roles/vault/tasks/shared/gen_userpass.yml
+++ b/roles/vault/tasks/shared/gen_userpass.yml
@@ -1,5 +1,4 @@
 ---
-
 - name: shared/gen_userpass | Create the Username/Password combo for the role
   uri:
     url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}/v1/auth/userpass/users/{{ gen_userpass_username }}"
@@ -11,13 +10,13 @@
       password: "{{ gen_userpass_password }}"
       policies: "{{ gen_userpass_role }}"
     status_code: 204
-  when: inventory_hostname == groups[gen_userpass_group]|first
+  delegate_to: "{{ groups.vault|first }}"
+  run_once: true
 
 - name: shared/gen_userpass | Ensure destination directory exists
   file:
     path: "{{ vault_roles_dir }}/{{ gen_userpass_role }}"
     state: directory
-  when: inventory_hostname in groups[gen_userpass_group]
 
 - name: shared/gen_userpass | Copy credentials to all hosts in the group
   copy:
@@ -27,4 +26,3 @@
               'password': gen_userpass_password} | to_nice_json(indent=4)
              }}
     dest: "{{ vault_roles_dir }}/{{ gen_userpass_role }}/userpass"
-  when: inventory_hostname in groups[gen_userpass_group]
diff --git a/roles/vault/tasks/shared/issue_cert.yml b/roles/vault/tasks/shared/issue_cert.yml
index fa09bfd2b236062ba36f0b0b2c2a30d9a89c8299..24db599573121f7cf6b20c9689756349b182599b 100644
--- a/roles/vault/tasks/shared/issue_cert.yml
+++ b/roles/vault/tasks/shared/issue_cert.yml
@@ -11,7 +11,6 @@
 #   issue_cert_file_mode:   Mode of the placed cert file
 #   issue_cert_file_owner:  Owner of the placed cert file and directory
 #   issue_cert_format:      Format for returned data. Can be pem, der, or pem_bundle
-#   issue_cert_headers:     Headers passed into the issue request
 #   issue_cert_hosts:       List of hosts to distribute the cert to
 #   issue_cert_ip_sans:     Requested IP Subject Alternative Names, in a list
 #   issue_cert_mount_path:  Mount point in Vault to make the request to
@@ -27,7 +26,47 @@
     mode: "{{ issue_cert_dir_mode | d('0755') }}"
     owner: "{{ issue_cert_file_owner | d('root') }}"
 
-- name: "issue_cert | Generate the cert for {{ issue_cert_role }}"
+- name: "issue_cert | Read in the local credentials"
+  command: cat {{ vault_roles_dir }}/{{ issue_cert_role }}/userpass
+  register: vault_creds_cat
+  delegate_to: "{{  groups.vault|first }}"
+  run_once: true
+
+- name: gen_certs_vault | Set facts for read Vault Creds
+  set_fact:
+    user_vault_creds: "{{ vault_creds_cat.stdout|from_json }}"
+  delegate_to: "{{ groups.vault|first }}"
+  run_once: true
+
+- name: gen_certs_vault | Log into Vault and obtain an token
+  uri:
+    url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}/v1/auth/userpass/login/{{ user_vault_creds.username }}"
+    headers:
+      Accept: application/json
+      Content-Type: application/json
+    method: POST
+    body_format: json
+    body:
+      password: "{{ user_vault_creds.password }}"
+  register: vault_login_result
+  delegate_to: "{{ groups.vault|first }}"
+  run_once: true
+
+- name: gen_certs_vault | Set fact for vault_client_token
+  set_fact:
+    vault_client_token: "{{ vault_login_result.get('json', {}).get('auth', {}).get('client_token') }}"
+  run_once: true
+
+- name: gen_certs_vault | Set fact for Vault API token
+  set_fact:
+    issue_cert_headers:
+      Accept: application/json
+      Content-Type: application/json
+      X-Vault-Token: "{{ vault_client_token }}"
+  run_once: true
+  when: vault_client_token != ""
+
+- name: "issue_cert | Generate {{ issue_cert_path }} for {{ issue_cert_role }} role"
   uri:
     url: "{{ issue_cert_url }}/v1/{{ issue_cert_mount_path|d('pki') }}/issue/{{ issue_cert_role }}"
     headers: "{{ issue_cert_headers }}"
@@ -69,8 +108,8 @@
 
 - name: issue_cert | Copy certificate serial to all hosts
   copy:
-    content: "{{ hostvars[issue_cert_hosts|first]['issue_cert_result']['json']['data']['serial_number'] }}"
-    dest: "{{ issue_cert_path.rsplit('.', 1)|first }}.serial }}"
+    content: "{{ issue_cert_result['json']['data']['serial_number'] }}"
+    dest: "{{ issue_cert_path.rsplit('.', 1)|first }}.serial"
     group: "{{ issue_cert_file_group | d('root' )}}"
     mode: "{{ issue_cert_file_mode | d('0640') }}"
     owner: "{{ issue_cert_file_owner | d('root') }}"