diff --git a/roles/kubernetes/master/tasks/kubeadm-migrate-certs.yml b/roles/kubernetes/master/tasks/kubeadm-migrate-certs.yml
index 58eaaa66f7bf469b52aa873d96a7e815ea1e8ce6..83bfbb22ad59dea8eef811c7f017132695e3e898 100644
--- a/roles/kubernetes/master/tasks/kubeadm-migrate-certs.yml
+++ b/roles/kubernetes/master/tasks/kubeadm-migrate-certs.yml
@@ -9,6 +9,10 @@
     - {src: apiserver-key.pem, dest: apiserver.key}
     - {src: ca.pem, dest: ca.crt}
     - {src: ca-key.pem, dest: ca.key}
+    - {src: front-proxy-ca.pem, dest: front-proxy-ca.crt}
+    - {src: front-proxy-ca-key.pem, dest: front-proxy-ca.key}
+    - {src: front-proxy-client.pem, dest: front-proxy-client.crt}
+    - {src: front-proxy-client-key.pem, dest: front-proxy-client.key}
     - {src: service-account-key.pem, dest: sa.pub}
     - {src: service-account-key.pem, dest: sa.key}
   register: kubeadm_copy_old_certs
diff --git a/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2 b/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
index 687ca415d3e21337e74d8e0007b0e0ef46777dec..e0054686a2ee2b10aa9fb853ea9054a3dc54db06 100644
--- a/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
+++ b/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
@@ -111,7 +111,7 @@ spec:
     - --feature-gates={{ kube_feature_gates|join(',') }}
 {% endif %}
 {% if kube_version | version_compare('v1.9', '>=') %}
-    - --requestheader-client-ca-file={{ kube_cert_dir }}/ca.pem
+    - --requestheader-client-ca-file={{ kube_cert_dir }}/front-proxy-ca.pem
     - --requestheader-allowed-names=front-proxy-client
     - --requestheader-extra-headers-prefix=X-Remote-Extra-
     - --requestheader-group-headers=X-Remote-Group
diff --git a/roles/kubernetes/secrets/defaults/main.yml b/roles/kubernetes/secrets/defaults/main.yml
index f0d10711d306a7aa6cfbcc2a7a96245e0ef22803..cda85eeb27a7a3eb35b01c5aa2a8280261bf2892 100644
--- a/roles/kubernetes/secrets/defaults/main.yml
+++ b/roles/kubernetes/secrets/defaults/main.yml
@@ -1,3 +1,4 @@
 ---
 kube_cert_group: kube-cert
 kube_vault_mount_path: kube
+front_proxy_vault_mount_path: front-proxy
diff --git a/roles/kubernetes/secrets/files/make-ssl.sh b/roles/kubernetes/secrets/files/make-ssl.sh
index 1c34fc69dba0b67e46c1686acb6a3e9a52653e99..2a4b930ea2b1f2b9b0e9ced51991b62ea1c3c816 100755
--- a/roles/kubernetes/secrets/files/make-ssl.sh
+++ b/roles/kubernetes/secrets/files/make-ssl.sh
@@ -72,6 +72,15 @@ else
     openssl req -x509 -new -nodes -key ca-key.pem -days 36500 -out ca.pem -subj "/CN=kube-ca" > /dev/null 2>&1
 fi
 
