Global trust for SaltCA, distribute ca.crt
diff --git a/.kitchen.yml b/.kitchen.yml
index 6e852bd..39df9e8 100644
--- a/.kitchen.yml
+++ b/.kitchen.yml
@@ -9,6 +9,7 @@
   salt_install: bootstrap
   salt_bootstrap_url: https://bootstrap.saltstack.com
   salt_version: latest
+  salt_minion_id: salt.ci.local
   require_chef: false
   log_level: error
   formula: salt
@@ -96,13 +97,17 @@
           base:
             "*":
               - common
+              - minion_pki
               - master_api
               - master_acl
               - master_ssh_key
               - master_ssh_password
               - master_ssh_root
               - master_handler
+              - minion_pki_cert
       pillars-from-files:
+        minion_pki.sls: tests/pillar/minion_pki_ca.sls
+        minion_pki_cert.sls: tests/pillar/minion_pki_cert.sls
         master_api.sls: tests/pillar/master_api.sls
         master_acl.sls: tests/pillar/master_acl.sls
         master_ssh_key.sls: tests/pillar/master_ssh_minion_key.sls
diff --git a/salt/minion/cert.sls b/salt/minion/cert.sls
index 34255c4..e25534e 100644
--- a/salt/minion/cert.sls
+++ b/salt/minion/cert.sls
@@ -1,5 +1,7 @@
 {%- from "salt/map.jinja" import minion with context %}
+
 {%- if minion.enabled %}
+{%- if minion.cert is defined %}
 
 {%- for cert_name,cert in minion.get('cert', {}).iteritems() %}
 {%- set rowloop = loop %}
@@ -10,6 +12,11 @@
 {%- set key_dir = key_file|replace(key_file.split('/')[-1], "") %}
 {%- set cert_dir = cert_file|replace(cert_file.split('/')[-1], "") %}
 {%- set ca_dir = ca_file|replace(ca_file.split('/')[-1], "") %}
