Repository: emissary-ingress/emissary

Issue:
Docker container security
We are running sysdig-falco in our Kubernetes cluster and it is complaining about the following:

`
k8s.node_name=ip-172-16-12-29.ec2.internal 10:53:58.969608520: Error File below /etc opened for writing (user=root command=python3 /application/kubewatch.py sync /etc/ambassador-config /etc/envoy.json parent=entrypoint.sh pcmdline=entrypoint.sh ./entrypoint.sh file=/etc/ambassador-config-1/payment-service-default.yaml program=python3 gparent=<NA> ggparent=<NA> gggparent=<NA>) k8s.pod=<NA> container=21b0bf1f68db
`

I would suggest changing the configuration location from `/etc/ambassador-config` to simply `/ambassador-config`.

I also strongly feel like Ambassador's processes (`entrypoint.sh`, `python3` and `envoy`) should be running as non-root user.



Discussion:
To handle OpenShift, Ambassador needs to work when run as an arbitrary UID with GID 0. More information is here: https://blog.openshift.com/jupyter-on-openshift-part-6-running-as-an-assigned-user-id/ but the short version is that one can rely on group write permissions (how exactly it's "better" to rely on a known group than on a known user I'm not exactly sure ;) ).
(We'll likely use `/application` as the root of everything, rather than `/`.)
(Cc @pdmack and @PaulM667)
I'll take a stab at this. Will try to run this on OpenShift, that should take care of some of the security concerns.
Well, apparently the problem is not only the UIDs, even after running `oc adm policy add-scc-to-user anyuid -n myproject -z default` I get -
```console
oc logs -f ambassador-6f6696f656-s75r7 -c ambassador
Traceback (most recent call last):
  File "/application/kubewatch.py", line 493, in <module>
    main()
  File "/usr/lib/python3.6/site-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3.6/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3.6/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3.6/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/application/kubewatch.py", line 476, in main
    sync(restarter)
  File "/application/kubewatch.py", line 313, in sync
    for x in v1.list_namespaced_config_map(restarter.namespace).items ]
  File "/usr/lib/python3.6/site-packages/kubernetes/client/apis/core_v1_api.py", line 12395, in list_namespaced_config_map
    (data) = self.list_namespaced_config_map_with_http_info(namespace, **kwargs)
  File "/usr/lib/python3.6/site-packages/kubernetes/client/apis/core_v1_api.py", line 12497, in list_namespaced_config_map_with_http_info
    collection_formats=collection_formats)
  File "/usr/lib/python3.6/site-packages/kubernetes/client/api_client.py", line 335, in call_api
    _preload_content, _request_timeout)
  File "/usr/lib/python3.6/site-packages/kubernetes/client/api_client.py", line 148, in __call_api
    _request_timeout=_request_timeout)
  File "/usr/lib/python3.6/site-packages/kubernetes/client/api_client.py", line 371, in request
    headers=headers)
  File "/usr/lib/python3.6/site-packages/kubernetes/client/rest.py", line 250, in GET
    query_params=query_params)
  File "/usr/lib/python3.6/site-packages/kubernetes/client/rest.py", line 240, in request
    raise ApiException(http_resp=r)
kubernetes.client.rest.ApiException: (403)
Reason: Forbidden
HTTP response headers: HTTPHeaderDict({'Cache-Control': 'no-store', 'Content-Type': 'application/json', 'X-Content-Type-Options': 'nosniff', 'Date': 'Mon, 11 Jun 2018 08:24:54 GMT', 'Content-Length': '371'})   
HTTP response body: {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"configmaps is forbidden: User \"system:serviceaccount:myproject:default\" cannot list configmaps in the namespace \"myproject\": User \"system:serviceaccount:myproject:default\" cannot list configmaps in project \"myproject\"","reason":"Forbidden","details":{"kind":"configmaps"},"code":403}                               


AMBASSADOR: kubewatch sync exited with status 1
Here's the envoy.json we were trying to run with:
ls: /etc/envoy*.json: No such file or directory
No config generated.
AMBASSADOR: shutting down
```

Update 1:
This was fixed by running - `oc adm policy add-cluster-role-to-user cluster-admin system:serviceaccount:myproject:default -n myproject`

Update 2:
The findings at https://github.com/deis/workflow/issues/856 can help us out

Resolving patch:
diff --git a/ambassador/ambassador/config.py b/ambassador/ambassador/config.py
--- a/ambassador/ambassador/config.py
+++ b/ambassador/ambassador/config.py
@@ -904,7 +904,7 @@ def generate_intermediate_config(self):
         # default values now.
 
         self.ambassador_module = SourcedDict(
-            service_port = 80,
+            service_port = 8080,
             admin_port = 8001,
             diag_port = 8877,
             auth_enabled = None,


Test patch:
diff --git a/ambassador/tests/000-default/gold.intermediate.json b/ambassador/tests/000-default/gold.intermediate.json
--- a/ambassador/tests/000-default/gold.intermediate.json
+++ b/ambassador/tests/000-default/gold.intermediate.json
@@ -98,7 +98,7 @@
             {
                 "_source": "--internal--",
                 "require_tls": false,
-                "service_port": 80,
+                "service_port": 8080,
                 "use_proxy_proto": false
             }
         ],
diff --git a/ambassador/tests/000-default/gold.json b/ambassador/tests/000-default/gold.json
--- a/ambassador/tests/000-default/gold.json
+++ b/ambassador/tests/000-default/gold.json
@@ -2,7 +2,7 @@
   "listeners": [
     
     {
-      "address": "tcp://0.0.0.0:80",
+      "address": "tcp://0.0.0.0:8080",
       
       "filters": [
         {
diff --git a/ambassador/tests/005-canary/gold.intermediate.json b/ambassador/tests/005-canary/gold.intermediate.json
--- a/ambassador/tests/005-canary/gold.intermediate.json
+++ b/ambassador/tests/005-canary/gold.intermediate.json
@@ -65,7 +65,7 @@
             {
                 "_source": "--internal--",
                 "require_tls": false,
-                "service_port": 80,
+                "service_port": 8080,
                 "use_proxy_proto": false
             }
         ],
diff --git a/ambassador/tests/005-canary/gold.json b/ambassador/tests/005-canary/gold.json
--- a/ambassador/tests/005-canary/gold.json
+++ b/ambassador/tests/005-canary/gold.json
@@ -2,7 +2,7 @@
   "listeners": [
     
     {
-      "address": "tcp://0.0.0.0:80",
+      "address": "tcp://0.0.0.0:8080",
       
       "filters": [
         {
diff --git a/ambassador/tests/006-headers-and-host/gold.intermediate.json b/ambassador/tests/006-headers-and-host/gold.intermediate.json
--- a/ambassador/tests/006-headers-and-host/gold.intermediate.json
+++ b/ambassador/tests/006-headers-and-host/gold.intermediate.json
@@ -124,7 +124,7 @@
             {
                 "_source": "--internal--",
                 "require_tls": false,
-                "service_port": 80,
+                "service_port": 8080,
                 "use_proxy_proto": false
             }
         ],
diff --git a/ambassador/tests/006-headers-and-host/gold.json b/ambassador/tests/006-headers-and-host/gold.json
--- a/ambassador/tests/006-headers-and-host/gold.json
+++ b/ambassador/tests/006-headers-and-host/gold.json
@@ -2,7 +2,7 @@
   "listeners": [
     
     {
-      "address": "tcp://0.0.0.0:80",
+      "address": "tcp://0.0.0.0:8080",
       
       "filters": [
         {
diff --git a/ambassador/tests/008-regex-prefix/gold.intermediate.json b/ambassador/tests/008-regex-prefix/gold.intermediate.json
--- a/ambassador/tests/008-regex-prefix/gold.intermediate.json
+++ b/ambassador/tests/008-regex-prefix/gold.intermediate.json
@@ -52,7 +52,7 @@
             {
                 "_source": "--internal--",
                 "require_tls": false,
-                "service_port": 80,
+                "service_port": 8080,
                 "use_proxy_proto": false
             }
         ],
diff --git a/ambassador/tests/008-regex-prefix/gold.json b/ambassador/tests/008-regex-prefix/gold.json
--- a/ambassador/tests/008-regex-prefix/gold.json
+++ b/ambassador/tests/008-regex-prefix/gold.json
@@ -2,7 +2,7 @@
   "listeners": [
     
     {
-      "address": "tcp://0.0.0.0:80",
+      "address": "tcp://0.0.0.0:8080",
       
       "filters": [
         {
diff --git a/ambassador/tests/009-rate-limit/gold.intermediate.json b/ambassador/tests/009-rate-limit/gold.intermediate.json
--- a/ambassador/tests/009-rate-limit/gold.intermediate.json
+++ b/ambassador/tests/009-rate-limit/gold.intermediate.json
@@ -84,7 +84,7 @@
             {
                 "_source": "--internal--",
                 "require_tls": false,
-                "service_port": 80,
+                "service_port": 8080,
                 "use_proxy_proto": false
             }
         ],
diff --git a/ambassador/tests/009-rate-limit/gold.json b/ambassador/tests/009-rate-limit/gold.json
--- a/ambassador/tests/009-rate-limit/gold.json
+++ b/ambassador/tests/009-rate-limit/gold.json
@@ -2,7 +2,7 @@
   "listeners": [
 
     {
-      "address": "tcp://0.0.0.0:80",
+      "address": "tcp://0.0.0.0:8080",
 
       "filters": [
         {
diff --git a/ambassador/tests/010-rewrite/gold.intermediate.json b/ambassador/tests/010-rewrite/gold.intermediate.json
--- a/ambassador/tests/010-rewrite/gold.intermediate.json
+++ b/ambassador/tests/010-rewrite/gold.intermediate.json
@@ -51,7 +51,7 @@
             {
                 "_source": "--internal--",
                 "require_tls": false,
-                "service_port": 80,
+                "service_port": 8080,
                 "use_proxy_proto": false
             }
         ],
diff --git a/ambassador/tests/010-rewrite/gold.json b/ambassador/tests/010-rewrite/gold.json
--- a/ambassador/tests/010-rewrite/gold.json
+++ b/ambassador/tests/010-rewrite/gold.json
@@ -2,7 +2,7 @@
   "listeners": [
     
     {
-      "address": "tcp://0.0.0.0:80",
+      "address": "tcp://0.0.0.0:8080",
       
       "filters": [
         {