From 3bb04bb45cf290f80fe3cd91b24230568b780acf Mon Sep 17 00:00:00 2001 From: Adrien Date: Sat, 10 Oct 2020 00:30:36 +0200 Subject: [PATCH] Work on PodSecurityPolicy --- defaults/main.yml | 6 +-- tasks/main.yml | 11 ++-- templates/2.2/traefik-clusterrole.yml.j2 | 4 ++ templates/2.3/traefik-clusterrole.yml.j2 | 2 +- templates/traefik-dashboard-insecure.yml.j2 | 25 ++++----- templates/traefik-dashboard-svc.yml.j2 | 6 +-- templates/traefik-dp.yml.j2 | 11 +++- ...ard.yml.j2 => traefik-ingressroute.yml.j2} | 42 ++++++++++----- templates/traefik-ping.yml.j2 | 24 +++++---- templates/traefik-psp.yml.j2 | 51 +++++++++++++++++++ 10 files changed, 132 insertions(+), 50 deletions(-) rename templates/{traefik-dashboard.yml.j2 => traefik-ingressroute.yml.j2} (52%) create mode 100644 templates/traefik-psp.yml.j2 diff --git a/defaults/main.yml b/defaults/main.yml index 07a1970..d4fd918 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -11,9 +11,9 @@ traefik_namespace: "traefik" traefik_cpu_limit: 500m traefik_memory_limit: 300Mi traefik_entrypoints: - - { name: "http", port: 80, proto: "TCP" } - - { name: "https", port: 443, proto: "TCP", tls: true } - - { name: "traefik", port: 8080, proto: "TCP" } + - { name: "http", port: 8000, proto: "TCP", hostport: 80 } + - { name: "https", port: 4443, proto: "TCP", hostport: 443, tls: true } +# - { name: "traefik", port: 8080, proto: "TCP" } basic_auth: false #traefik_dashboard_certificate: wildcard-cluster \ No newline at end of file diff --git a/tasks/main.yml b/tasks/main.yml index 1e57147..b528a69 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -49,7 +49,7 @@ k8s_info: context: "{{ my_context }}" api_version: v1 - kind: Deployment + kind: DaemonSet name: traefik namespace: '{{ traefik_namespace }}' field_selectors: @@ -82,18 +82,19 @@ resource_definition: "{{ lookup('template', item) | from_yaml }}" with_items: - "{{ lookup('vars', 'traefik_' + traefik_version | regex_replace('[.]','_') + '_list') }}" + - traefik-psp.yml.j2 - traefik-cm.yml.j2 - traefik-sa.yml.j2 - traefik-dp.yml.j2 - - traefik-svc.yml.j2 - - traefik-dashboard-svc.yml.j2 +# - traefik-svc.yml.j2 +# - traefik-dashboard-svc.yml.j2 - traefik-middleware-httpsredirect.yml.j2 - traefik-middleware-basicauth.yml.j2 - traefik-middleware-headers.yml.j2 - traefik-tls-options.yml.j2 - - traefik-dashboard.yml.j2 + - traefik-ingressroute.yml.j2 - traefik-dashboard-insecure.yml.j2 - - traefik-ping.yml.j2 +# - traefik-ping.yml.j2 - name: Define state of ipwhitelist middleware to present diff --git a/templates/2.2/traefik-clusterrole.yml.j2 b/templates/2.2/traefik-clusterrole.yml.j2 index 519d0dc..bef2410 100644 --- a/templates/2.2/traefik-clusterrole.yml.j2 +++ b/templates/2.2/traefik-clusterrole.yml.j2 @@ -4,6 +4,10 @@ metadata: name: traefik-ingress-controller rules: + - apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: ['traefik-ingress-controller'] - apiGroups: - "" resources: diff --git a/templates/2.3/traefik-clusterrole.yml.j2 b/templates/2.3/traefik-clusterrole.yml.j2 index 50b65c9..46bbd16 100644 --- a/templates/2.3/traefik-clusterrole.yml.j2 +++ b/templates/2.3/traefik-clusterrole.yml.j2 @@ -1,5 +1,5 @@ kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1beta1 +apiVersion: rbac.authorization.k8s.io/v1 metadata: name: traefik-ingress-controller diff --git a/templates/traefik-dashboard-insecure.yml.j2 b/templates/traefik-dashboard-insecure.yml.j2 index a37a302..4ed4b56 100644 --- a/templates/traefik-dashboard-insecure.yml.j2 +++ b/templates/traefik-dashboard-insecure.yml.j2 @@ -19,21 +19,22 @@ spec: # only support "Rule". kind: Rule # (optional) Priority disambiguates rules of the same length, for route matching. - priority: 12 middlewares: {% if ingress_whitelist is defined %} - name: traefik-ipwhitelist {% endif %} - name: https-only services: - - name: traefik-dashboard - port: 8080 - # (default 1) A weight used by the weighted round-robin strategy (WRR). - weight: 1 - # (default true) PassHostHeader controls whether to leave the request's Host - # Header as it was before it reached the proxy, or whether to let the proxy set it - # to the destination (backend) host. - passHostHeader: true - responseForwarding: - # (default 100ms) Interval between flushes of the buffered response body to the client. - flushInterval: 100ms + - name: api@internal + kind: TraefikService +# - name: traefik-dashboard +# port: 8080 +# # (default 1) A weight used by the weighted round-robin strategy (WRR). +# weight: 1 +# # (default true) PassHostHeader controls whether to leave the request's Host +# # Header as it was before it reached the proxy, or whether to let the proxy set it +# # to the destination (backend) host. +# passHostHeader: true +# responseForwarding: +# # (default 100ms) Interval between flushes of the buffered response body to the client. +# flushInterval: 100ms diff --git a/templates/traefik-dashboard-svc.yml.j2 b/templates/traefik-dashboard-svc.yml.j2 index d89d096..f6973c0 100644 --- a/templates/traefik-dashboard-svc.yml.j2 +++ b/templates/traefik-dashboard-svc.yml.j2 @@ -12,9 +12,9 @@ spec: port: 80 protocol: TCP targetPort: 80 - - name: traefik - port: 8080 - protocol: TCP +# - name: traefik +# port: 8080 +# protocol: TCP - protocol: TCP port: 443 name: https diff --git a/templates/traefik-dp.yml.j2 b/templates/traefik-dp.yml.j2 index efcc8fe..b7f3a54 100644 --- a/templates/traefik-dp.yml.j2 +++ b/templates/traefik-dp.yml.j2 @@ -19,6 +19,10 @@ spec: app: traefik spec: serviceAccountName: traefik-ingress-controller +# securityContext: +# sysctls: +# - name: kernel.net.ipv4.ip_unprivileged_port_start +# value: "80" containers: - name: traefik image: traefik:{{ lookup('vars', 'traefik_version_' + traefik_version | regex_replace('\.','_')) }} @@ -30,7 +34,9 @@ spec: - name: {{ traefik_entrypoint.name }} containerPort: {{ traefik_entrypoint.port }} protocol: {{ traefik_entrypoint.proto }} - hostPort: {{ traefik_entrypoint.port }} +{% if traefik_entrypoint.hostport is defined %} + hostPort: {{ traefik_entrypoint.hostport }} +{% endif %} {% endfor %} readinessProbe: httpGet: @@ -56,6 +62,9 @@ spec: - ALL add: - NET_BIND_SERVICE + runAsUser: 1000 + runAsGroup: 1000 + allowPrivilegeEscalation: true resources: limits: cpu: {{ traefik_cpu_limit }} diff --git a/templates/traefik-dashboard.yml.j2 b/templates/traefik-ingressroute.yml.j2 similarity index 52% rename from templates/traefik-dashboard.yml.j2 rename to templates/traefik-ingressroute.yml.j2 index c8f45b1..fe5d341 100644 --- a/templates/traefik-dashboard.yml.j2 +++ b/templates/traefik-ingressroute.yml.j2 @@ -1,7 +1,7 @@ apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: - name: traefik-dashboard + name: traefik namespace: {{ traefik_namespace }} labels: app: traefik @@ -13,13 +13,12 @@ spec: # Match is the rule corresponding to an underlying router. # Later on, match could be the simple form of a path prefix, e.g. just "/bar", # but for now we only support a traefik style matching rule. +# - match: PathPrefix(`/dashboard`) || PathPrefix(`/api`) - match: Host(`traefik.{{ traefik_domain }}`) # kind could eventually be one of "Rule", "Path", "Host", "Method", "Header", # "Parameter", etc, to support simpler forms of rule matching, but for now we # only support "Rule". kind: Rule - # (optional) Priority disambiguates rules of the same length, for route matching. - priority: 12 {% if basic_auth is defined or ingress_whitelist is defined %} middlewares: {% if ingress_whitelist is defined %} @@ -30,17 +29,32 @@ spec: {% endif %} {% endif %} services: - - name: traefik-dashboard - port: 8080 - # (default 1) A weight used by the weighted round-robin strategy (WRR). - weight: 1 - # (default true) PassHostHeader controls whether to leave the request's Host - # Header as it was before it reached the proxy, or whether to let the proxy set it - # to the destination (backend) host. - passHostHeader: true - responseForwarding: - # (default 100ms) Interval between flushes of the buffered response body to the client. - flushInterval: 100ms + - name: api@internal + kind: TraefikService +# - name: traefik-dashboard +# port: 8080 +# # (default 1) A weight used by the weighted round-robin strategy (WRR). +# weight: 1 +# # (default true) PassHostHeader controls whether to leave the request's Host +# # Header as it was before it reached the proxy, or whether to let the proxy set it +# # to the destination (backend) host. +# passHostHeader: true +# responseForwarding: +# # (default 100ms) Interval between flushes of the buffered response body to the client. +# flushInterval: 100ms + - match: Host(`traefik.{{ traefik_domain }}`) && PathPrefix(`/ping`) + kind: Rule + services: + - name: ping@internal + kind: TraefikService + - match: Host(`traefik.{{ traefik_domain }}`) && PathPrefix(`/metrics`) + kind: Rule + services: + - name: prometheus@internal + kind: TraefikService + + + tls: {% if traefik_dashboard_certificate is defined %} secretName: {{ traefik_dashboard_certificate }} diff --git a/templates/traefik-ping.yml.j2 b/templates/traefik-ping.yml.j2 index 1703002..86666f8 100644 --- a/templates/traefik-ping.yml.j2 +++ b/templates/traefik-ping.yml.j2 @@ -21,17 +21,19 @@ spec: # (optional) Priority disambiguates rules of the same length, for route matching. priority: 14 services: - - name: traefik-dashboard - port: 8080 - # (default 1) A weight used by the weighted round-robin strategy (WRR). - weight: 1 - # (default true) PassHostHeader controls whether to leave the request's Host - # Header as it was before it reached the proxy, or whether to let the proxy set it - # to the destination (backend) host. - passHostHeader: true - responseForwarding: - # (default 100ms) Interval between flushes of the buffered response body to the client. - flushInterval: 100ms + - name: ping@internal + kind: TraefikService +# - name: traefik-dashboard +# port: 8080 +# # (default 1) A weight used by the weighted round-robin strategy (WRR). +# weight: 1 +# # (default true) PassHostHeader controls whether to leave the request's Host +# # Header as it was before it reached the proxy, or whether to let the proxy set it +# # to the destination (backend) host. +# passHostHeader: true +# responseForwarding: +# # (default 100ms) Interval between flushes of the buffered response body to the client. +# flushInterval: 100ms tls: secretName: wildcard-cluster options: diff --git a/templates/traefik-psp.yml.j2 b/templates/traefik-psp.yml.j2 new file mode 100644 index 0000000..aa93c50 --- /dev/null +++ b/templates/traefik-psp.yml.j2 @@ -0,0 +1,51 @@ +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: runtime/default + seccomp.security.alpha.kubernetes.io/defaultProfileName: runtime/default + name: traefik-ingress-controller +spec: + requiredDropCapabilities: + - ALL + allowedCapabilities: + - NET_BIND_SERVICE + privileged: false + allowPrivilegeEscalation: false + # Allow core volume types. + volumes: + - configMap + - downwardAPI + - secret + - emptyDir + - projected +# - persistentVolumeClaim + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + # Require the container to run without root privileges. + rule: 'MustRunAsNonRoot' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + hostPorts: + - max: 65535 + min: 1 + readOnlyRootFilesystem: true + seLinux: + rule: 'RunAsAny' + hostPorts: + - max: 65535 + min: 1 +# allowedUnsafeSysctls: +# - kernel.net.ipv4.ip_unprivileged_port_start \ No newline at end of file