add support for etcd over ssl

Change-Id: If777a3835d6f8cdd0e4565d149cc2070580dcd9c
diff --git a/README.rst b/README.rst
index 0fa35e4..cf05053 100644
--- a/README.rst
+++ b/README.rst
@@ -8,6 +8,26 @@
 Sample pillars
 ==============
 
+Certificates
+-------------
+
+Use certificate authentication (for peers and clients). Certificates must be prepared in advance.
+
+.. code-block:: yaml
+
+    etcd:
+      server:
+        enabled: true
+        ssl:
+          enabled: true
+        bind:
+          host: 10.0.175.101
+        token: $(uuidgen)
+        members:
+        - host: 10.0.175.101
+          name: etcd01
+          port: 4001
+
 Single etcd service
 ---------------------
 
diff --git a/etcd/files/configenv b/etcd/files/configenv
new file mode 100644
index 0000000..43550b4
--- /dev/null
+++ b/etcd/files/configenv
@@ -0,0 +1,8 @@
+{%- from "etcd/map.jinja" import server with context %}
+# this file can be sourced and used to configure etcdctl
+export ETCDCTL_ENDPOINT="{%- if server.bind.host != '127.0.0.1' %}http{% if server.get('ssl', {}).get('enabled') %}s{% endif %}://{{ server.bind.host }}:4001,{% endif %}http{% if server.get('ssl', {}).get('enabled') %}s{% endif %}://127.0.0.1:4001"
+{%- if server.get('ssl', {}).get('enabled') %}
+export ETCDCTL_CA_FILE=/var/lib/etcd/ca.pem
+export ETCDCTL_CERT_FILE=/var/lib/etcd/etcd-server.pem
+export ETCDCTL_KEY_FILE=/var/lib/etcd/etcd-server.key
+{% endif %}
diff --git a/etcd/files/default b/etcd/files/default
index 3224dff..72d975c 100644
--- a/etcd/files/default
+++ b/etcd/files/default
@@ -11,7 +11,7 @@
 ## default: "off"
 ETCD_PROXY="on"
 
-ETCD_INITIAL_CLUSTER="{% for member in server.members %}{{ member.name }}={%- if server.bind.host == '127.0.0.1' %}http://127.0.0.1:2380{% else %}http://{{ member.host }}:2380{% if not loop.last %},{% endif %}{% endif %}{% endfor %}"
+ETCD_INITIAL_CLUSTER="{% for member in server.members %}{{ member.name }}={%- if server.bind.host == '127.0.0.1' %}http{% if server.get('ssl', {}).get('enabled') %}s{% endif %}://127.0.0.1:2380{% else %}http{% if server.get('ssl', {}).get('enabled') %}s:{% endif %}//{{ member.host }}:2380{% if not loop.last %},{% endif %}{% endif %}{% endfor %}"
 
 ##### -proxy-failure-wait
 ## Time (in milliseconds) an endpoint will be held in a failed state before being
@@ -93,7 +93,7 @@
 ## invalid example: "http://example.com:2380" (domain name is invalid for binding)
 ## default: "http://localhost:2380,http://localhost:7001"
 # ETCD_LISTEN_PEER_URLS="http://localhost:2380,http://localhost:7001"
-ETCD_LISTEN_PEER_URLS="http://{{ server.bind.host }}:2380"
+ETCD_LISTEN_PEER_URLS="http{% if server.get('ssl', {}).get('enabled') %}s{% endif %}://{{ server.bind.host }}:2380"
 
 ##### -listen-client-urls
 ## List of URLs to listen on for client traffic. This flag tells the etcd to accept
@@ -108,7 +108,7 @@
 ## invalid example: "http://example.com:2379" (domain name is invalid for binding)
 ## default: "http://localhost:2379,http://localhost:4001"
 # ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://localhost:4001"
-ETCD_LISTEN_CLIENT_URLS="{%- if server.bind.host != '127.0.0.1' %}http://{{ server.bind.host }}:4001,{% endif %}http://127.0.0.1:4001"
+ETCD_LISTEN_CLIENT_URLS="{%- if server.bind.host != '127.0.0.1' %}http{% if server.get('ssl', {}).get('enabled') %}s{% endif %}://{{ server.bind.host }}:4001,{% endif %}http{% if server.get('ssl', {}).get('enabled') %}s{% endif %}://127.0.0.1:4001"
 ##### -max-snapshots
 ## Maximum number of snapshot files to retain (0 is unlimited)
 ## default: 5
@@ -140,7 +140,7 @@
 ## example: "http://example.com:2380, http://10.0.0.1:2380"
 ## default: "http://localhost:2380,http://localhost:7001"
 # ETCD_INITIAL_ADVERTISE_PEER_URLS="http://localhost:2380,http://localhost:7001"
-ETCD_INITIAL_ADVERTISE_PEER_URLS="http://{{ server.bind.host }}:2380"
+ETCD_INITIAL_ADVERTISE_PEER_URLS="http{% if server.get('ssl', {}).get('enabled') %}s{% endif %}://{{ server.bind.host }}:2380"
 
 ##### -initial-cluster
 ## initial cluster configuration for bootstrapping.
@@ -148,7 +148,7 @@
 ## The default uses `default` for the key because this is the default for the `-name` flag.
 ## default: "default=http://localhost:2380,default=http://localhost:7001"
 # ETCD_INITIAL_CLUSTER="default=http://localhost:2380,default=http://localhost:7001"