+# Front proxy client CA
+if [ -e "$SSLDIR/front-proxy-ca-key.pem" ]; then
+    # Reuse existing front proxy CA
+    cp $SSLDIR/{front-proxy-ca.pem,front-proxy-ca-key.pem} .
+else
+    openssl genrsa -out front-proxy-ca-key.pem 2048 > /dev/null 2>&1
+    openssl req -x509 -new -nodes -key front-proxy-ca-key.pem -days 36500 -out front-proxy-ca.pem -subj "/CN=front-proxy-ca" > /dev/null 2>&1
+fi
+
 gen_key_and_cert() {
     local name=$1
     local subject=$2
@@ -80,6 +89,14 @@ gen_key_and_cert() {
     openssl x509 -req -in ${name}.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out ${name}.pem -days 36500 -extensions v3_req -extfile ${CONFIG} > /dev/null 2>&1
 }
 
+gen_key_and_cert_front_proxy() {
+    local name=$1
+    local subject=$2
+    openssl genrsa -out ${name}-key.pem 2048 > /dev/null 2>&1
+    openssl req -new -key ${name}-key.pem -out ${name}.csr -subj "${subject}" -config ${CONFIG} > /dev/null 2>&1
+    openssl x509 -req -in ${name}.csr -CA front-proxy-ca.pem -CAkey front-proxy-ca-key.pem -CAcreateserial -out ${name}.pem -days 36500 -extensions v3_req -extfile ${CONFIG} > /dev/null 2>&1
+}
+
 # Admins
 if [ -n "$MASTERS" ]; then
 
@@ -105,7 +122,7 @@ if [ -n "$MASTERS" ]; then
     # kube-controller-manager
     gen_key_and_cert "kube-controller-manager" "/CN=system:kube-controller-manager"
     # metrics aggregator
-    gen_key_and_cert "front-proxy-client" "/CN=front-proxy-client"
+    gen_key_and_cert_front_proxy "front-proxy-client" "/CN=front-proxy-client"
 
     for host in $MASTERS; do
         cn="${host%%.*}"
diff --git a/roles/kubernetes/secrets/tasks/check-certs.yml b/roles/kubernetes/secrets/tasks/check-certs.yml
index 07820edf7bacfa8ce850a57c41b810b555ba6a9f..110ffa8981c842a4643e51172b1ca2178a344a7a 100644
--- a/roles/kubernetes/secrets/tasks/check-certs.yml
+++ b/roles/kubernetes/secrets/tasks/check-certs.yml
@@ -48,6 +48,8 @@
        '{{ kube_cert_dir }}/kube-scheduler-key.pem',
        '{{ kube_cert_dir }}/kube-controller-manager.pem',
        '{{ kube_cert_dir }}/kube-controller-manager-key.pem',
+       '{{ kube_cert_dir }}/front-proxy-ca.pem',
+       '{{ kube_cert_dir }}/front-proxy-ca-key.pem',
        '{{ kube_cert_dir }}/front-proxy-client.pem',
        '{{ kube_cert_dir }}/front-proxy-client-key.pem',
        '{{ kube_cert_dir }}/service-account-key.pem',
@@ -72,6 +74,7 @@
       {% for cert in ['apiserver.pem', 'apiserver-key.pem',
                       'kube-scheduler.pem','kube-scheduler-key.pem',
                       'kube-controller-manager.pem','kube-controller-manager-key.pem',
+                      'front-proxy-ca.pem','front-proxy-ca-key.pem',
                       'front-proxy-client.pem','front-proxy-client-key.pem',
                       'service-account-key.pem'] -%}
         {% set cert_file = "%s/%s.pem"|format(kube_cert_dir, cert) %}
diff --git a/roles/kubernetes/secrets/tasks/gen_certs_script.yml b/roles/kubernetes/secrets/tasks/gen_certs_script.yml
index c39f606ad43f85ea29d7c4c0d7d016891412d378..72ff6b46917d0c2505395b9b1f1640c8050ae0ed 100644
--- a/roles/kubernetes/secrets/tasks/gen_certs_script.yml
+++ b/roles/kubernetes/secrets/tasks/gen_certs_script.yml
@@ -73,6 +73,8 @@
                        'kube-scheduler-key.pem',
                        'kube-controller-manager.pem',
                        'kube-controller-manager-key.pem',
+                       'front-proxy-ca.pem',
+                       'front-proxy-ca-key.pem',
                        'front-proxy-client.pem',
                        'front-proxy-client-key.pem',
                        'service-account-key.pem',
@@ -85,6 +87,8 @@
                       'admin-{{ inventory_hostname }}-key.pem',
                       'apiserver.pem',
                       'apiserver-key.pem',
+                      'front-proxy-ca.pem',
+                      'front-proxy-ca-key.pem',
                       'front-proxy-client.pem',
                       'front-proxy-client-key.pem',
                       'service-account-key.pem',
diff --git a/roles/kubernetes/secrets/tasks/gen_certs_vault.yml b/roles/kubernetes/secrets/tasks/gen_certs_vault.yml
index cc16b749bed5ff3ea060c48ac0faa86e4d81f10f..05afdfcf8f620419ff0c1ce0df1e1d8ee81c38b7 100644
--- a/roles/kubernetes/secrets/tasks/gen_certs_vault.yml
+++ b/roles/kubernetes/secrets/tasks/gen_certs_vault.yml
@@ -98,6 +98,8 @@
 - include_tasks: ../../../vault/tasks/shared/issue_cert.yml
   vars:
     issue_cert_common_name: "front-proxy-client"
+    issue_cert_copy_ca: "{{ item == kube_front_proxy_clients_certs_needed|first }}"
+    issue_cert_ca_filename: front-proxy-ca.pem
     issue_cert_alt_names: "{{ kube_cert_alt_names }}"
     issue_cert_file_group: "{{ kube_cert_group }}"
     issue_cert_file_owner: kube
@@ -115,7 +117,7 @@
     issue_cert_path: "{{ item }}"
     issue_cert_role: front-proxy-client
     issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}"
