Repository: emissary-ingress/emissary

Issue:
When create ambassador-cacert, here will throw exception.
https://github.com/datawire/ambassador/blob/32eec960f2da5f9abea1ff6a14985421020c5525/ambassador/kubewatch.py#L305

None type will throw exception for key


Discussion:
Hitting the same error trying to do client auth. Fix for this would be nice.
And also in line https://github.com/datawire/ambassador/blob/32eec960f2da5f9abea1ff6a14985421020c5525/ambassador/kubewatch.py#L350

the file written out is /etc/cacert/tls.crt, the tls module should have tls.crt and not tls.pem

Resolving patch:
diff --git a/ambassador/ambassador/config.py b/ambassador/ambassador/config.py
--- a/ambassador/ambassador/config.py
+++ b/ambassador/ambassador/config.py
@@ -301,7 +301,7 @@ def __init__(self, config_dir_path, k8s=False, schema_dir_path=None, template_di
                 "private_key_file": "/etc/certs/tls.key"
             },
             "client": {
-                "cacert_chain_file": "/etc/cacert/fullchain.pem"
+                "cacert_chain_file": "/etc/cacert/tls.crt"
             }
         }
 
diff --git a/ambassador/ambassador_diag/envoy.py b/ambassador/ambassador_diag/envoy.py
--- a/ambassador/ambassador_diag/envoy.py
+++ b/ambassador/ambassador_diag/envoy.py
@@ -133,7 +133,7 @@ def update_log_levels(self, last_attempt, level=None):
             if level:
                 url += "?level=%s" % level
 
-            r = requests.get(url)
+            r = requests.post(url)
         except OSError as e:
             logging.warning("EnvoyStats.update_log_levels failed: %s" % e)
             self.stats['update_errors'] += 1
@@ -200,7 +200,19 @@ def update_envoy_stats(self, last_attempt):
 
                 node = node[key]
 
-            node[keypath[-1]] = int(value.strip())
+            value = value.strip()
+
+            # Skip histograms for the moment.
+            # if value.startswith("P0("):
+            #     continue
+            #     # for field in value.split(' '):
+            #     #     if field.startswith('P95('):
+            #     #         value = field.split(',')
+
+            try:
+                node[keypath[-1]] = int(value)
+            except:
+                continue
 
         # Now dig into clusters a bit more.
 
diff --git a/ambassador/kubewatch.py b/ambassador/kubewatch.py
--- a/ambassador/kubewatch.py
+++ b/ambassador/kubewatch.py
@@ -302,7 +302,9 @@ def save_cert(cert, key, dir):
         pass
 
     open(os.path.join(dir, "tls.crt"), "w").write(cert.decode("utf-8"))
-    open(os.path.join(dir, "tls.key"), "w").write(key.decode("utf-8"))
+
+    if key:
+        open(os.path.join(dir, "tls.key"), "w").write(key.decode("utf-8"))
 
 def sync(restarter):
     v1 = kube_v1()
@@ -329,10 +331,13 @@ def sync(restarter):
                                                              restarter.namespace)
 
             if server_cert and server_key:
+                ambassador_id = os.getenv("AMBASSADOR_ID", "default")
+
                 tls_mod = {
                     "apiVersion": "ambassador/v0",
                     "kind": "Module",
                     "name": "tls-from-ambassador-certs",
+                    "ambassador_id": ambassador_id,
                     "config": {
                         "server": {
                             "enabled": True,
@@ -347,7 +352,7 @@ def sync(restarter):
                 if client_cert:
                     tls_mod['config']['client'] = {
                         "enabled": True,
-                        "cacert_chain_file": "/etc/cacert/tls.pem"
+                        "cacert_chain_file": "/etc/cacert/tls.crt"
                     }
 
                     if client_data.get('cert_required', None):
@@ -355,7 +360,9 @@ def sync(restarter):
 
                     save_cert(client_cert, None, "/etc/cacert")
 
-                restarter.update("tls.yaml", yaml.safe_dump(tls_mod))
+                tls_yaml = yaml.safe_dump(tls_mod)
+                logger.debug("generated TLS config %s" % tls_yaml)
+                restarter.update("tls.yaml", tls_yaml)
 
         # Next, check for annotations and such.
         svc_list = None


Test patch:
diff --git a/end-to-end/008-cacert/test.sh b/end-to-end/008-cacert/test.sh
new file mode 100644
--- /dev/null
+++ b/end-to-end/008-cacert/test.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+set -e -o pipefail
+
+HERE=$(cd $(dirname $0); pwd)
+
+cd "$HERE"
+
+ROOT=$(cd ..; pwd)
+PATH="${ROOT}:${PATH}"
+
+source ${ROOT}/utils.sh
+
+initialize_namespace "008-cacert"
+
+# Make sure cluster-wide RBAC is set up.
+kubectl apply -f ${ROOT}/rbac.yaml
+
+kubectl cluster-info
+
+python ${ROOT}/yfix.py ${ROOT}/fixes/test-dep.yfix \
+    ${ROOT}/ambassador-deployment.yaml \
+    k8s/ambassador-deployment.yaml \
+    008-cacert \
+    008-cacert
+
+# create secrets for TLS stuff
+kubectl create -n 008-cacert secret tls ambassador-certs --cert=certs/server.crt --key=certs/server.key
+kubectl create -n 008-cacert secret generic ambassador-cacert --from-file=tls.crt=certs/client.crt 
+# --from-literal=cert_required=true
+
+kubectl apply -f k8s/rbac.yaml
+kubectl apply -f k8s/ambassador.yaml
+kubectl apply -f k8s/ambassador-deployment.yaml
+# kubectl run demotest -n 008-cacert --image=dwflynn/demotest:0.0.1 -- /bin/sh -c "sleep 3600"
+
+set +e +o pipefail
+
+wait_for_pods 008-cacert
+
+CLUSTER=$(cluster_ip)
+APORT=$(service_port ambassador 008-cacert)
+# DEMOTEST_POD=$(demotest_pod)
+
+BASEURL="https://${CLUSTER}:${APORT}"
+
+echo "Base URL $BASEURL"
+echo "Diag URL $BASEURL/ambassador/v0/diag/"
+
+wait_for_ready "$BASEURL"
+
+if ! check_diag "$BASEURL" 1 "no services but TLS"; then
+    exit 1
+fi
+
+if ! check_listeners "$BASEURL" 1 "no services but TLS"; then
+    exit 1
+fi
+