-ETCD_INITIAL_CLUSTER="{% for member in server.members %}{{ member.name }}={%- if server.bind.host == '127.0.0.1' %}http://127.0.0.1:2380{% else %}http://{{ member.host }}:2380{% if not loop.last %},{% endif %}{% endif %}{% endfor %}"
+ETCD_INITIAL_CLUSTER="{% for member in server.members %}{{ member.name }}={%- if server.bind.host == '127.0.0.1' %}http{% if server.get('ssl', {}).get('enabled') %}s{% endif %}://127.0.0.1:2380{% else %}http{% if server.get('ssl', {}).get('enabled') %}s{% endif %}://{{ member.host }}:2380{% if not loop.last %},{% endif %}{% endif %}{% endfor %}"
 ##### -initial-cluster-state
 ## Initial cluster state ("new" or "existing"). Set to `new` for all members
 ## present during initial static or DNS bootstrapping. If this option is set to
@@ -178,7 +178,7 @@
 ## (memory, file descriptors) are eventually depleted.
 ## default: "http://localhost:2379,http://localhost:4001"
 # ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379,http://localhost:4001"
-ETCD_ADVERTISE_CLIENT_URLS="http://{{ server.bind.host }}:4001"
+ETCD_ADVERTISE_CLIENT_URLS="http{% if server.get('ssl', {}).get('enabled') %}s{% endif %}://{{ server.bind.host }}:4001"
 
 ##### -discovery
 ## Discovery URL used to bootstrap the cluster.
@@ -210,22 +210,34 @@
 ##### -cert-file
 ## Path to the client server TLS cert file.
 ## default: none
-# ETCD_CERT_FILE=""
+# ETCD_CERT_FILE
+{%- if server.get('ssl', {}).get('enabled') %}
+ETCD_CERT_FILE="/var/lib/etcd/etcd-server.crt"
+{%- endif %}
 
 ##### -key-file
 ## Path to the client server TLS key file.
 ## default: none
 # ETCD_KEY_FILE=""
+{%- if server.get('ssl', {}).get('enabled') %}
+ETCD_KEY_FILE="/var/lib/etcd/etcd-server.key"
+{%- endif %}
 
 ##### -client-cert-auth
 ## Enable client cert authentication.
 ## default: false
 # ETCD_CLIENT_CERT_AUTH
+{%- if server.get('ssl', {}).get('enabled') %}
+ETCD_CLIENT_CERT_AUTH=true
+{%- endif %}
 
 ##### -trusted-ca-file
 ## Path to the client server TLS trusted CA key file.
 ## default: none
 # ETCD_TRUSTED_CA_FILE
+{%- if server.get('ssl', {}).get('enabled') %}
+ETCD_TRUSTED_CA_FILE="/var/lib/etcd/ca.pem"
+{%- endif %}
 
 ##### -peer-ca-file [DEPRECATED]
 ## Path to the peer server TLS CA file. `-peer-ca-file ca.crt` could be replaced
@@ -237,27 +249,38 @@
 ## Path to the peer server TLS cert file.
 ## default: none
 # ETCD_PEER_CERT_FILE
+{%- if server.get('ssl', {}).get('enabled') %}
+ETCD_PEER_CERT_FILE="/var/lib/etcd/etcd-server.crt"
+{%- endif %}
 
 ##### -peer-key-file
 ## Path to the peer server TLS key file.
 ## default: none
 # ETCD_PEER_KEY_FILE
+{%- if server.get('ssl', {}).get('enabled') %}
+ETCD_PEER_KEY_FILE="/var/lib/etcd/etcd-server.key"
+{%- endif %}
 
 ##### -peer-client-cert-auth
 ## Enable peer client cert authentication.
 ## default: false
 # ETCD_PEER_CLIENT_CERT_AUTH
+{%- if server.get('ssl', {}).get('enabled') %}
+ETCD_PEER_CLIENT_CERT_AUTH=true
+{%- endif %}
 
 ##### -peer-trusted-ca-file
 ## Path to the peer server TLS trusted CA file.
 ## default: none
 # ETCD_PEER_TRUSTED_CA_FILE
+{%- if server.get('ssl', {}).get('enabled') %}
+ETCD_PEER_TRUSTED_CA_FILE="/var/lib/etcd/ca.pem"
+{%- endif %}
 
 ### Logging Flags
 ##### -debug
 ## Drop the default log level to DEBUG for all subpackages.
 ## default: false (INFO for all packages)
-# ETCD_DEBUG
 
 ##### -log-package-levels
 ## Set individual etcd subpackages to specific log levels.
@@ -268,4 +291,4 @@
 
 #### Daemon parameters:
 # DAEMON_ARGS=""
-{% endif %}
\ No newline at end of file
+{% endif %}
diff --git a/etcd/server/service.sls b/etcd/server/service.sls
index 2f0ddf4..e9c2306 100644
--- a/etcd/server/service.sls
+++ b/etcd/server/service.sls
@@ -39,6 +39,18 @@
     - source: salt://etcd/files/default
     - template: jinja
 
+/var/lib/etcd/:
+  file.directory:
+    - user: etcd
+    - group: etcd
+
+/var/lib/etcd/configenv:
+  file.managed:
+    - source: salt://etcd/files/configenv
+    - template: jinja
+    - require:
+      - file: /var/lib/etcd/
+
 etcd:
   service.running:
   - enable: True