-    issue_cert_mount_path: "{{ kube_vault_mount_path }}"
+    issue_cert_mount_path: "{{ front_proxy_vault_mount_path }}"
   with_items: "{{ kube_front_proxy_clients_certs_needed|d([]) }}"
   when: inventory_hostname in groups['kube-master']
   notify: set secret_changed
diff --git a/roles/kubernetes/secrets/tasks/sync_kube_master_certs.yml b/roles/kubernetes/secrets/tasks/sync_kube_master_certs.yml
index 02c512a4e4b7fe7892b488a45201680786e4ac01..50e1a01e784dde373beff14e9be5277690c12bbb 100644
--- a/roles/kubernetes/secrets/tasks/sync_kube_master_certs.yml
+++ b/roles/kubernetes/secrets/tasks/sync_kube_master_certs.yml
@@ -44,6 +44,18 @@
   set_fact:
     sync_file_results: []
 
+- include_tasks: ../../../vault/tasks/shared/sync_file.yml
+  vars:
+    sync_file: front-proxy-ca.pem
+    sync_file_dir: "{{ kube_cert_dir }}"
+    sync_file_group: "{{ kube_cert_group }}"
+    sync_file_hosts: "{{ groups['kube-master'] }}"
+    sync_file_owner: kube
+
+- name: sync_kube_master_certs | Unset sync_file_results after front-proxy-ca.pem
+  set_fact:
+    sync_file_results: []
+
 - include_tasks: ../../../vault/tasks/shared/sync_file.yml
   vars:
     sync_file: "{{ item }}"
diff --git a/roles/vault/defaults/main.yml b/roles/vault/defaults/main.yml
index 8e5ad08a08371de29bd6c7b07d517e86dc628ce5..f19c734383614379c379e53ef85727c1c749c39e 100644
--- a/roles/vault/defaults/main.yml
+++ b/roles/vault/defaults/main.yml
@@ -97,6 +97,11 @@ vault_ca_options:
     format: pem
     ttl: "{{ vault_max_lease_ttl }}"
     exclude_cn_from_sans: true
+  front_proxy:
+    common_name: front-proxy
+    format: pem
+    ttl: "{{ vault_max_lease_ttl }}"
+    exclude_cn_from_sans: true
 
 vault_client_headers:
   Accept: "application/json"
@@ -164,11 +169,18 @@ vault_pki_mounts:
           allow_any_name: true
           enforce_hostnames: false
           organization: "system:node-proxier"
+  front_proxy:
+    name: front-proxy
+    default_lease_ttl: "{{ vault_default_lease_ttl }}"
+    max_lease_ttl: "{{ vault_max_lease_ttl }}"
+    description: "Kubernetes Front Proxy CA"
+    cert_dir: "{{ vault_kube_cert_dir }}"
+    roles:
       - name: front-proxy-client
         group: k8s-cluster
-        password: "{{ lookup('password', inventory_dir + '/credentials/vault/kube-proxy.creds length=15') }}"
+        password: "{{ lookup('password', inventory_dir + '/credentials/vault/front-proxy-client.creds length=15') }}"
         policy_rules: default
         role_options:
           allow_any_name: true
           enforce_hostnames: false