+{%- if grains.os_family == 'RedHat' %}
+{%- set cacerts_dir='/etc/pki/ca-trust/source/anchors' %}
+{%- else %}
+{%- set cacerts_dir='/usr/local/share/ca-certificates' %}
+{%- endif %}
 
 {# Only ensure directories exists, don't touch permissions, etc. #}
 salt_minion_cert_{{ cert_name }}_dirs:
@@ -43,11 +50,21 @@
 
 {{ cert_file }}:
   x509.certificate_managed:
-    - ca_server: {{ cert.host }}
+    {% if cert.host is defined %}- ca_server: {{ cert.host }}{%- endif %}
+    {% if cert.authority is defined and cert.signing_policy is defined %}
     - signing_policy: {{ cert.authority }}_{{ cert.signing_policy }}
+    {%- endif %}
     - public_key: {{ key_file }}
     - CN: "{{ cert.common_name }}"
-    {%- if cert.alternative_names is defined %}
+    {% if cert.state is defined %}- ST: {{ cert.state }}{%- endif %}
+    {% if cert.country is defined %}- C: {{ cert.country }}{%- endif %}
+    {% if cert.locality is defined %}- L: {{ cert.locality }}{%- endif %}
+    {% if cert.organization is defined %}- O: {{ cert.organization }}{%- endif %}
+    {% if cert.signing_private_key is defined and cert.signing_cert is defined %}
+    - signing_private_key: "{{ cert.signing_private_key }}"
+    - signing_cert: "{{ cert.signing_cert }}"
+    {%- endif %}
+    {% if cert.alternative_names is defined %}
     - subjectAltName: "{{ cert.alternative_names }}"
     {%- endif %}
     {%- if cert.extended_key_usage is defined %}
@@ -75,6 +92,7 @@
     - watch:
       - x509: {{ cert_file }}
 
+{%- if cert.host is defined %}
 {%- for ca_path,ca_cert in salt['mine.get'](cert.host, 'x509.get_pem_entries').get(cert.host, {}).iteritems() %}
 
 {%- if '/etc/pki/ca/'+cert.authority in ca_path %}
@@ -97,30 +115,17 @@
     - watch:
       - x509: {{ ca_file }}
 
-{%- if grains.os_family == 'Debian' %}
-
-salt_ca_certificates_packages_{{ rowloop.index }}:
-  pkg.installed:
-    - name: ca-certificates
-
-{{ ca_file }}_{{ rowloop.index }}_debian_symlink:
+{{ ca_file }}_{{ rowloop.index }}_local_trusted_symlink:
   file.symlink:
-    - name: "/usr/local/share/ca-certificates/ca-{{ cert.authority }}.crt"
+    - name: "{{ cacerts_dir }}/ca-{{ cert.authority }}.crt"
     - target: {{ ca_file }}
     - watch_in:
-      - cmd: salt_update_certificates_{{ rowloop.index }}
-    - require:
-      - pkg: salt_ca_certificates_packages_{{ rowloop.index }}
-
-salt_update_certificates_{{ rowloop.index }}:
-  cmd.wait:
-    - name: update-ca-certificates
-
-{%- endif %}
+      - cmd: salt_update_certificates
 
 {%- endif %}
 
 {%- endfor %}
+{%- endif %}
 
 {%- if cert.all_file is defined %}
 salt_minion_cert_{{ cert_name }}_all:
@@ -148,3 +153,48 @@
 {%- endfor %}
 
 {%- endif %}
+
+salt_ca_certificates_packages:
+  pkg.installed:
+{%- if grains.os_family == 'Debian' %}
+    - name: ca-certificates
+{%- elif grains.os_family == 'RedHat' %}
+    - name: ca-certificates
+{%- else %}
+    - name: []
+{%- endif %}
+
+salt_update_certificates:
+  cmd.wait:
+{%- if grains.os_family == 'Debian' %}
+    - name: "update-ca-certificates{% if minion.get('ca_certificates_cleanup') %} --fresh {% endif %}"
+{%- elif grains.os_family == 'RedHat' %}
+    - name: "update-ca-trust extract"
+{%- else %}
+    - name: true
+{%- endif %}
+    - require:
+      - pkg: salt_ca_certificates_packages
+
+{%- if minion.get('cert', {}).get('trust_salt_ca', 'True') %}
+{%- for ca_host, certs in salt['mine.get']('*/ca*', 'x510.get_pem_entries').iteritems() %}
+{%- for ca_path, ca_cert in certs.iteritems() %}
+{%- set cacert_file="ca-"+ca_path.split("/")[4]+".crt" %}
+
+salt_cert_{{ cacerts_dir }}/{{ cacert_file }}:
+  file.managed:
+  - name: {{ cacerts_dir }}/{{ cacert_file }}
+  - contents: |
+      {{ ca_cert | indent(8) }}
+  - makedirs: True
+  - show_changes: True
+  - follow_symlinks: True
+  - watch_in:
+    - cmd: salt_update_certificates
+
+{%- endfor %}
+{%- endfor %}
+{%- endif %}
+
+{%- endif %}
+
diff --git a/salt/minion/init.sls b/salt/minion/init.sls
index f81ca43..477b0b9 100644
--- a/salt/minion/init.sls
+++ b/salt/minion/init.sls
@@ -7,6 +7,4 @@
 {%- if pillar.salt.minion.ca is defined %}
 - salt.minion.ca
 {%- endif %}
-{%- if pillar.salt.minion.cert is defined %}
 - salt.minion.cert
-{%- endif %}
\ No newline at end of file
diff --git a/tests/pillar/minion_pki_ca.sls b/tests/pillar/minion_pki_ca.sls
index 453d1f7..935014b 100644
--- a/tests/pillar/minion_pki_ca.sls
+++ b/tests/pillar/minion_pki_ca.sls
@@ -2,8 +2,8 @@
   minion:
     enabled: true
     ca:
-      vagrant:
-        common_name: Test CA
+      salt-ca-default:
+        common_name: Test CA Default
         country: Czech
         state: Prague
         locality: Zizkov
@@ -23,3 +23,24 @@
           ca_intermediate:
             type: v3_intermediate_ca
             minions: '*'
+      salt-ca-test:
+        common_name: Test CA Testing
+        country: Czech
+        state: Prague
+        locality: Karlin
+        days_valid:
+          authority: 3650
+          certificate: 90
+        signing_policy:
+          cert_server:
+            type: v3_edge_cert_server
+            minions: '*'
+          cert_client:
+            type: v3_edge_cert_client
+            minions: '*'
+          ca_edge:
+            type: v3_edge_ca
+            minions: '*'
+          ca_intermediate:
+            type: v3_intermediate_ca
+            minions: '*'
diff --git a/tests/pillar/minion_pki_cert.sls b/tests/pillar/minion_pki_cert.sls
new file mode 100644
index 0000000..14b0194
--- /dev/null
+++ b/tests/pillar/minion_pki_cert.sls
@@ -0,0 +1,59 @@
+salt:
+  #master:
+  # enabled: true
+  # accept_policy:
+  #   open_mode
+  # peer:
+  #   '.*':
+  #     - x509.sign_remote_certificate
+  minion:
+    enabled: true
+    cert:
+      ceph_cert:
+          alternative_names:
+              IP:127.0.0.1,DNS:salt.ci.local,DNS:ceph.ci.local,DNS:radosgw.ci.local,DNS:swift.ci.local
+          cert_file:
+              /srv/salt/pki/ci/ceph.ci.local.crt
+          common_name:
+              ceph_mon.ci.local
+          key_file:
+              /srv/salt/pki/ci/ceph.ci.local.key
+          country: CZ
+          state: Prague
+          locality: Karlin
+          signing_cert:
+              /etc/pki/ca/salt-ca-test/ca.crt
+          signing_private_key:
+              /etc/pki/ca/salt-ca-test/ca.key
+          # Kitchen-Salt CI trigger `salt-call --local`, below attributes
+          # can't be used as there is no required SaltMaster connectivity
+          authority:
+              salt-ca-test
+          #host:
+          #    salt.ci.local
+          #signing_policy:
+          #    cert_server
+      proxy_cert:
+          alternative_names:
+              IP:127.0.0.1,DNS:salt.ci.local,DNS:proxy.ci.local
+          cert_file:
+              /srv/salt/pki/ci/prx.ci.local.crt
+          common_name:
+              prx.ci.local
+          key_file:
+              /srv/salt/pki/ci/prx.ci.local.key
+          country: CZ
+          state: Prague
+          locality: Zizkov
+          signing_cert:
+              /etc/pki/ca/salt-ca-default/ca.crt
+          signing_private_key:
+              /etc/pki/ca/salt-ca-default/ca.key
+          # Kitchen-Salt CI trigger `salt-call --local`, below attributes
+          # can't be used as there is no required SaltMaster connectivity
+          authority:
+             salt-ca-default
+          #host:
+          #   salt.ci.local
+          #signing_policy:
+          #   cert_server
diff --git a/tests/pillar/minion_pki_cert_extended.sls b/tests/pillar/minion_pki_cert_extended.sls
new file mode 100644
index 0000000..f395bf7
--- /dev/null
+++ b/tests/pillar/minion_pki_cert_extended.sls
@@ -0,0 +1,45 @@
+salt:
+  #master:
+  # enabled: true
+  # accept_policy:
+  #   open_mode
+  # peer:
+  #   .*:
+  #     - x509.sign_remote_certificate
+  minion:
+    enabled: true
+    cert:
+      ceph_cert:
+          all_file:
+              /srv/salt/pki/ci/ceph-with-key.ci.local.pem
+          alternative_names:
+              IP:127.0.0.1,DNS:salt.ci.local,DNS:ceph.ci.local,DNS:radosgw.ci.local,DNS:swift.ci.local
+          cert_file:
+              /srv/salt/pki/ci/ceph.ci.local.crt
+          common_name:
+              ceph_mon.ci.local
+          key_file:
+              /srv/salt/pki/ci/ceph.ci.local.key
+          authority:
+              salt-ca-test
+          host:
+              salt.ci.local
+          signing_policy:
+              cert_server
+      proxy_cert:
+          all_file:
+              /srv/salt/pki/ci/prx-with-key.ci.local.pem
+          alternative_names:
+              IP:127.0.0.1,DNS:salt.ci.local,DNS:proxy.ci.local
+          cert_file:
+              /srv/salt/pki/ci/prx.ci.local.crt
+          common_name:
+              prx.ci.local
+          key_file:
+              /srv/salt/pki/ci/prx.ci.local.key
+          authority:
+             salt-ca-default
+          host:
+             salt.ci.local
+          signing_policy:
+             cert_server