-          organization: "system:front-proxy"
+          organization: "system:front-proxy"
\ No newline at end of file
diff --git a/roles/vault/tasks/cluster/create_mounts.yml b/roles/vault/tasks/cluster/create_mounts.yml
index c6e075698db24908da2f091d25ddd02ce04af0fa..087430942cf4389c972ad84e925c3bfddd9fb283 100644
--- a/roles/vault/tasks/cluster/create_mounts.yml
+++ b/roles/vault/tasks/cluster/create_mounts.yml
@@ -6,8 +6,9 @@
     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
+    create_mount_config_ca_needed: item.name != vault_pki_mounts.kube.name and item.name != vault_pki_mounts.front_proxy.name
   with_items:
     - "{{ vault_pki_mounts.vault }}"
     - "{{ vault_pki_mounts.etcd }}"
     - "{{ vault_pki_mounts.kube }}"
+    - "{{ vault_pki_mounts.front_proxy }}"
diff --git a/roles/vault/tasks/cluster/main.yml b/roles/vault/tasks/cluster/main.yml
index 65b9dae9b8e97775124664280c742a34f29f6676..7f535d0682593286869c7939ec18e728a6437a7d 100644
--- a/roles/vault/tasks/cluster/main.yml
+++ b/roles/vault/tasks/cluster/main.yml
@@ -35,6 +35,14 @@
     gen_ca_copy_group: "kube-master"
   when: inventory_hostname in groups.vault
 
+- include_tasks: ../shared/gen_ca.yml
+  vars:
+    gen_ca_cert_dir: "{{ vault_pki_mounts.front_proxy.cert_dir }}"
+    gen_ca_mount_path: "{{ vault_pki_mounts.front_proxy.name }}"
+    gen_ca_vault_headers: "{{ vault_headers }}"
+    gen_ca_vault_options: "{{ vault_ca_options.front_proxy }}"
+  when: inventory_hostname in groups.vault
+
 - include_tasks: ../shared/auth_backend.yml
   vars:
     auth_backend_description: A Username/Password Auth Backend primarily used for services needing to issue certificates
@@ -47,6 +55,7 @@
     - "{{ vault_pki_mounts.vault }}"
     - "{{ vault_pki_mounts.etcd }}"
     - "{{ vault_pki_mounts.kube }}"
+    - "{{ vault_pki_mounts.front_proxy }}"
   loop_control:
     loop_var: mount
   when: inventory_hostname in groups.vault
diff --git a/roles/vault/tasks/shared/issue_cert.yml b/roles/vault/tasks/shared/issue_cert.yml
index 1ba90ea77b5d7af39284d8c8485ec30d548d82ef..36a42efaaa76c1eb6f45efae25069ac85f4c8be3 100644
--- a/roles/vault/tasks/shared/issue_cert.yml
+++ b/roles/vault/tasks/shared/issue_cert.yml
@@ -6,6 +6,7 @@
 #   issue_cert_alt_name:    Requested Subject Alternative Names, in a list.
 #   issue_cert_common_name: Common Name included in the cert
 #   issue_cert_copy_ca:     Copy issuing CA cert needed
+#   issue_cert_ca_filename: Filename for copied issuing CA cert (default ca.pem)
 #   issue_cert_dir_mode:    Mode of the placed cert directory
 #   issue_cert_file_group:  Group of the placed cert file and directory
 #   issue_cert_file_mode:   Mode of the placed cert file
@@ -100,7 +101,7 @@
 - name: issue_cert | Copy issuing CA cert
   copy:
     content: "{{ issue_cert_result['json']['data']['issuing_ca'] }}\n"
-    dest: "{{ issue_cert_path | dirname }}/ca.pem"
+    dest: "{{ issue_cert_path | dirname }}/{{ issue_cert_ca_filename | default('ca.pem') }}"
     group: "{{ issue_cert_file_group | d('root' )}}"
     mode: "{{ issue_cert_file_mode | d('0644') }}"
     owner: "{{ issue_cert_file_owner | d('root') }}"