diff --git a/docs/content/middlewares/addprefix.md b/docs/content/middlewares/http/addprefix.md similarity index 95% rename from docs/content/middlewares/addprefix.md rename to docs/content/middlewares/http/addprefix.md index fb33e8552..53b2b47d7 100644 --- a/docs/content/middlewares/addprefix.md +++ b/docs/content/middlewares/http/addprefix.md @@ -3,7 +3,7 @@ Prefixing the Path {: .subtitle } -![AddPrefix](../assets/img/middleware/addprefix.png) +![AddPrefix](../../assets/img/middleware/addprefix.png) The AddPrefix middleware updates the path of a request before forwarding it. diff --git a/docs/content/middlewares/basicauth.md b/docs/content/middlewares/http/basicauth.md similarity index 99% rename from docs/content/middlewares/basicauth.md rename to docs/content/middlewares/http/basicauth.md index be9691357..c1fd92cbb 100644 --- a/docs/content/middlewares/basicauth.md +++ b/docs/content/middlewares/http/basicauth.md @@ -3,7 +3,7 @@ Adding Basic Authentication {: .subtitle } -![BasicAuth](../assets/img/middleware/basicauth.png) +![BasicAuth](../../assets/img/middleware/basicauth.png) The BasicAuth middleware restricts access to your services to known users. diff --git a/docs/content/middlewares/buffering.md b/docs/content/middlewares/http/buffering.md similarity index 99% rename from docs/content/middlewares/buffering.md rename to docs/content/middlewares/http/buffering.md index d455981a4..5a5d81503 100644 --- a/docs/content/middlewares/buffering.md +++ b/docs/content/middlewares/http/buffering.md @@ -3,7 +3,7 @@ How to Read the Request before Forwarding It {: .subtitle } -![Buffering](../assets/img/middleware/buffering.png) +![Buffering](../../assets/img/middleware/buffering.png) The Buffering middleware limits the size of requests that can be forwarded to services. diff --git a/docs/content/middlewares/chain.md b/docs/content/middlewares/http/chain.md similarity index 99% rename from docs/content/middlewares/chain.md rename to docs/content/middlewares/http/chain.md index 146b5d2ca..1eee6220e 100644 --- a/docs/content/middlewares/chain.md +++ b/docs/content/middlewares/http/chain.md @@ -3,7 +3,7 @@ When One Isn't Enough {: .subtitle } -![Chain](../assets/img/middleware/chain.png) +![Chain](../../assets/img/middleware/chain.png) The Chain middleware enables you to define reusable combinations of other pieces of middleware. It makes reusing the same groups easier. diff --git a/docs/content/middlewares/circuitbreaker.md b/docs/content/middlewares/http/circuitbreaker.md similarity index 98% rename from docs/content/middlewares/circuitbreaker.md rename to docs/content/middlewares/http/circuitbreaker.md index 14ffa91b4..031087286 100644 --- a/docs/content/middlewares/circuitbreaker.md +++ b/docs/content/middlewares/http/circuitbreaker.md @@ -3,7 +3,7 @@ Don't Waste Time Calling Unhealthy Services {: .subtitle } -![CircuitBreaker](../assets/img/middleware/circuitbreaker.png) +![CircuitBreaker](../../assets/img/middleware/circuitbreaker.png) The circuit breaker protects your system from stacking requests to unhealthy services, resulting in cascading failures. diff --git a/docs/content/middlewares/compress.md b/docs/content/middlewares/http/compress.md similarity index 98% rename from docs/content/middlewares/compress.md rename to docs/content/middlewares/http/compress.md index 311820e67..3314c7332 100644 --- a/docs/content/middlewares/compress.md +++ b/docs/content/middlewares/http/compress.md @@ -3,7 +3,7 @@ Compress Responses before Sending them to the Client {: .subtitle } -![Compress](../assets/img/middleware/compress.png) +![Compress](../../assets/img/middleware/compress.png) The Compress middleware uses gzip compression. diff --git a/docs/content/middlewares/contenttype.md b/docs/content/middlewares/http/contenttype.md similarity index 100% rename from docs/content/middlewares/contenttype.md rename to docs/content/middlewares/http/contenttype.md diff --git a/docs/content/middlewares/digestauth.md b/docs/content/middlewares/http/digestauth.md similarity index 99% rename from docs/content/middlewares/digestauth.md rename to docs/content/middlewares/http/digestauth.md index ccdaa6979..bb47e08ff 100644 --- a/docs/content/middlewares/digestauth.md +++ b/docs/content/middlewares/http/digestauth.md @@ -3,7 +3,7 @@ Adding Digest Authentication {: .subtitle } -![BasicAuth](../assets/img/middleware/digestauth.png) +![BasicAuth](../../assets/img/middleware/digestauth.png) The DigestAuth middleware restricts access to your services to known users. diff --git a/docs/content/middlewares/errorpages.md b/docs/content/middlewares/http/errorpages.md similarity index 98% rename from docs/content/middlewares/errorpages.md rename to docs/content/middlewares/http/errorpages.md index 5bf3b0215..f892b79bd 100644 --- a/docs/content/middlewares/errorpages.md +++ b/docs/content/middlewares/http/errorpages.md @@ -3,7 +3,7 @@ It Has Never Been Easier to Say That Something Went Wrong {: .subtitle } -![ErrorPages](../assets/img/middleware/errorpages.png) +![ErrorPages](../../assets/img/middleware/errorpages.png) The ErrorPage middleware returns a custom page in lieu of the default, according to configured ranges of HTTP Status codes. diff --git a/docs/content/middlewares/forwardauth.md b/docs/content/middlewares/http/forwardauth.md similarity index 99% rename from docs/content/middlewares/forwardauth.md rename to docs/content/middlewares/http/forwardauth.md index 710d5eb5c..8947cd68c 100644 --- a/docs/content/middlewares/forwardauth.md +++ b/docs/content/middlewares/http/forwardauth.md @@ -3,7 +3,7 @@ Using an External Service to Forward Authentication {: .subtitle } -![AuthForward](../assets/img/middleware/authforward.png) +![AuthForward](../../assets/img/middleware/authforward.png) The ForwardAuth middleware delegates authentication to an external service. If the service answers with a 2XX code, access is granted, and the original request is performed. diff --git a/docs/content/middlewares/headers.md b/docs/content/middlewares/http/headers.md similarity index 97% rename from docs/content/middlewares/headers.md rename to docs/content/middlewares/http/headers.md index e6910f52f..6247c7208 100644 --- a/docs/content/middlewares/headers.md +++ b/docs/content/middlewares/http/headers.md @@ -3,7 +3,7 @@ Managing Request/Response headers {: .subtitle } -![Headers](../assets/img/middleware/headers.png) +![Headers](../../assets/img/middleware/headers.png) The Headers middleware manages the headers of requests and responses. @@ -349,7 +349,7 @@ The `hostsProxyHeaders` option is a set of header keys that may hold a proxied h !!! warning - Deprecated in favor of [EntryPoint redirection](../routing/entrypoints.md#redirection) or the [RedirectScheme middleware](./redirectscheme.md). + Deprecated in favor of [EntryPoint redirection](../../routing/entrypoints.md#redirection) or the [RedirectScheme middleware](./redirectscheme.md). The `sslRedirect` only allow HTTPS requests when set to `true`. @@ -357,7 +357,7 @@ The `sslRedirect` only allow HTTPS requests when set to `true`. !!! warning - Deprecated in favor of [EntryPoint redirection](../routing/entrypoints.md#redirection) or the [RedirectScheme middleware](./redirectscheme.md). + Deprecated in favor of [EntryPoint redirection](../../routing/entrypoints.md#redirection) or the [RedirectScheme middleware](./redirectscheme.md). Set `sslTemporaryRedirect` to `true` to force an SSL redirection using a 302 (instead of a 301). diff --git a/docs/content/middlewares/inflightreq.md b/docs/content/middlewares/http/inflightreq.md similarity index 99% rename from docs/content/middlewares/inflightreq.md rename to docs/content/middlewares/http/inflightreq.md index fd3ae2dd9..b47eb3aab 100644 --- a/docs/content/middlewares/inflightreq.md +++ b/docs/content/middlewares/http/inflightreq.md @@ -3,7 +3,7 @@ Limiting the Number of Simultaneous In-Flight Requests {: .subtitle } -![InFlightReq](../assets/img/middleware/inflightreq.png) +![InFlightReq](../../assets/img/middleware/inflightreq.png) To proactively prevent services from being overwhelmed with high load, the number of allowed simultaneous in-flight requests can be limited. diff --git a/docs/content/middlewares/ipwhitelist.md b/docs/content/middlewares/http/ipwhitelist.md similarity index 99% rename from docs/content/middlewares/ipwhitelist.md rename to docs/content/middlewares/http/ipwhitelist.md index d09e86971..9fe9dda58 100644 --- a/docs/content/middlewares/ipwhitelist.md +++ b/docs/content/middlewares/http/ipwhitelist.md @@ -3,7 +3,7 @@ Limiting Clients to Specific IPs {: .subtitle } -![IpWhiteList](../assets/img/middleware/ipwhitelist.png) +![IpWhiteList](../../assets/img/middleware/ipwhitelist.png) IPWhitelist accepts / refuses requests based on the client IP. diff --git a/docs/content/middlewares/http/overview.md b/docs/content/middlewares/http/overview.md new file mode 100644 index 000000000..67a18b895 --- /dev/null +++ b/docs/content/middlewares/http/overview.md @@ -0,0 +1,149 @@ +# HTTP Middlewares + +Controlling connections +{: .subtitle } + +![Overview](../../assets/img/middleware/overview.png) + +## Configuration Example + +```yaml tab="Docker" +# As a Docker Label +whoami: + # A container that exposes an API to show its IP address + image: traefik/whoami + labels: + # Create a middleware named `foo-add-prefix` + - "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo" + # Apply the middleware named `foo-add-prefix` to the router named `router1` + - "traefik.http.routers.router1.middlewares=foo-add-prefix@docker" +``` + +```yaml tab="Kubernetes IngressRoute" +# As a Kubernetes Traefik IngressRoute +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: middlewares.traefik.containo.us +spec: + group: traefik.containo.us + version: v1alpha1 + names: + kind: Middleware + plural: middlewares + singular: middleware + scope: Namespaced + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: stripprefix +spec: + stripPrefix: + prefixes: + - /stripit + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: ingressroute +spec: +# more fields... + routes: + # more fields... + middlewares: + - name: stripprefix +``` + +```yaml tab="Consul Catalog" +# Create a middleware named `foo-add-prefix` +- "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo" +# Apply the middleware named `foo-add-prefix` to the router named `router1` +- "traefik.http.routers.router1.middlewares=foo-add-prefix@consulcatalog" +``` + +```json tab="Marathon" +"labels": { + "traefik.http.middlewares.foo-add-prefix.addprefix.prefix": "/foo", + "traefik.http.routers.router1.middlewares": "foo-add-prefix@marathon" +} +``` + +```yaml tab="Rancher" +# As a Rancher Label +labels: + # Create a middleware named `foo-add-prefix` + - "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo" + # Apply the middleware named `foo-add-prefix` to the router named `router1` + - "traefik.http.routers.router1.middlewares=foo-add-prefix@rancher" +``` + +```toml tab="File (TOML)" +# As TOML Configuration File +[http.routers] + [http.routers.router1] + service = "myService" + middlewares = ["foo-add-prefix"] + rule = "Host(`example.com`)" + +[http.middlewares] + [http.middlewares.foo-add-prefix.addPrefix] + prefix = "/foo" + +[http.services] + [http.services.service1] + [http.services.service1.loadBalancer] + + [[http.services.service1.loadBalancer.servers]] + url = "http://127.0.0.1:80" +``` + +```yaml tab="File (YAML)" +# As YAML Configuration File +http: + routers: + router1: + service: myService + middlewares: + - "foo-add-prefix" + rule: "Host(`example.com`)" + + middlewares: + foo-add-prefix: + addPrefix: + prefix: "/foo" + + services: + service1: + loadBalancer: + servers: + - url: "http://127.0.0.1:80" +``` + +## Available HTTP Middlewares + +| Middleware | Purpose | Area | +|-------------------------------------------|---------------------------------------------------|-----------------------------| +| [AddPrefix](addprefix.md) | Add a Path Prefix | Path Modifier | +| [BasicAuth](basicauth.md) | Basic auth mechanism | Security, Authentication | +| [Buffering](buffering.md) | Buffers the request/response | Request Lifecycle | +| [Chain](chain.md) | Combine multiple pieces of middleware | Middleware tool | +| [CircuitBreaker](circuitbreaker.md) | Stop calling unhealthy services | Request Lifecycle | +| [Compress](compress.md) | Compress the response | Content Modifier | +| [DigestAuth](digestauth.md) | Adds Digest Authentication | Security, Authentication | +| [Errors](errorpages.md) | Define custom error pages | Request Lifecycle | +| [ForwardAuth](forwardauth.md) | Authentication delegation | Security, Authentication | +| [Headers](headers.md) | Add / Update headers | Security | +| [IPWhiteList](ipwhitelist.md) | Limit the allowed client IPs | Security, Request lifecycle | +| [InFlightReq](inflightreq.md) | Limit the number of simultaneous connections | Security, Request lifecycle | +| [PassTLSClientCert](passtlsclientcert.md) | Adding Client Certificates in a Header | Security | +| [RateLimit](ratelimit.md) | Limit the call frequency | Security, Request lifecycle | +| [RedirectScheme](redirectscheme.md) | Redirect easily the client elsewhere | Request lifecycle | +| [RedirectRegex](redirectregex.md) | Redirect the client elsewhere | Request lifecycle | +| [ReplacePath](replacepath.md) | Change the path of the request | Path Modifier | +| [ReplacePathRegex](replacepathregex.md) | Change the path of the request | Path Modifier | +| [Retry](retry.md) | Automatically retry the request in case of errors | Request lifecycle | +| [StripPrefix](stripprefix.md) | Change the path of the request | Path Modifier | +| [StripPrefixRegex](stripprefixregex.md) | Change the path of the request | Path Modifier | diff --git a/docs/content/middlewares/passtlsclientcert.md b/docs/content/middlewares/http/passtlsclientcert.md similarity index 99% rename from docs/content/middlewares/passtlsclientcert.md rename to docs/content/middlewares/http/passtlsclientcert.md index 17a27d08c..137422571 100644 --- a/docs/content/middlewares/passtlsclientcert.md +++ b/docs/content/middlewares/http/passtlsclientcert.md @@ -248,7 +248,7 @@ PassTLSClientCert can add two headers to the request: !!! info * The headers are filled with escaped string so it can be safely placed inside a URL query. - * These options only work accordingly to the [MutualTLS configuration](../https/tls.md#client-authentication-mtls). + * These options only work accordingly to the [MutualTLS configuration](../../https/tls.md#client-authentication-mtls). That is to say, only the certificates that match the `clientAuth.clientAuthType` policy are passed. The following example shows a complete certificate and explains each of the middleware options. diff --git a/docs/content/middlewares/ratelimit.md b/docs/content/middlewares/http/ratelimit.md similarity index 100% rename from docs/content/middlewares/ratelimit.md rename to docs/content/middlewares/http/ratelimit.md diff --git a/docs/content/middlewares/redirectregex.md b/docs/content/middlewares/http/redirectregex.md similarity index 100% rename from docs/content/middlewares/redirectregex.md rename to docs/content/middlewares/http/redirectregex.md diff --git a/docs/content/middlewares/redirectscheme.md b/docs/content/middlewares/http/redirectscheme.md similarity index 100% rename from docs/content/middlewares/redirectscheme.md rename to docs/content/middlewares/http/redirectscheme.md diff --git a/docs/content/middlewares/replacepath.md b/docs/content/middlewares/http/replacepath.md similarity index 100% rename from docs/content/middlewares/replacepath.md rename to docs/content/middlewares/http/replacepath.md diff --git a/docs/content/middlewares/replacepathregex.md b/docs/content/middlewares/http/replacepathregex.md similarity index 100% rename from docs/content/middlewares/replacepathregex.md rename to docs/content/middlewares/http/replacepathregex.md diff --git a/docs/content/middlewares/retry.md b/docs/content/middlewares/http/retry.md similarity index 100% rename from docs/content/middlewares/retry.md rename to docs/content/middlewares/http/retry.md diff --git a/docs/content/middlewares/stripprefix.md b/docs/content/middlewares/http/stripprefix.md similarity index 100% rename from docs/content/middlewares/stripprefix.md rename to docs/content/middlewares/http/stripprefix.md diff --git a/docs/content/middlewares/stripprefixregex.md b/docs/content/middlewares/http/stripprefixregex.md similarity index 100% rename from docs/content/middlewares/stripprefixregex.md rename to docs/content/middlewares/http/stripprefixregex.md diff --git a/docs/content/middlewares/overview.md b/docs/content/middlewares/overview.md index 69e7d8000..68e741dc2 100644 --- a/docs/content/middlewares/overview.md +++ b/docs/content/middlewares/overview.md @@ -9,7 +9,7 @@ Attached to the routers, pieces of middleware are a means of tweaking the reques There are several available middleware in Traefik, some can modify the request, the headers, some are in charge of redirections, some add authentication, and so on. -Pieces of middleware can be combined in chains to fit every scenario. +Middlewares that use the same protocol can be combined into chains to fit every scenario. !!! warning "Provider Namespace" @@ -121,26 +121,6 @@ http: ## Available Middlewares -| Middleware | Purpose | Area | -|-------------------------------------------|---------------------------------------------------|-----------------------------| -| [AddPrefix](addprefix.md) | Add a Path Prefix | Path Modifier | -| [BasicAuth](basicauth.md) | Basic auth mechanism | Security, Authentication | -| [Buffering](buffering.md) | Buffers the request/response | Request Lifecycle | -| [Chain](chain.md) | Combine multiple pieces of middleware | Middleware tool | -| [CircuitBreaker](circuitbreaker.md) | Stop calling unhealthy services | Request Lifecycle | -| [Compress](compress.md) | Compress the response | Content Modifier | -| [DigestAuth](digestauth.md) | Adds Digest Authentication | Security, Authentication | -| [Errors](errorpages.md) | Define custom error pages | Request Lifecycle | -| [ForwardAuth](forwardauth.md) | Authentication delegation | Security, Authentication | -| [Headers](headers.md) | Add / Update headers | Security | -| [IPWhiteList](ipwhitelist.md) | Limit the allowed client IPs | Security, Request lifecycle | -| [InFlightReq](inflightreq.md) | Limit the number of simultaneous connections | Security, Request lifecycle | -| [PassTLSClientCert](passtlsclientcert.md) | Adding Client Certificates in a Header | Security | -| [RateLimit](ratelimit.md) | Limit the call frequency | Security, Request lifecycle | -| [RedirectScheme](redirectscheme.md) | Redirect easily the client elsewhere | Request lifecycle | -| [RedirectRegex](redirectregex.md) | Redirect the client elsewhere | Request lifecycle | -| [ReplacePath](replacepath.md) | Change the path of the request | Path Modifier | -| [ReplacePathRegex](replacepathregex.md) | Change the path of the request | Path Modifier | -| [Retry](retry.md) | Automatically retry the request in case of errors | Request lifecycle | -| [StripPrefix](stripprefix.md) | Change the path of the request | Path Modifier | -| [StripPrefixRegex](stripprefixregex.md) | Change the path of the request | Path Modifier | +A list of HTTP middlewares can be found [here](http/overview.md). + +A list of TCP middlewares can be found [here](tcp/overview.md). diff --git a/docs/content/middlewares/tcp/ipwhitelist.md b/docs/content/middlewares/tcp/ipwhitelist.md new file mode 100644 index 000000000..9191919fb --- /dev/null +++ b/docs/content/middlewares/tcp/ipwhitelist.md @@ -0,0 +1,67 @@ +# IPWhiteList + +Limiting Clients to Specific IPs +{: .subtitle } + +IPWhitelist accepts / refuses connections based on the client IP. + +## Configuration Examples + +```yaml tab="Docker" +# Accepts connections from defined IP +labels: + - "traefik.tcp.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: MiddlewareTCP +metadata: + name: test-ipwhitelist +spec: + ipWhiteList: + sourceRange: + - 127.0.0.1/32 + - 192.168.1.7 +``` + +```yaml tab="Consul Catalog" +# Accepts request from defined IP +- "traefik.tcp.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" +``` + +```json tab="Marathon" +"labels": { + "traefik.tcp.middlewares.test-ipwhitelist.ipwhitelist.sourcerange": "127.0.0.1/32,192.168.1.7" +} +``` + +```yaml tab="Rancher" +# Accepts request from defined IP +labels: + - "traefik.tcp.middlewares.test-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" +``` + +```toml tab="File (TOML)" +# Accepts request from defined IP +[tcp.middlewares] + [tcp.middlewares.test-ipwhitelist.ipWhiteList] + sourceRange = ["127.0.0.1/32", "192.168.1.7"] +``` + +```yaml tab="File (YAML)" +# Accepts request from defined IP +http: + middlewares: + test-ipwhitelist: + ipWhiteList: + sourceRange: + - "127.0.0.1/32" + - "192.168.1.7" +``` + +## Configuration Options + +### `sourceRange` + +The `sourceRange` option sets the allowed IPs (or ranges of allowed IPs by using CIDR notation). diff --git a/docs/content/middlewares/tcp/overview.md b/docs/content/middlewares/tcp/overview.md new file mode 100644 index 000000000..310cae1af --- /dev/null +++ b/docs/content/middlewares/tcp/overview.md @@ -0,0 +1,134 @@ +# TCP Middlewares + +Controlling connections +{: .subtitle } + +![Overview](../../assets/img/middleware/overview.png) + +## Configuration Example + +```yaml tab="Docker" +# As a Docker Label +whoami: + # A container that exposes an API to show its IP address + image: traefik/whoami + labels: + # Create a middleware named `foo-ip-whitelist` + - "traefik.tcp.middlewares.foo-ip-whitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" + # Apply the middleware named `foo-ip-whitelist` to the router named `router1` + - "traefik.tcp.routers.router1.middlewares=foo-ip-whitelist@docker" +``` + +```yaml tab="Kubernetes IngressRoute" +# As a Kubernetes Traefik IngressRoute +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: middlewaretcps.traefik.containo.us +spec: + group: traefik.containo.us + version: v1alpha1 + names: + kind: MiddlewareTCP + plural: middlewaretcps + singular: middlewaretcp + scope: Namespaced + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: foo-ip-whitelist +spec: + ipWhiteList: + sourcerange: + - 127.0.0.1/32 + - 192.168.1.7 + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: ingressroute +spec: +# more fields... + routes: + # more fields... + middlewares: + - name: foo-ip-whitelist +``` + +```yaml tab="Consul Catalog" +# Create a middleware named `foo-ip-whitelist` +- "traefik.tcp.middlewares.foo-ip-whitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" +# Apply the middleware named `foo-ip-whitelist` to the router named `router1` +- "traefik.tcp.routers.router1.middlewares=foo-ip-whitelist@consulcatalog" +``` + +```json tab="Marathon" +"labels": { + "traefik.tcp.middlewares.foo-ip-whitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7", + "traefik.tcp.routers.router1.middlewares=foo-ip-whitelist@marathon" +} +``` + +```yaml tab="Rancher" +# As a Rancher Label +labels: + # Create a middleware named `foo-ip-whitelist` + - "traefik.tcp.middlewares.foo-ip-whitelist.ipwhitelist.sourcerange=127.0.0.1/32, 192.168.1.7" + # Apply the middleware named `foo-ip-whitelist` to the router named `router1` + - "traefik.tcp.routers.router1.middlewares=foo-ip-whitelist@rancher" +``` + +```toml tab="File (TOML)" +# As TOML Configuration File +[tcp.routers] + [tcp.routers.router1] + service = "myService" + middlewares = ["foo-ip-whitelist"] + rule = "Host(`example.com`)" + +[tcp.middlewares] + [tcp.middlewares.foo-ip-whitelist.ipWhiteList] + sourceRange = ["127.0.0.1/32", "192.168.1.7"] + +[tcp.services] + [tcp.services.service1] + [tcp.services.service1.loadBalancer] + [[tcp.services.service1.loadBalancer.servers]] + address = "10.0.0.10:4000" + [[tcp.services.service1.loadBalancer.servers]] + address = "10.0.0.11:4000" +``` + +```yaml tab="File (YAML)" +# As YAML Configuration File +tcp: + routers: + router1: + service: myService + middlewares: + - "foo-ip-whitelist" + rule: "Host(`example.com`)" + + middlewares: + foo-ip-whitelist: + ipWhiteList: + sourceRange: + - "127.0.0.1/32" + - "192.168.1.7" + + services: + service1: + loadBalancer: + servers: + - address: "10.0.0.10:4000" + - address: "10.0.0.11:4000" +``` + +## Available TCP Middlewares + +| Middleware | Purpose | Area | +|-------------------------------------------|---------------------------------------------------|-----------------------------| +| [IPWhiteList](ipwhitelist.md) | Limit the allowed client IPs | Security, Request lifecycle | diff --git a/docs/content/migration/v1-to-v2.md b/docs/content/migration/v1-to-v2.md index 3c0c58080..70857d8c0 100644 --- a/docs/content/migration/v1-to-v2.md +++ b/docs/content/migration/v1-to-v2.md @@ -327,7 +327,7 @@ With Traefik v2 it is applied on an entry point or a [Router](../routing/routers To apply a redirection: - on an entry point, the [HTTP redirection](../routing/entrypoints.md#redirection) has to be configured. -- on a router, one of the redirect middlewares, [RedirectRegex](../middlewares/redirectregex.md) or [RedirectScheme](../middlewares/redirectscheme.md), has to be configured and added to the router middlewares list. +- on a router, one of the redirect middlewares, [RedirectRegex](../middlewares/http/redirectregex.md) or [RedirectScheme](../middlewares/http/redirectscheme.md), has to be configured and added to the router middlewares list. !!! example "Global HTTP to HTTPS redirection" @@ -545,7 +545,7 @@ Use Case: Incoming requests to `http://example.org/admin` are forwarded to the w with the path `/admin` stripped, e.g. to `http://:/`. In this case, you must: - First, configure a router named `admin` with a rule matching at least the path prefix with the `PathPrefix` keyword, -- Then, define a middleware of type [`stripprefix`](../middlewares/stripprefix.md), which removes the prefix `/admin`, associated to the router `admin`. +- Then, define a middleware of type [`stripprefix`](../middlewares/http/stripprefix.md), which removes the prefix `/admin`, associated to the router `admin`. !!! example "Strip Path Prefix When Forwarding to Backend" @@ -660,12 +660,12 @@ with the path `/admin` stripped, e.g. to `http://:/`. In this case, yo ??? question "What About Other Path Transformations?" - Instead of removing the path prefix with the [`stripprefix` middleware](../../middlewares/stripprefix/), you can also: + Instead of removing the path prefix with the [`stripprefix` middleware](../../middlewares/http/stripprefix/), you can also: - - Add a path prefix with the [`addprefix` middleware](../../middlewares/addprefix/) - - Replace the complete path of the request with the [`replacepath` middleware](../../middlewares/replacepath/) - - ReplaceRewrite path using Regexp with the [`replacepathregex` middleware](../../middlewares/replacepathregex/) - - And a lot more on the [`middlewares` page](../../middlewares/overview/) + - Add a path prefix with the [`addprefix` middleware](../../middlewares/http/addprefix/) + - Replace the complete path of the request with the [`replacepath` middleware](../../middlewares/http/replacepath/) + - ReplaceRewrite path using Regexp with the [`replacepathregex` middleware](../../middlewares/http/replacepathregex/) + - And a lot more on the [`HTTP middlewares` page](../../middlewares/http/overview/) ## ACME (LetsEncrypt) diff --git a/docs/content/migration/v2.md b/docs/content/migration/v2.md index 554ca27a8..a1d4b762c 100644 --- a/docs/content/migration/v2.md +++ b/docs/content/migration/v2.md @@ -395,7 +395,7 @@ The support of the `networking.k8s.io/v1beta1` API Version will stop in Kubernet For simple HTTP to HTTPS redirection, you may use [EntryPoints redirections](../routing/entrypoints.md#redirection). -For more advanced use cases, you can use either the [RedirectScheme middleware](../middlewares/redirectscheme.md) or the [RedirectRegex middleware](../middlewares/redirectregex.md). +For more advanced use cases, you can use either the [RedirectScheme middleware](../middlewares/http/redirectscheme.md) or the [RedirectRegex middleware](../middlewares/http/redirectregex.md). ### Headers middleware: accessControlAllowOrigin diff --git a/docs/content/operations/dashboard.md b/docs/content/operations/dashboard.md index 879ae1e06..5bd4dce51 100644 --- a/docs/content/operations/dashboard.md +++ b/docs/content/operations/dashboard.md @@ -66,8 +66,8 @@ with a router attached to the service `api@internal` in the to allow defining: - One or more security features through [middlewares](../middlewares/overview.md) - like authentication ([basicAuth](../middlewares/basicauth.md) , [digestAuth](../middlewares/digestauth.md), - [forwardAuth](../middlewares/forwardauth.md)) or [whitelisting](../middlewares/ipwhitelist.md). + like authentication ([basicAuth](../middlewares/http/basicauth.md) , [digestAuth](../middlewares/http/digestauth.md), + [forwardAuth](../middlewares/http/forwardauth.md)) or [whitelisting](../middlewares/http/ipwhitelist.md). - A [router rule](#dashboard-router-rule) for accessing the dashboard, through Traefik itself (sometimes referred as "Traefik-ception"). diff --git a/docs/content/reference/dynamic-configuration/docker-labels.yml b/docs/content/reference/dynamic-configuration/docker-labels.yml index ebc58f670..cd4f59243 100644 --- a/docs/content/reference/dynamic-configuration/docker-labels.yml +++ b/docs/content/reference/dynamic-configuration/docker-labels.yml @@ -159,7 +159,9 @@ - "traefik.http.services.service01.loadbalancer.server.port=foobar" - "traefik.http.services.service01.loadbalancer.server.scheme=foobar" - "traefik.http.services.service01.loadbalancer.serverstransport=foobar" +- "traefik.tcp.middlewares.middleware00.ipwhitelist.sourcerange=foobar, foobar" - "traefik.tcp.routers.tcprouter0.entrypoints=foobar, foobar" +- "traefik.tcp.routers.tcprouter0.middlewares=foobar, foobar" - "traefik.tcp.routers.tcprouter0.rule=foobar" - "traefik.tcp.routers.tcprouter0.service=foobar" - "traefik.tcp.routers.tcprouter0.tls=true" @@ -171,6 +173,7 @@ - "traefik.tcp.routers.tcprouter0.tls.options=foobar" - "traefik.tcp.routers.tcprouter0.tls.passthrough=true" - "traefik.tcp.routers.tcprouter1.entrypoints=foobar, foobar" +- "traefik.tcp.routers.tcprouter1.middlewares=foobar, foobar" - "traefik.tcp.routers.tcprouter1.rule=foobar" - "traefik.tcp.routers.tcprouter1.service=foobar" - "traefik.tcp.routers.tcprouter1.tls=true" diff --git a/docs/content/reference/dynamic-configuration/file.toml b/docs/content/reference/dynamic-configuration/file.toml index 55f7da3a8..3fbd66122 100644 --- a/docs/content/reference/dynamic-configuration/file.toml +++ b/docs/content/reference/dynamic-configuration/file.toml @@ -310,6 +310,7 @@ [tcp.routers] [tcp.routers.TCPRouter0] entryPoints = ["foobar", "foobar"] + middlewares = ["foobar", "foobar"] service = "foobar" rule = "foobar" [tcp.routers.TCPRouter0.tls] @@ -326,6 +327,7 @@ sans = ["foobar", "foobar"] [tcp.routers.TCPRouter1] entryPoints = ["foobar", "foobar"] + middlewares = ["foobar", "foobar"] service = "foobar" rule = "foobar" [tcp.routers.TCPRouter1.tls] @@ -362,6 +364,10 @@ [[tcp.services.TCPService02.weighted.services]] name = "foobar" weight = 42 + [tcp.middlewares] + [tcp.middlewares.Middleware00] + [tcp.middlewares.Middleware00.ipWhiteList] + sourceRange = ["foobar", "foobar"] [udp] [udp.routers] diff --git a/docs/content/reference/dynamic-configuration/file.yaml b/docs/content/reference/dynamic-configuration/file.yaml index 77d3b77e6..72f87ff0d 100644 --- a/docs/content/reference/dynamic-configuration/file.yaml +++ b/docs/content/reference/dynamic-configuration/file.yaml @@ -350,6 +350,9 @@ tcp: entryPoints: - foobar - foobar + middlewares: + - foobar + - foobar service: foobar rule: foobar tls: @@ -369,6 +372,9 @@ tcp: entryPoints: - foobar - foobar + middlewares: + - foobar + - foobar service: foobar rule: foobar tls: @@ -384,6 +390,12 @@ tcp: sans: - foobar - foobar + middlewares: + Middleware00: + ipWhiteList: + sourceRange: + - foobar + - foobar services: TCPService01: loadBalancer: diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1beta1.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1beta1.yml index 7cfd37b15..8319e66aa 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1beta1.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1beta1.yml @@ -27,6 +27,21 @@ spec: singular: middleware scope: Namespaced +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: middlewaretcps.traefik.containo.us + +spec: + group: traefik.containo.us + version: v1alpha1 + names: + kind: MiddlewareTCP + plural: middlewaretcps + singular: middlewaretcp + scope: Namespaced + --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml index ddedbb7be..58548c561 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml @@ -34,6 +34,7 @@ rules: - traefik.containo.us resources: - middlewares + - middlewaretcps - ingressroutes - traefikservices - ingressroutetcps diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml index 56c5e7419..4b9bb5562 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-resource.yml @@ -147,6 +147,8 @@ spec: services: - name: whoamitcp port: 8080 + middlewares: + - name: ipwhitelist tls: secretName: foosecret passthrough: false diff --git a/docs/content/reference/dynamic-configuration/kv-ref.md b/docs/content/reference/dynamic-configuration/kv-ref.md index 9db07ced9..ff4d87835 100644 --- a/docs/content/reference/dynamic-configuration/kv-ref.md +++ b/docs/content/reference/dynamic-configuration/kv-ref.md @@ -220,8 +220,12 @@ | `traefik/http/services/Service03/weighted/sticky/cookie/name` | `foobar` | | `traefik/http/services/Service03/weighted/sticky/cookie/sameSite` | `foobar` | | `traefik/http/services/Service03/weighted/sticky/cookie/secure` | `true` | +| `traefik/tcp/middlewares/Middleware00/ipWhiteList/sourceRange/0` | `foobar` | +| `traefik/tcp/middlewares/Middleware00/ipWhiteList/sourceRange/1` | `foobar` | | `traefik/tcp/routers/TCPRouter0/entryPoints/0` | `foobar` | | `traefik/tcp/routers/TCPRouter0/entryPoints/1` | `foobar` | +| `traefik/tcp/routers/TCPRouter0/middlewares/0` | `foobar` | +| `traefik/tcp/routers/TCPRouter0/middlewares/1` | `foobar` | | `traefik/tcp/routers/TCPRouter0/rule` | `foobar` | | `traefik/tcp/routers/TCPRouter0/service` | `foobar` | | `traefik/tcp/routers/TCPRouter0/tls/certResolver` | `foobar` | @@ -235,6 +239,8 @@ | `traefik/tcp/routers/TCPRouter0/tls/passthrough` | `true` | | `traefik/tcp/routers/TCPRouter1/entryPoints/0` | `foobar` | | `traefik/tcp/routers/TCPRouter1/entryPoints/1` | `foobar` | +| `traefik/tcp/routers/TCPRouter1/middlewares/0` | `foobar` | +| `traefik/tcp/routers/TCPRouter1/middlewares/1` | `foobar` | | `traefik/tcp/routers/TCPRouter1/rule` | `foobar` | | `traefik/tcp/routers/TCPRouter1/service` | `foobar` | | `traefik/tcp/routers/TCPRouter1/tls/certResolver` | `foobar` | diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml index e1346f242..6e6b4d135 100644 --- a/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_ingressroutetcps.yaml @@ -47,6 +47,21 @@ spec: properties: match: type: string + middlewares: + description: Middlewares contains references to MiddlewareTCP + resources. + items: + description: ObjectReference is a generic reference to a Traefik + resource. + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object + type: array services: items: description: ServiceTCP defines an upstream to proxy traffic. diff --git a/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml new file mode 100644 index 000000000..1042a06df --- /dev/null +++ b/docs/content/reference/dynamic-configuration/traefik.containo.us_middlewaretcps.yaml @@ -0,0 +1,59 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: middlewaretcps.traefik.containo.us +spec: + group: traefik.containo.us + names: + kind: MiddlewareTCP + listKind: MiddlewareTCPList + plural: middlewaretcps + singular: middlewaretcp + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: MiddlewareTCP is a specification for a MiddlewareTCP resource. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: MiddlewareTCPSpec holds the MiddlewareTCP configuration. + properties: + ipWhiteList: + description: TCPIPWhiteList holds the TCP ip white list configuration. + properties: + sourceRange: + items: + type: string + type: array + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/docs/content/routing/overview.md b/docs/content/routing/overview.md index 58db1b5fb..2e252166c 100644 --- a/docs/content/routing/overview.md +++ b/docs/content/routing/overview.md @@ -22,7 +22,7 @@ If they do, the router might transform the request using pieces of [middleware]( ## Example with a File Provider Below is an example of a full configuration file for the [file provider](../providers/file.md) that forwards `http://domain/whoami/` requests to a service reachable on `http://private/whoami-service/`. -In the process, Traefik will make sure that the user is authenticated (using the [BasicAuth middleware](../middlewares/basicauth.md)). +In the process, Traefik will make sure that the user is authenticated (using the [BasicAuth middleware](../middlewares/http/basicauth.md)). Static configuration: diff --git a/docs/content/routing/providers/consul-catalog.md b/docs/content/routing/providers/consul-catalog.md index ed88664e7..4a577133e 100644 --- a/docs/content/routing/providers/consul-catalog.md +++ b/docs/content/routing/providers/consul-catalog.md @@ -263,7 +263,7 @@ you'd add the tag `traefik.http.services.{name-of-your-choice}.loadbalancer.pass You can declare pieces of middleware using tags starting with `traefik.http.middlewares.{name-of-your-choice}.`, followed by the middleware type/options. -For example, to declare a middleware [`redirectscheme`](../../middlewares/redirectscheme.md) named `my-redirect`, you'd write `traefik.http.middlewares.my-redirect.redirectscheme.scheme: https`. +For example, to declare a middleware [`redirectscheme`](../../middlewares/http/redirectscheme.md) named `my-redirect`, you'd write `traefik.http.middlewares.my-redirect.redirectscheme.scheme: https`. More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md). diff --git a/docs/content/routing/providers/docker.md b/docs/content/routing/providers/docker.md index 09738ec77..1e071fb5e 100644 --- a/docs/content/routing/providers/docker.md +++ b/docs/content/routing/providers/docker.md @@ -419,7 +419,7 @@ you'd add the label `traefik.http.services..loadbalancer.pa You can declare pieces of middleware using labels starting with `traefik.http.middlewares..`, followed by the middleware type/options. -For example, to declare a middleware [`redirectscheme`](../../middlewares/redirectscheme.md) named `my-redirect`, +For example, to declare a middleware [`redirectscheme`](../../middlewares/http/redirectscheme.md) named `my-redirect`, you'd write `traefik.http.middlewares.my-redirect.redirectscheme.scheme=https`. More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md). diff --git a/docs/content/routing/providers/ecs.md b/docs/content/routing/providers/ecs.md index 78abd573e..cfcb1af8c 100644 --- a/docs/content/routing/providers/ecs.md +++ b/docs/content/routing/providers/ecs.md @@ -268,7 +268,7 @@ you'd add the label `traefik.http.services.{name-of-your-choice}.loadbalancer.pa You can declare pieces of middleware using labels starting with `traefik.http.middlewares.{name-of-your-choice}.`, followed by the middleware type/options. -For example, to declare a middleware [`redirectscheme`](../../middlewares/redirectscheme.md) named `my-redirect`, you'd write `traefik.http.middlewares.my-redirect.redirectscheme.scheme: https`. +For example, to declare a middleware [`redirectscheme`](../../middlewares/http/redirectscheme.md) named `my-redirect`, you'd write `traefik.http.middlewares.my-redirect.redirectscheme.scheme: https`. More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md). diff --git a/docs/content/routing/providers/marathon.md b/docs/content/routing/providers/marathon.md index ae25d5c9e..5591981fb 100644 --- a/docs/content/routing/providers/marathon.md +++ b/docs/content/routing/providers/marathon.md @@ -293,7 +293,7 @@ For example, to change the passHostHeader behavior, you'd add the label `"traefi You can declare pieces of middleware using labels starting with `traefik.http.middlewares.{middleware-name-of-your-choice}.`, followed by the middleware type/options. -For example, to declare a middleware [`redirectscheme`](../../middlewares/redirectscheme.md) named `my-redirect`, you'd write `"traefik.http.middlewares.my-redirect.redirectscheme.scheme": "https"`. +For example, to declare a middleware [`redirectscheme`](../../middlewares/http/redirectscheme.md) named `my-redirect`, you'd write `"traefik.http.middlewares.my-redirect.redirectscheme.scheme": "https"`. More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md). diff --git a/docs/content/routing/providers/rancher.md b/docs/content/routing/providers/rancher.md index 77506158a..1a5aa0444 100644 --- a/docs/content/routing/providers/rancher.md +++ b/docs/content/routing/providers/rancher.md @@ -299,7 +299,7 @@ you'd add the label `traefik.http.services.{name-of-your-choice}.loadbalancer.pa You can declare pieces of middleware using labels starting with `traefik.http.middlewares.{name-of-your-choice}.`, followed by the middleware type/options. -For example, to declare a middleware [`redirectscheme`](../../middlewares/redirectscheme.md) named `my-redirect`, you'd write `traefik.http.middlewares.my-redirect.redirectscheme.scheme: https`. +For example, to declare a middleware [`redirectscheme`](../../middlewares/http/redirectscheme.md) named `my-redirect`, you'd write `traefik.http.middlewares.my-redirect.redirectscheme.scheme: https`. More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md). diff --git a/docs/content/routing/routers/index.md b/docs/content/routing/routers/index.md index c6e76a891..e7a18ca8e 100644 --- a/docs/content/routing/routers/index.md +++ b/docs/content/routing/routers/index.md @@ -808,6 +808,41 @@ If you want to limit the router scope to a set of entry points, set the entry po Hence, only TLS routers will be able to specify a domain name with that rule. However, non-TLS routers will have to explicitly use that rule with `*` (every domain) to state that every non-TLS request will be handled by the router. +### Middlewares + +You can attach a list of [middlewares](../../middlewares/overview.md) to each TCP router. +The middlewares will take effect only if the rule matches, and before connecting to the service. + +!!! warning "The character `@` is not allowed to be used in the middleware name." + +!!! tip "Middlewares order" + + Middlewares are applied in the same order as their declaration in **router**. + +??? example "With a [middleware](../../middlewares/tcp/overview.md) -- using the [File Provider](../../providers/file.md)" + + ```toml tab="TOML" + ## Dynamic configuration + [tcp.routers] + [tcp.routers.my-router] + rule = "HostSNI(`*`)" + # declared elsewhere + middlewares = ["ipwhitelist"] + service = "service-foo" + ``` + + ```yaml tab="YAML" + ## Dynamic configuration + tcp: + routers: + my-router: + rule: "HostSNI(`*`)" + # declared elsewhere + middlewares: + - ipwhitelist + service: service-foo + ``` + ### Services You must attach a TCP [service](../services/index.md) per TCP router. diff --git a/docs/content/routing/services/index.md b/docs/content/routing/services/index.md index 95f79b4fb..859e5c26d 100644 --- a/docs/content/routing/services/index.md +++ b/docs/content/routing/services/index.md @@ -116,7 +116,7 @@ The `url` option point to a specific instance. !!! info "" Paths in the servers' `url` have no effect. If you want the requests to be sent to a specific path on your servers, - configure your [`routers`](../routers/index.md) to use a corresponding [middleware](../../middlewares/overview.md) (e.g. the [AddPrefix](../../middlewares/addprefix.md) or [ReplacePath](../../middlewares/replacepath.md)) middlewares. + configure your [`routers`](../routers/index.md) to use a corresponding [middleware](../../middlewares/overview.md) (e.g. the [AddPrefix](../../middlewares/http/addprefix.md) or [ReplacePath](../../middlewares/http/replacepath.md)) middlewares. ??? example "A Service with One Server -- Using the [File Provider](../../providers/file.md)" diff --git a/docs/content/user-guides/marathon.md b/docs/content/user-guides/marathon.md index 2b1836cf5..091d9833c 100644 --- a/docs/content/user-guides/marathon.md +++ b/docs/content/user-guides/marathon.md @@ -57,7 +57,7 @@ Beginning with version 1.4, Traefik respects readiness check results if the Trae Due to the way readiness check results are currently exposed by the Marathon API, ready tasks may be taken into rotation with a small delay. It is on the order of one readiness check timeout interval (as configured on the application specification) and guarantees that non-ready tasks do not receive traffic prematurely. -If readiness checks are not possible, a current mitigation strategy is to enable [retries](../middlewares/retry.md) and make sure that a sufficient number of healthy application tasks exist so that one retry will likely hit one of those. +If readiness checks are not possible, a current mitigation strategy is to enable [retries](../middlewares/http/retry.md) and make sure that a sufficient number of healthy application tasks exist so that one retry will likely hit one of those. Apart from its probabilistic nature, the workaround comes at the price of increased latency. #### Shutdown diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index fe176494c..3a9e141e4 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -104,29 +104,34 @@ nav: - 'TLS': 'https/tls.md' - 'Let''s Encrypt': 'https/acme.md' - 'Middlewares': - - 'Overview': 'middlewares/overview.md' - - 'AddPrefix': 'middlewares/addprefix.md' - - 'BasicAuth': 'middlewares/basicauth.md' - - 'Buffering': 'middlewares/buffering.md' - - 'Chain': 'middlewares/chain.md' - - 'CircuitBreaker': 'middlewares/circuitbreaker.md' - - 'Compress': 'middlewares/compress.md' - - 'ContentType': 'middlewares/contenttype.md' - - 'DigestAuth': 'middlewares/digestauth.md' - - 'Errors': 'middlewares/errorpages.md' - - 'ForwardAuth': 'middlewares/forwardauth.md' - - 'Headers': 'middlewares/headers.md' - - 'IpWhitelist': 'middlewares/ipwhitelist.md' - - 'InFlightReq': 'middlewares/inflightreq.md' - - 'PassTLSClientCert': 'middlewares/passtlsclientcert.md' - - 'RateLimit': 'middlewares/ratelimit.md' - - 'RedirectRegex': 'middlewares/redirectregex.md' - - 'RedirectScheme': 'middlewares/redirectscheme.md' - - 'ReplacePath': 'middlewares/replacepath.md' - - 'ReplacePathRegex': 'middlewares/replacepathregex.md' - - 'Retry': 'middlewares/retry.md' - - 'StripPrefix': 'middlewares/stripprefix.md' - - 'StripPrefixRegex': 'middlewares/stripprefixregex.md' + - 'Overview': 'middlewares/overview.md' + - 'HTTP': + - 'Overview': 'middlewares/http/overview.md' + - 'AddPrefix': 'middlewares/http/addprefix.md' + - 'BasicAuth': 'middlewares/http/basicauth.md' + - 'Buffering': 'middlewares/http/buffering.md' + - 'Chain': 'middlewares/http/chain.md' + - 'CircuitBreaker': 'middlewares/http/circuitbreaker.md' + - 'Compress': 'middlewares/http/compress.md' + - 'ContentType': 'middlewares/http/contenttype.md' + - 'DigestAuth': 'middlewares/http/digestauth.md' + - 'Errors': 'middlewares/http/errorpages.md' + - 'ForwardAuth': 'middlewares/http/forwardauth.md' + - 'Headers': 'middlewares/http/headers.md' + - 'IpWhitelist': 'middlewares/http/ipwhitelist.md' + - 'InFlightReq': 'middlewares/http/inflightreq.md' + - 'PassTLSClientCert': 'middlewares/http/passtlsclientcert.md' + - 'RateLimit': 'middlewares/http/ratelimit.md' + - 'RedirectRegex': 'middlewares/http/redirectregex.md' + - 'RedirectScheme': 'middlewares/http/redirectscheme.md' + - 'ReplacePath': 'middlewares/http/replacepath.md' + - 'ReplacePathRegex': 'middlewares/http/replacepathregex.md' + - 'Retry': 'middlewares/http/retry.md' + - 'StripPrefix': 'middlewares/http/stripprefix.md' + - 'StripPrefixRegex': 'middlewares/http/stripprefixregex.md' + - 'TCP': + - 'Overview': 'middlewares/tcp/overview.md' + - 'IpWhitelist': 'middlewares/tcp/ipwhitelist.md' - 'Plugins & Traefik Pilot': 'plugins/index.md' - 'Operations': - 'CLI': 'operations/cli.md' diff --git a/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml index 5d7a8a364..fdfcdc39e 100644 --- a/integration/fixtures/k8s/01-traefik-crd.yml +++ b/integration/fixtures/k8s/01-traefik-crd.yml @@ -245,6 +245,21 @@ spec: properties: match: type: string + middlewares: + description: Middlewares contains references to MiddlewareTCP + resources. + items: + description: ObjectReference is a generic reference to a Traefik + resource. + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object + type: array services: items: description: ServiceTCP defines an upstream to proxy traffic. @@ -989,6 +1004,65 @@ status: conditions: [] storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: middlewaretcps.traefik.containo.us +spec: + group: traefik.containo.us + names: + kind: MiddlewareTCP + listKind: MiddlewareTCPList + plural: middlewaretcps + singular: middlewaretcp + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: MiddlewareTCP is a specification for a MiddlewareTCP resource. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: MiddlewareTCPSpec holds the MiddlewareTCP configuration. + properties: + ipWhiteList: + description: TCPIPWhiteList holds the TCP ip white list configuration. + properties: + sourceRange: + items: + type: string + type: array + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition diff --git a/integration/fixtures/tcp/ip-whitelist.toml b/integration/fixtures/tcp/ip-whitelist.toml new file mode 100644 index 000000000..dba71102a --- /dev/null +++ b/integration/fixtures/tcp/ip-whitelist.toml @@ -0,0 +1,55 @@ +[global] + checkNewVersion = false + sendAnonymousUsage = false + +[log] + level = "DEBUG" + +[entryPoints] + [entryPoints.tcp] + address = ":8093" + +[api] + insecure = true + +[providers.file] + filename = "{{ .SelfFilename }}" + +## dynamic configuration ## + +[tcp] + [tcp.routers] + [tcp.routers.to-whoami-a] + entryPoints = ["tcp"] + rule = "HostSNI(`whoami-a.test`)" + service = "whoami-a" + middlewares = ["blocking-ipwhitelist"] + [tcp.routers.to-whoami-a.tls] + passthrough = true + + [tcp.routers.to-whoami-b] + entryPoints = ["tcp"] + rule = "HostSNI(`whoami-b.test`)" + service = "whoami-b" + middlewares = ["allowing-ipwhitelist"] + [tcp.routers.to-whoami-b.tls] + passthrough = true + + [tcp.services] + [tcp.services.whoami-a.loadBalancer] + [[tcp.services.whoami-a.loadBalancer.servers]] + address = "localhost:8081" + + [tcp.services.whoami-b.loadBalancer] + [[tcp.services.whoami-b.loadBalancer.servers]] + address = "localhost:8082" + + [tcp.middlewares] + [tcp.middlewares.allowing-ipwhitelist.ipWhiteList] + sourceRange = ["127.0.0.1/32"] + [tcp.middlewares.blocking-ipwhitelist.ipWhiteList] + sourceRange = ["127.127.127.127/32"] + +[[tls.certificates]] + certFile = "fixtures/tcp/whoami-c.crt" + keyFile = "fixtures/tcp/whoami-c.key" diff --git a/integration/tcp_test.go b/integration/tcp_test.go index 16b1c8e41..e01a59f0b 100644 --- a/integration/tcp_test.go +++ b/integration/tcp_test.go @@ -200,6 +200,30 @@ func (s *TCPSuite) TestCatchAllNoTLSWithHTTPS(c *check.C) { c.Assert(err, checker.IsNil) } +func (s *TCPSuite) TestMiddlewareWhiteList(c *check.C) { + file := s.adaptFile(c, "fixtures/tcp/ip-whitelist.toml", struct{}{}) + defer os.Remove(file) + + cmd, display := s.traefikCmd(withConfigFile(file)) + defer display(c) + + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer s.killCmd(cmd) + + err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 50*time.Second, try.StatusCodeIs(http.StatusOK), try.BodyContains("HostSNI(`whoami-a.test`)")) + c.Assert(err, checker.IsNil) + + // Traefik not passes through, ipWhitelist closes connection + _, err = guessWho("127.0.0.1:8093", "whoami-a.test", true) + c.Assert(err, checker.NotNil) + + // Traefik passes through, termination handled by whoami-b + out, err := guessWho("127.0.0.1:8093", "whoami-b.test", true) + c.Assert(err, checker.IsNil) + c.Assert(out, checker.Contains, "whoami-b") +} + func welcome(addr string) (string, error) { tcpAddr, err := net.ResolveTCPAddr("tcp", addr) if err != nil { diff --git a/pkg/api/handler.go b/pkg/api/handler.go index d35483f82..ff2ae7e86 100644 --- a/pkg/api/handler.go +++ b/pkg/api/handler.go @@ -36,13 +36,14 @@ type serviceInfoRepresentation struct { // RunTimeRepresentation is the configuration information exposed by the API handler. type RunTimeRepresentation struct { - Routers map[string]*runtime.RouterInfo `json:"routers,omitempty"` - Middlewares map[string]*runtime.MiddlewareInfo `json:"middlewares,omitempty"` - Services map[string]*serviceInfoRepresentation `json:"services,omitempty"` - TCPRouters map[string]*runtime.TCPRouterInfo `json:"tcpRouters,omitempty"` - TCPServices map[string]*runtime.TCPServiceInfo `json:"tcpServices,omitempty"` - UDPRouters map[string]*runtime.UDPRouterInfo `json:"udpRouters,omitempty"` - UDPServices map[string]*runtime.UDPServiceInfo `json:"udpServices,omitempty"` + Routers map[string]*runtime.RouterInfo `json:"routers,omitempty"` + Middlewares map[string]*runtime.MiddlewareInfo `json:"middlewares,omitempty"` + Services map[string]*serviceInfoRepresentation `json:"services,omitempty"` + TCPRouters map[string]*runtime.TCPRouterInfo `json:"tcpRouters,omitempty"` + TCPMiddlewares map[string]*runtime.TCPMiddlewareInfo `json:"tcpMiddlewares,omitempty"` + TCPServices map[string]*runtime.TCPServiceInfo `json:"tcpServices,omitempty"` + UDPRouters map[string]*runtime.UDPRouterInfo `json:"udpRouters,omitempty"` + UDPServices map[string]*runtime.UDPServiceInfo `json:"udpServices,omitempty"` } // Handler serves the configuration and status of Traefik on API endpoints. @@ -107,6 +108,8 @@ func (h Handler) createRouter() *mux.Router { router.Methods(http.MethodGet).Path("/api/tcp/routers/{routerID}").HandlerFunc(h.getTCPRouter) router.Methods(http.MethodGet).Path("/api/tcp/services").HandlerFunc(h.getTCPServices) router.Methods(http.MethodGet).Path("/api/tcp/services/{serviceID}").HandlerFunc(h.getTCPService) + router.Methods(http.MethodGet).Path("/api/tcp/middlewares").HandlerFunc(h.getTCPMiddlewares) + router.Methods(http.MethodGet).Path("/api/tcp/middlewares/{middlewareID}").HandlerFunc(h.getTCPMiddleware) router.Methods(http.MethodGet).Path("/api/udp/routers").HandlerFunc(h.getUDPRouters) router.Methods(http.MethodGet).Path("/api/udp/routers/{routerID}").HandlerFunc(h.getUDPRouter) @@ -132,13 +135,14 @@ func (h Handler) getRuntimeConfiguration(rw http.ResponseWriter, request *http.R } result := RunTimeRepresentation{ - Routers: h.runtimeConfiguration.Routers, - Middlewares: h.runtimeConfiguration.Middlewares, - Services: siRepr, - TCPRouters: h.runtimeConfiguration.TCPRouters, - TCPServices: h.runtimeConfiguration.TCPServices, - UDPRouters: h.runtimeConfiguration.UDPRouters, - UDPServices: h.runtimeConfiguration.UDPServices, + Routers: h.runtimeConfiguration.Routers, + Middlewares: h.runtimeConfiguration.Middlewares, + Services: siRepr, + TCPRouters: h.runtimeConfiguration.TCPRouters, + TCPMiddlewares: h.runtimeConfiguration.TCPMiddlewares, + TCPServices: h.runtimeConfiguration.TCPServices, + UDPRouters: h.runtimeConfiguration.UDPRouters, + UDPServices: h.runtimeConfiguration.UDPServices, } rw.Header().Set("Content-Type", "application/json") diff --git a/pkg/api/handler_overview.go b/pkg/api/handler_overview.go index a9ff75139..4e6485e7d 100644 --- a/pkg/api/handler_overview.go +++ b/pkg/api/handler_overview.go @@ -45,8 +45,9 @@ func (h Handler) getOverview(rw http.ResponseWriter, request *http.Request) { Middlewares: getHTTPMiddlewareSection(h.runtimeConfiguration.Middlewares), }, TCP: schemeOverview{ - Routers: getTCPRouterSection(h.runtimeConfiguration.TCPRouters), - Services: getTCPServiceSection(h.runtimeConfiguration.TCPServices), + Routers: getTCPRouterSection(h.runtimeConfiguration.TCPRouters), + Services: getTCPServiceSection(h.runtimeConfiguration.TCPServices), + Middlewares: getTCPMiddlewareSection(h.runtimeConfiguration.TCPMiddlewares), }, UDP: schemeOverview{ Routers: getUDPRouterSection(h.runtimeConfiguration.UDPRouters), @@ -160,6 +161,25 @@ func getTCPServiceSection(services map[string]*runtime.TCPServiceInfo) *section } } +func getTCPMiddlewareSection(middlewares map[string]*runtime.TCPMiddlewareInfo) *section { + var countErrors int + var countWarnings int + for _, mid := range middlewares { + switch mid.Status { + case runtime.StatusDisabled: + countErrors++ + case runtime.StatusWarning: + countWarnings++ + } + } + + return §ion{ + Total: len(middlewares), + Warnings: countWarnings, + Errors: countErrors, + } +} + func getUDPRouterSection(routers map[string]*runtime.UDPRouterInfo) *section { var countErrors int var countWarnings int diff --git a/pkg/api/handler_overview_test.go b/pkg/api/handler_overview_test.go index 8614e0098..6dee89a72 100644 --- a/pkg/api/handler_overview_test.go +++ b/pkg/api/handler_overview_test.go @@ -171,6 +171,31 @@ func TestHandler_Overview(t *testing.T) { Status: runtime.StatusDisabled, }, }, + TCPMiddlewares: map[string]*runtime.TCPMiddlewareInfo{ + "ipwhitelist1@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + Status: runtime.StatusEnabled, + }, + "ipwhitelist2@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + }, + "ipwhitelist3@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + Status: runtime.StatusDisabled, + }, + }, TCPRouters: map[string]*runtime.TCPRouterInfo{ "tcpbar@myprovider": { TCPRouter: &dynamic.TCPRouter{ diff --git a/pkg/api/handler_tcp.go b/pkg/api/handler_tcp.go index d64d42d55..390e1179c 100644 --- a/pkg/api/handler_tcp.go +++ b/pkg/api/handler_tcp.go @@ -43,6 +43,22 @@ func newTCPServiceRepresentation(name string, si *runtime.TCPServiceInfo) tcpSer } } +type tcpMiddlewareRepresentation struct { + *runtime.TCPMiddlewareInfo + Name string `json:"name,omitempty"` + Provider string `json:"provider,omitempty"` + Type string `json:"type,omitempty"` +} + +func newTCPMiddlewareRepresentation(name string, mi *runtime.TCPMiddlewareInfo) tcpMiddlewareRepresentation { + return tcpMiddlewareRepresentation{ + TCPMiddlewareInfo: mi, + Name: name, + Provider: getProviderName(name), + Type: strings.ToLower(extractType(mi.TCPMiddleware)), + } +} + func (h Handler) getTCPRouters(rw http.ResponseWriter, request *http.Request) { results := make([]tcpRouterRepresentation, 0, len(h.runtimeConfiguration.TCPRouters)) @@ -147,6 +163,58 @@ func (h Handler) getTCPService(rw http.ResponseWriter, request *http.Request) { } } +func (h Handler) getTCPMiddlewares(rw http.ResponseWriter, request *http.Request) { + results := make([]tcpMiddlewareRepresentation, 0, len(h.runtimeConfiguration.Middlewares)) + + criterion := newSearchCriterion(request.URL.Query()) + + for name, mi := range h.runtimeConfiguration.TCPMiddlewares { + if keepTCPMiddleware(name, mi, criterion) { + results = append(results, newTCPMiddlewareRepresentation(name, mi)) + } + } + + sort.Slice(results, func(i, j int) bool { + return results[i].Name < results[j].Name + }) + + rw.Header().Set("Content-Type", "application/json") + + pageInfo, err := pagination(request, len(results)) + if err != nil { + writeError(rw, err.Error(), http.StatusBadRequest) + return + } + + rw.Header().Set(nextPageHeader, strconv.Itoa(pageInfo.nextPage)) + + err = json.NewEncoder(rw).Encode(results[pageInfo.startIndex:pageInfo.endIndex]) + if err != nil { + log.FromContext(request.Context()).Error(err) + writeError(rw, err.Error(), http.StatusInternalServerError) + } +} + +func (h Handler) getTCPMiddleware(rw http.ResponseWriter, request *http.Request) { + middlewareID := mux.Vars(request)["middlewareID"] + + rw.Header().Set("Content-Type", "application/json") + + middleware, ok := h.runtimeConfiguration.TCPMiddlewares[middlewareID] + if !ok { + writeError(rw, fmt.Sprintf("middleware not found: %s", middlewareID), http.StatusNotFound) + return + } + + result := newTCPMiddlewareRepresentation(middlewareID, middleware) + + err := json.NewEncoder(rw).Encode(result) + if err != nil { + log.FromContext(request.Context()).Error(err) + writeError(rw, err.Error(), http.StatusInternalServerError) + } +} + func keepTCPRouter(name string, item *runtime.TCPRouterInfo, criterion *searchCriterion) bool { if criterion == nil { return true @@ -162,3 +230,11 @@ func keepTCPService(name string, item *runtime.TCPServiceInfo, criterion *search return criterion.withStatus(item.Status) && criterion.searchIn(name) } + +func keepTCPMiddleware(name string, item *runtime.TCPMiddlewareInfo, criterion *searchCriterion) bool { + if criterion == nil { + return true + } + + return criterion.withStatus(item.Status) && criterion.searchIn(name) +} diff --git a/pkg/api/handler_tcp_test.go b/pkg/api/handler_tcp_test.go index f00a99a4b..3e14921fb 100644 --- a/pkg/api/handler_tcp_test.go +++ b/pkg/api/handler_tcp_test.go @@ -507,6 +507,223 @@ func TestHandler_TCP(t *testing.T) { statusCode: http.StatusNotFound, }, }, + { + desc: "all middlewares", + path: "/api/tcp/middlewares", + conf: runtime.Configuration{ + TCPMiddlewares: map[string]*runtime.TCPMiddlewareInfo{ + "ipwhitelist1@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + UsedBy: []string{"bar@myprovider", "test@myprovider"}, + }, + "ipwhitelist2@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.2/32"}, + }, + }, + UsedBy: []string{"test@myprovider"}, + }, + "ipwhitelist1@anotherprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + UsedBy: []string{"bar@myprovider"}, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/tcpmiddlewares.json", + }, + }, + { + desc: "middlewares filtered by status", + path: "/api/tcp/middlewares?status=enabled", + conf: runtime.Configuration{ + TCPMiddlewares: map[string]*runtime.TCPMiddlewareInfo{ + "ipwhitelist@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + UsedBy: []string{"bar@myprovider", "test@myprovider"}, + Status: runtime.StatusEnabled, + }, + "ipwhitelist2@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.2/32"}, + }, + }, + UsedBy: []string{"test@myprovider"}, + Status: runtime.StatusDisabled, + }, + "ipwhitelist@anotherprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + UsedBy: []string{"bar@myprovider"}, + Status: runtime.StatusEnabled, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/tcpmiddlewares-filtered-status.json", + }, + }, + { + desc: "middlewares filtered by search", + path: "/api/tcp/middlewares?search=ipwhitelist", + conf: runtime.Configuration{ + TCPMiddlewares: map[string]*runtime.TCPMiddlewareInfo{ + "bad@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + UsedBy: []string{"bar@myprovider", "test@myprovider"}, + Status: runtime.StatusEnabled, + }, + "ipwhitelist@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + UsedBy: []string{"test@myprovider"}, + Status: runtime.StatusDisabled, + }, + "ipwhitelist@anotherprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + UsedBy: []string{"bar@myprovider"}, + Status: runtime.StatusEnabled, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "1", + jsonFile: "testdata/tcpmiddlewares-filtered-search.json", + }, + }, + { + desc: "all middlewares, 1 res per page, want page 2", + path: "/api/tcp/middlewares?page=2&per_page=1", + conf: runtime.Configuration{ + TCPMiddlewares: map[string]*runtime.TCPMiddlewareInfo{ + "ipwhitelist@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + UsedBy: []string{"bar@myprovider", "test@myprovider"}, + }, + "ipwhitelist2@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.2/32"}, + }, + }, + UsedBy: []string{"test@myprovider"}, + }, + "ipwhitelist@anotherprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + UsedBy: []string{"bar@myprovider"}, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + nextPage: "3", + jsonFile: "testdata/tcpmiddlewares-page2.json", + }, + }, + { + desc: "one middleware by id", + path: "/api/tcp/middlewares/ipwhitelist@myprovider", + conf: runtime.Configuration{ + TCPMiddlewares: map[string]*runtime.TCPMiddlewareInfo{ + "ipwhitelist@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + UsedBy: []string{"bar@myprovider", "test@myprovider"}, + }, + "ipwhitelist2@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.2/32"}, + }, + }, + UsedBy: []string{"test@myprovider"}, + }, + "ipwhitelist@anotherprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + UsedBy: []string{"bar@myprovider"}, + }, + }, + }, + expected: expected{ + statusCode: http.StatusOK, + jsonFile: "testdata/tcpmiddleware-ipwhitelist.json", + }, + }, + { + desc: "one middleware by id, that does not exist", + path: "/api/tcp/middlewares/foo@myprovider", + conf: runtime.Configuration{ + TCPMiddlewares: map[string]*runtime.TCPMiddlewareInfo{ + "ipwhitelist@myprovider": { + TCPMiddleware: &dynamic.TCPMiddleware{ + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + UsedBy: []string{"bar@myprovider", "test@myprovider"}, + }, + }, + }, + expected: expected{ + statusCode: http.StatusNotFound, + }, + }, + { + desc: "one middleware by id, but no config", + path: "/api/tcp/middlewares/foo@myprovider", + conf: runtime.Configuration{}, + expected: expected{ + statusCode: http.StatusNotFound, + }, + }, } for _, test := range testCases { diff --git a/pkg/api/testdata/overview-dynamic.json b/pkg/api/testdata/overview-dynamic.json index b89a17df6..abe3e1300 100644 --- a/pkg/api/testdata/overview-dynamic.json +++ b/pkg/api/testdata/overview-dynamic.json @@ -22,6 +22,11 @@ } }, "tcp": { + "middlewares": { + "errors": 1, + "total": 3, + "warnings": 0 + }, "routers": { "errors": 1, "total": 3, diff --git a/pkg/api/testdata/overview-empty.json b/pkg/api/testdata/overview-empty.json index 78dd6c8a6..2a1f7251b 100644 --- a/pkg/api/testdata/overview-empty.json +++ b/pkg/api/testdata/overview-empty.json @@ -22,6 +22,11 @@ } }, "tcp": { + "middlewares": { + "errors": 0, + "total": 0, + "warnings": 0 + }, "routers": { "errors": 0, "total": 0, diff --git a/pkg/api/testdata/overview-features.json b/pkg/api/testdata/overview-features.json index d2fb0d3ff..37ee19760 100644 --- a/pkg/api/testdata/overview-features.json +++ b/pkg/api/testdata/overview-features.json @@ -22,6 +22,11 @@ } }, "tcp": { + "middlewares": { + "errors": 0, + "total": 0, + "warnings": 0 + }, "routers": { "errors": 0, "total": 0, diff --git a/pkg/api/testdata/overview-providers.json b/pkg/api/testdata/overview-providers.json index 08fb3ffa3..dedce0e46 100644 --- a/pkg/api/testdata/overview-providers.json +++ b/pkg/api/testdata/overview-providers.json @@ -32,6 +32,11 @@ "plugin-test" ], "tcp": { + "middlewares": { + "errors": 0, + "total": 0, + "warnings": 0 + }, "routers": { "errors": 0, "total": 0, diff --git a/pkg/api/testdata/tcpmiddleware-ipwhitelist.json b/pkg/api/testdata/tcpmiddleware-ipwhitelist.json new file mode 100644 index 000000000..95f2540de --- /dev/null +++ b/pkg/api/testdata/tcpmiddleware-ipwhitelist.json @@ -0,0 +1,13 @@ +{ + "ipWhiteList": { + "sourceRange": ["127.0.0.1/32"] + }, + "name": "ipwhitelist@myprovider", + "provider": "myprovider", + "status": "enabled", + "type": "ipwhitelist", + "usedBy": [ + "bar@myprovider", + "test@myprovider" + ] +} \ No newline at end of file diff --git a/pkg/api/testdata/tcpmiddlewares-empty.json b/pkg/api/testdata/tcpmiddlewares-empty.json new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/pkg/api/testdata/tcpmiddlewares-empty.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/pkg/api/testdata/tcpmiddlewares-filtered-search.json b/pkg/api/testdata/tcpmiddlewares-filtered-search.json new file mode 100644 index 000000000..5dc58379e --- /dev/null +++ b/pkg/api/testdata/tcpmiddlewares-filtered-search.json @@ -0,0 +1,26 @@ +[ + { + "ipWhiteList": { + "sourceRange": ["127.0.0.1/32"] + }, + "name": "ipwhitelist@anotherprovider", + "provider": "anotherprovider", + "status": "enabled", + "type": "ipwhitelist", + "usedBy": [ + "bar@myprovider" + ] + }, + { + "ipWhiteList": { + "sourceRange": ["127.0.0.1/32"] + }, + "name": "ipwhitelist@myprovider", + "provider": "myprovider", + "status": "disabled", + "type": "ipwhitelist", + "usedBy": [ + "test@myprovider" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/tcpmiddlewares-filtered-status.json b/pkg/api/testdata/tcpmiddlewares-filtered-status.json new file mode 100644 index 000000000..906679181 --- /dev/null +++ b/pkg/api/testdata/tcpmiddlewares-filtered-status.json @@ -0,0 +1,27 @@ +[ + { + "ipWhiteList": { + "sourceRange": ["127.0.0.1/32"] + }, + "name": "ipwhitelist@anotherprovider", + "provider": "anotherprovider", + "status": "enabled", + "type": "ipwhitelist", + "usedBy": [ + "bar@myprovider" + ] + }, + { + "ipWhiteList": { + "sourceRange": ["127.0.0.1/32"] + }, + "name": "ipwhitelist@myprovider", + "provider": "myprovider", + "status": "enabled", + "type": "ipwhitelist", + "usedBy": [ + "bar@myprovider", + "test@myprovider" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/tcpmiddlewares-page2.json b/pkg/api/testdata/tcpmiddlewares-page2.json new file mode 100644 index 000000000..76c516876 --- /dev/null +++ b/pkg/api/testdata/tcpmiddlewares-page2.json @@ -0,0 +1,14 @@ +[ + { + "ipWhiteList": { + "sourceRange": ["127.0.0.1/32"] + }, + "name": "ipwhitelist@anotherprovider", + "provider": "anotherprovider", + "status": "enabled", + "type": "ipwhitelist", + "usedBy": [ + "bar@myprovider" + ] + } +] \ No newline at end of file diff --git a/pkg/api/testdata/tcpmiddlewares.json b/pkg/api/testdata/tcpmiddlewares.json new file mode 100644 index 000000000..b1c0cdab1 --- /dev/null +++ b/pkg/api/testdata/tcpmiddlewares.json @@ -0,0 +1,39 @@ +[ + { + "ipWhiteList": { + "sourceRange": ["127.0.0.1/32"] + }, + "name": "ipwhitelist1@anotherprovider", + "provider": "anotherprovider", + "status": "enabled", + "type": "ipwhitelist", + "usedBy": [ + "bar@myprovider" + ] + }, + { + "ipWhiteList": { + "sourceRange": ["127.0.0.1/32"] + }, + "name": "ipwhitelist1@myprovider", + "provider": "myprovider", + "status": "enabled", + "type": "ipwhitelist", + "usedBy": [ + "bar@myprovider", + "test@myprovider" + ] + }, + { + "ipWhiteList": { + "sourceRange": ["127.0.0.2/32"] + }, + "name": "ipwhitelist2@myprovider", + "provider": "myprovider", + "status": "enabled", + "type": "ipwhitelist", + "usedBy": [ + "test@myprovider" + ] + } +] \ No newline at end of file diff --git a/pkg/config/dynamic/tcp_config.go b/pkg/config/dynamic/tcp_config.go index ebf8423f3..270f490d1 100644 --- a/pkg/config/dynamic/tcp_config.go +++ b/pkg/config/dynamic/tcp_config.go @@ -10,8 +10,9 @@ import ( // TCPConfiguration contains all the TCP configuration parameters. type TCPConfiguration struct { - Routers map[string]*TCPRouter `json:"routers,omitempty" toml:"routers,omitempty" yaml:"routers,omitempty" export:"true"` - Services map[string]*TCPService `json:"services,omitempty" toml:"services,omitempty" yaml:"services,omitempty" export:"true"` + Routers map[string]*TCPRouter `json:"routers,omitempty" toml:"routers,omitempty" yaml:"routers,omitempty" export:"true"` + Services map[string]*TCPService `json:"services,omitempty" toml:"services,omitempty" yaml:"services,omitempty" export:"true"` + Middlewares map[string]*TCPMiddleware `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty" export:"true"` } // +k8s:deepcopy-gen=true @@ -48,6 +49,7 @@ func (w *TCPWRRService) SetDefaults() { // TCPRouter holds the router configuration. type TCPRouter struct { EntryPoints []string `json:"entryPoints,omitempty" toml:"entryPoints,omitempty" yaml:"entryPoints,omitempty" export:"true"` + Middlewares []string `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty" export:"true"` Service string `json:"service,omitempty" toml:"service,omitempty" yaml:"service,omitempty" export:"true"` Rule string `json:"rule,omitempty" toml:"rule,omitempty" yaml:"rule,omitempty"` TLS *RouterTCPTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` diff --git a/pkg/config/dynamic/tcp_middlewares.go b/pkg/config/dynamic/tcp_middlewares.go new file mode 100644 index 000000000..83b2d1169 --- /dev/null +++ b/pkg/config/dynamic/tcp_middlewares.go @@ -0,0 +1,15 @@ +package dynamic + +// +k8s:deepcopy-gen=true + +// TCPMiddleware holds the TCPMiddleware configuration. +type TCPMiddleware struct { + IPWhiteList *TCPIPWhiteList `json:"ipWhiteList,omitempty" toml:"ipWhiteList,omitempty" yaml:"ipWhiteList,omitempty" export:"true"` +} + +// +k8s:deepcopy-gen=true + +// TCPIPWhiteList holds the TCP ip white list configuration. +type TCPIPWhiteList struct { + SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"` +} diff --git a/pkg/config/dynamic/zz_generated.deepcopy.go b/pkg/config/dynamic/zz_generated.deepcopy.go index e3b79ad66..3c0ee71c0 100644 --- a/pkg/config/dynamic/zz_generated.deepcopy.go +++ b/pkg/config/dynamic/zz_generated.deepcopy.go @@ -1295,6 +1295,21 @@ func (in *TCPConfiguration) DeepCopyInto(out *TCPConfiguration) { (*out)[key] = outVal } } + if in.Middlewares != nil { + in, out := &in.Middlewares, &out.Middlewares + *out = make(map[string]*TCPMiddleware, len(*in)) + for key, val := range *in { + var outVal *TCPMiddleware + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = new(TCPMiddleware) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } return } @@ -1308,6 +1323,48 @@ func (in *TCPConfiguration) DeepCopy() *TCPConfiguration { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TCPIPWhiteList) DeepCopyInto(out *TCPIPWhiteList) { + *out = *in + if in.SourceRange != nil { + in, out := &in.SourceRange, &out.SourceRange + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPIPWhiteList. +func (in *TCPIPWhiteList) DeepCopy() *TCPIPWhiteList { + if in == nil { + return nil + } + out := new(TCPIPWhiteList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TCPMiddleware) DeepCopyInto(out *TCPMiddleware) { + *out = *in + if in.IPWhiteList != nil { + in, out := &in.IPWhiteList, &out.IPWhiteList + *out = new(TCPIPWhiteList) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPMiddleware. +func (in *TCPMiddleware) DeepCopy() *TCPMiddleware { + if in == nil { + return nil + } + out := new(TCPMiddleware) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TCPRouter) DeepCopyInto(out *TCPRouter) { *out = *in @@ -1316,6 +1373,11 @@ func (in *TCPRouter) DeepCopyInto(out *TCPRouter) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.Middlewares != nil { + in, out := &in.Middlewares, &out.Middlewares + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.TLS != nil { in, out := &in.TLS, &out.TLS *out = new(RouterTCPTLSConfig) diff --git a/pkg/config/label/label_test.go b/pkg/config/label/label_test.go index dfa804b37..a976c2e9a 100644 --- a/pkg/config/label/label_test.go +++ b/pkg/config/label/label_test.go @@ -169,22 +169,24 @@ func TestDecodeConfiguration(t *testing.T) { "traefik.http.services.Service1.loadbalancer.server.port": "8080", "traefik.http.services.Service1.loadbalancer.sticky": "false", "traefik.http.services.Service1.loadbalancer.sticky.cookie.name": "fui", - "traefik.tcp.routers.Router0.rule": "foobar", - "traefik.tcp.routers.Router0.entrypoints": "foobar, fiibar", - "traefik.tcp.routers.Router0.service": "foobar", - "traefik.tcp.routers.Router0.tls.passthrough": "false", - "traefik.tcp.routers.Router0.tls.options": "foo", - "traefik.tcp.routers.Router1.rule": "foobar", - "traefik.tcp.routers.Router1.entrypoints": "foobar, fiibar", - "traefik.tcp.routers.Router1.service": "foobar", - "traefik.tcp.routers.Router1.tls.options": "foo", - "traefik.tcp.routers.Router1.tls.passthrough": "false", - "traefik.tcp.services.Service0.loadbalancer.server.Port": "42", - "traefik.tcp.services.Service0.loadbalancer.TerminationDelay": "42", - "traefik.tcp.services.Service0.loadbalancer.proxyProtocol.version": "42", - "traefik.tcp.services.Service1.loadbalancer.server.Port": "42", - "traefik.tcp.services.Service1.loadbalancer.TerminationDelay": "42", - "traefik.tcp.services.Service1.loadbalancer.proxyProtocol": "true", + + "traefik.tcp.middlewares.Middleware0.ipwhitelist.sourcerange": "foobar, fiibar", + "traefik.tcp.routers.Router0.rule": "foobar", + "traefik.tcp.routers.Router0.entrypoints": "foobar, fiibar", + "traefik.tcp.routers.Router0.service": "foobar", + "traefik.tcp.routers.Router0.tls.passthrough": "false", + "traefik.tcp.routers.Router0.tls.options": "foo", + "traefik.tcp.routers.Router1.rule": "foobar", + "traefik.tcp.routers.Router1.entrypoints": "foobar, fiibar", + "traefik.tcp.routers.Router1.service": "foobar", + "traefik.tcp.routers.Router1.tls.options": "foo", + "traefik.tcp.routers.Router1.tls.passthrough": "false", + "traefik.tcp.services.Service0.loadbalancer.server.Port": "42", + "traefik.tcp.services.Service0.loadbalancer.TerminationDelay": "42", + "traefik.tcp.services.Service0.loadbalancer.proxyProtocol.version": "42", + "traefik.tcp.services.Service1.loadbalancer.server.Port": "42", + "traefik.tcp.services.Service1.loadbalancer.TerminationDelay": "42", + "traefik.tcp.services.Service1.loadbalancer.proxyProtocol": "true", "traefik.udp.routers.Router0.entrypoints": "foobar, fiibar", "traefik.udp.routers.Router0.service": "foobar", @@ -225,6 +227,13 @@ func TestDecodeConfiguration(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{ + "Middleware0": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"foobar", "fiibar"}, + }, + }, + }, Services: map[string]*dynamic.TCPService{ "Service0": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -696,6 +705,13 @@ func TestEncodeConfiguration(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{ + "Middleware0": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"foobar", "fiibar"}, + }, + }, + }, Services: map[string]*dynamic.TCPService{ "Service0": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -1289,6 +1305,7 @@ func TestEncodeConfiguration(t *testing.T) { "traefik.HTTP.Services.Service1.LoadBalancer.server.Scheme": "foobar", "traefik.HTTP.Services.Service0.LoadBalancer.HealthCheck.Headers.name0": "foobar", + "traefik.TCP.Middlewares.Middleware0.IPWhiteList.SourceRange": "foobar, fiibar", "traefik.TCP.Routers.Router0.Rule": "foobar", "traefik.TCP.Routers.Router0.EntryPoints": "foobar, fiibar", "traefik.TCP.Routers.Router0.Service": "foobar", diff --git a/pkg/config/runtime/runtime.go b/pkg/config/runtime/runtime.go index 12237cc33..9f64c7147 100644 --- a/pkg/config/runtime/runtime.go +++ b/pkg/config/runtime/runtime.go @@ -17,13 +17,14 @@ const ( // Configuration holds the information about the currently running traefik instance. type Configuration struct { - Routers map[string]*RouterInfo `json:"routers,omitempty"` - Middlewares map[string]*MiddlewareInfo `json:"middlewares,omitempty"` - Services map[string]*ServiceInfo `json:"services,omitempty"` - TCPRouters map[string]*TCPRouterInfo `json:"tcpRouters,omitempty"` - TCPServices map[string]*TCPServiceInfo `json:"tcpServices,omitempty"` - UDPRouters map[string]*UDPRouterInfo `json:"udpRouters,omitempty"` - UDPServices map[string]*UDPServiceInfo `json:"udpServices,omitempty"` + Routers map[string]*RouterInfo `json:"routers,omitempty"` + Middlewares map[string]*MiddlewareInfo `json:"middlewares,omitempty"` + TCPMiddlewares map[string]*TCPMiddlewareInfo `json:"tcpMiddlewares,omitempty"` + Services map[string]*ServiceInfo `json:"services,omitempty"` + TCPRouters map[string]*TCPRouterInfo `json:"tcpRouters,omitempty"` + TCPServices map[string]*TCPServiceInfo `json:"tcpServices,omitempty"` + UDPRouters map[string]*UDPRouterInfo `json:"udpRouters,omitempty"` + UDPServices map[string]*UDPServiceInfo `json:"udpServices,omitempty"` } // NewConfig returns a Configuration initialized with the given conf. It never returns nil. @@ -74,6 +75,13 @@ func NewConfig(conf dynamic.Configuration) *Configuration { runtimeConfig.TCPServices[k] = &TCPServiceInfo{TCPService: v, Status: StatusEnabled} } } + + if len(conf.TCP.Middlewares) > 0 { + runtimeConfig.TCPMiddlewares = make(map[string]*TCPMiddlewareInfo, len(conf.TCP.Middlewares)) + for k, v := range conf.TCP.Middlewares { + runtimeConfig.TCPMiddlewares[k] = &TCPMiddlewareInfo{TCPMiddleware: v, Status: StatusEnabled} + } + } } if conf.UDP != nil { @@ -177,6 +185,15 @@ func (c *Configuration) PopulateUsedBy() { sort.Strings(c.TCPServices[k].UsedBy) } + for midName, mid := range c.TCPMiddlewares { + // lazily initialize Status in case caller forgot to do it + if mid.Status == "" { + mid.Status = StatusEnabled + } + + sort.Strings(c.TCPMiddlewares[midName].UsedBy) + } + for routerName, routerInfo := range c.UDPRouters { // lazily initialize Status in case caller forgot to do it if routerInfo.Status == "" { diff --git a/pkg/config/runtime/runtime_tcp.go b/pkg/config/runtime/runtime_tcp.go index 18a1a0911..82d8b76f5 100644 --- a/pkg/config/runtime/runtime_tcp.go +++ b/pkg/config/runtime/runtime_tcp.go @@ -112,3 +112,33 @@ func (s *TCPServiceInfo) AddError(err error, critical bool) { s.Status = StatusWarning } } + +// TCPMiddlewareInfo holds information about a currently running middleware. +type TCPMiddlewareInfo struct { + *dynamic.TCPMiddleware // dynamic configuration + // Err contains all the errors that occurred during service creation. + Err []string `json:"error,omitempty"` + Status string `json:"status,omitempty"` + UsedBy []string `json:"usedBy,omitempty"` // list of TCP routers and services using that middleware. +} + +// AddError adds err to s.Err, if it does not already exist. +// If critical is set, m is marked as disabled. +func (m *TCPMiddlewareInfo) AddError(err error, critical bool) { + for _, value := range m.Err { + if value == err.Error() { + return + } + } + + m.Err = append(m.Err, err.Error()) + if critical { + m.Status = StatusDisabled + return + } + + // only set it to "warning" if not already in a worse state + if m.Status != StatusDisabled { + m.Status = StatusWarning + } +} diff --git a/pkg/middlewares/tcp/ipwhitelist/ip_whitelist.go b/pkg/middlewares/tcp/ipwhitelist/ip_whitelist.go new file mode 100644 index 000000000..755972e70 --- /dev/null +++ b/pkg/middlewares/tcp/ipwhitelist/ip_whitelist.go @@ -0,0 +1,65 @@ +package tcpipwhitelist + +import ( + "context" + "errors" + "fmt" + + "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v2/pkg/ip" + "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/middlewares" + "github.com/traefik/traefik/v2/pkg/tcp" +) + +const ( + typeName = "IPWhiteListerTCP" +) + +// ipWhiteLister is a middleware that provides Checks of the Requesting IP against a set of Whitelists. +type ipWhiteLister struct { + next tcp.Handler + whiteLister *ip.Checker + name string +} + +// New builds a new TCP IPWhiteLister given a list of CIDR-Strings to whitelist. +func New(ctx context.Context, next tcp.Handler, config dynamic.TCPIPWhiteList, name string) (tcp.Handler, error) { + logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)) + logger.Debug("Creating middleware") + + if len(config.SourceRange) == 0 { + return nil, errors.New("sourceRange is empty, IPWhiteLister not created") + } + + checker, err := ip.NewChecker(config.SourceRange) + if err != nil { + return nil, fmt.Errorf("cannot parse CIDR whitelist %s: %w", config.SourceRange, err) + } + + logger.Debugf("Setting up IPWhiteLister with sourceRange: %s", config.SourceRange) + + return &ipWhiteLister{ + whiteLister: checker, + next: next, + name: name, + }, nil +} + +func (wl *ipWhiteLister) ServeTCP(conn tcp.WriteCloser) { + ctx := middlewares.GetLoggerCtx(context.Background(), wl.name, typeName) + logger := log.FromContext(ctx) + + addr := conn.RemoteAddr().String() + + err := wl.whiteLister.IsAuthorized(addr) + if err != nil { + logger.Errorf("Connection from %s rejected: %v", addr, err) + conn.Close() + return + } + + logger.Debugf("Connection from %s accepted", addr) + + wl.next.ServeTCP(conn) +} diff --git a/pkg/middlewares/tcp/ipwhitelist/ip_whitelist_test.go b/pkg/middlewares/tcp/ipwhitelist/ip_whitelist_test.go new file mode 100644 index 000000000..d61111726 --- /dev/null +++ b/pkg/middlewares/tcp/ipwhitelist/ip_whitelist_test.go @@ -0,0 +1,139 @@ +package tcpipwhitelist + +import ( + "context" + "io/ioutil" + "net" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v2/pkg/tcp" +) + +func TestNewIPWhiteLister(t *testing.T) { + testCases := []struct { + desc string + whiteList dynamic.TCPIPWhiteList + expectedError bool + }{ + { + desc: "Empty config", + whiteList: dynamic.TCPIPWhiteList{}, + expectedError: true, + }, + { + desc: "invalid IP", + whiteList: dynamic.TCPIPWhiteList{ + SourceRange: []string{"foo"}, + }, + expectedError: true, + }, + { + desc: "valid IP", + whiteList: dynamic.TCPIPWhiteList{ + SourceRange: []string{"10.10.10.10"}, + }, + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + next := tcp.HandlerFunc(func(conn tcp.WriteCloser) {}) + whiteLister, err := New(context.Background(), next, test.whiteList, "traefikTest") + + if test.expectedError { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.NotNil(t, whiteLister) + } + }) + } +} + +func TestIPWhiteLister_ServeHTTP(t *testing.T) { + testCases := []struct { + desc string + whiteList dynamic.TCPIPWhiteList + remoteAddr string + expected string + }{ + { + desc: "authorized with remote address", + whiteList: dynamic.TCPIPWhiteList{ + SourceRange: []string{"20.20.20.20"}, + }, + remoteAddr: "20.20.20.20:1234", + expected: "OK", + }, + { + desc: "non authorized with remote address", + whiteList: dynamic.TCPIPWhiteList{ + SourceRange: []string{"20.20.20.20"}, + }, + remoteAddr: "20.20.20.21:1234", + }, + } + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + next := tcp.HandlerFunc(func(conn tcp.WriteCloser) { + write, err := conn.Write([]byte("OK")) + require.NoError(t, err) + assert.Equal(t, 2, write) + + err = conn.Close() + require.NoError(t, err) + }) + + whiteLister, err := New(context.Background(), next, test.whiteList, "traefikTest") + require.NoError(t, err) + + server, client := net.Pipe() + + go func() { + whiteLister.ServeTCP(&contextWriteCloser{client, addr{test.remoteAddr}}) + }() + + read, err := ioutil.ReadAll(server) + require.NoError(t, err) + + assert.Equal(t, test.expected, string(read)) + }) + } +} + +type contextWriteCloser struct { + net.Conn + addr +} + +type addr struct { + remoteAddr string +} + +func (a addr) Network() string { + panic("implement me") +} + +func (a addr) String() string { + return a.remoteAddr +} + +func (c contextWriteCloser) CloseWrite() error { + panic("implement me") +} + +func (c contextWriteCloser) RemoteAddr() net.Addr { return c.addr } + +func (c contextWriteCloser) Context() context.Context { + return context.Background() +} diff --git a/pkg/provider/configuration.go b/pkg/provider/configuration.go index a708c72af..361e8f025 100644 --- a/pkg/provider/configuration.go +++ b/pkg/provider/configuration.go @@ -25,8 +25,9 @@ func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration Services: make(map[string]*dynamic.Service), }, TCP: &dynamic.TCPConfiguration{ - Routers: make(map[string]*dynamic.TCPRouter), - Services: make(map[string]*dynamic.TCPService), + Routers: make(map[string]*dynamic.TCPRouter), + Services: make(map[string]*dynamic.TCPService), + Middlewares: make(map[string]*dynamic.TCPMiddleware), }, UDP: &dynamic.UDPConfiguration{ Routers: make(map[string]*dynamic.UDPRouter), @@ -55,6 +56,9 @@ func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration middlewaresToDelete := map[string]struct{}{} middlewares := map[string][]string{} + middlewaresTCPToDelete := map[string]struct{}{} + middlewaresTCP := map[string][]string{} + var sortedKeys []string for key := range configurations { sortedKeys = append(sortedKeys, key) @@ -111,6 +115,13 @@ func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration middlewaresToDelete[middlewareName] = struct{}{} } } + + for middlewareName, middleware := range conf.TCP.Middlewares { + middlewaresTCP[middlewareName] = append(middlewaresTCP[middlewareName], root) + if !AddMiddlewareTCP(configuration.TCP, middlewareName, middleware) { + middlewaresTCPToDelete[middlewareName] = struct{}{} + } + } } for serviceName := range servicesToDelete { @@ -155,6 +166,12 @@ func Merge(ctx context.Context, configurations map[string]*dynamic.Configuration delete(configuration.HTTP.Middlewares, middlewareName) } + for middlewareName := range middlewaresTCPToDelete { + logger.WithField(log.MiddlewareName, middlewareName). + Errorf("TCP Middleware defined multiple times with different configurations in %v", middlewaresTCP[middlewareName]) + delete(configuration.TCP.Middlewares, middlewareName) + } + return configuration } @@ -193,6 +210,16 @@ func AddRouterTCP(configuration *dynamic.TCPConfiguration, routerName string, ro return reflect.DeepEqual(configuration.Routers[routerName], router) } +// AddMiddlewareTCP Adds a middleware to a configurations. +func AddMiddlewareTCP(configuration *dynamic.TCPConfiguration, middlewareName string, middleware *dynamic.TCPMiddleware) bool { + if _, ok := configuration.Middlewares[middlewareName]; !ok { + configuration.Middlewares[middlewareName] = middleware + return true + } + + return reflect.DeepEqual(configuration.Middlewares[middlewareName], middleware) +} + // AddServiceUDP adds a service to a configuration. func AddServiceUDP(configuration *dynamic.UDPConfiguration, serviceName string, service *dynamic.UDPService) bool { if _, ok := configuration.Services[serviceName]; !ok { diff --git a/pkg/provider/consulcatalog/config_test.go b/pkg/provider/consulcatalog/config_test.go index 73713215e..1526134f5 100644 --- a/pkg/provider/consulcatalog/config_test.go +++ b/pkg/provider/consulcatalog/config_test.go @@ -37,8 +37,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: "Host(`foo.bar`)", expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -85,8 +86,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: `Host("{{ .Name }}.{{ index .Labels "traefik.domain" }}")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -131,8 +133,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: `Host("{{ .Toto }}")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -172,8 +175,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: ``, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -213,8 +217,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: DefaultTemplateRule, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -293,8 +298,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -347,8 +353,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -415,8 +422,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -472,8 +480,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -526,8 +535,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -575,8 +585,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -623,8 +634,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -669,8 +681,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -716,8 +729,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -764,8 +778,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -824,8 +839,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -879,8 +895,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -924,8 +941,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -973,8 +991,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1034,8 +1053,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1098,8 +1118,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1169,8 +1190,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1232,8 +1254,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1298,8 +1321,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1357,8 +1381,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1406,8 +1431,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1453,8 +1479,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1500,8 +1527,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1549,8 +1577,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1578,8 +1607,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1607,8 +1637,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1636,8 +1667,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1667,8 +1699,9 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Tag("traefik.tags=bar")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1698,8 +1731,9 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Tag("traefik.tags=foo")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1745,8 +1779,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1785,6 +1820,62 @@ func Test_buildConfiguration(t *testing.T) { }, }, }, + { + desc: "Middlewares used in TCP router", + items: []itemData{ + { + ID: "Test", + Name: "Test", + Labels: map[string]string{ + "traefik.tcp.routers.Test.rule": "HostSNI(`foo.bar`)", + "traefik.tcp.middlewares.Middleware1.ipwhitelist.sourcerange": "foobar, fiibar", + "traefik.tcp.routers.Test.middlewares": "Middleware1", + }, + Address: "127.0.0.1", + Port: "80", + Status: api.HealthPassing, + }, + }, + expected: &dynamic.Configuration{ + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "Test": { + Service: "Test", + Rule: "HostSNI(`foo.bar`)", + Middlewares: []string{"Middleware1"}, + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{ + "Middleware1": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"foobar", "fiibar"}, + }, + }, + }, + Services: map[string]*dynamic.TCPService{ + "Test": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "127.0.0.1:80", + }, + }, + TerminationDelay: Int(100), + }, + }, + }, + }, + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + }, + }, { desc: "tcp with label", items: []itemData{ @@ -1809,6 +1900,7 @@ func Test_buildConfiguration(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "Test": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -1868,8 +1960,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1894,7 +1987,8 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "Test": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -1946,6 +2040,7 @@ func Test_buildConfiguration(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -2006,8 +2101,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2055,6 +2151,7 @@ func Test_buildConfiguration(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -2153,8 +2250,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2198,7 +2296,8 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -2253,8 +2352,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2280,7 +2380,8 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ diff --git a/pkg/provider/docker/config_test.go b/pkg/provider/docker/config_test.go index a487b2f5f..843c8735a 100644 --- a/pkg/provider/docker/config_test.go +++ b/pkg/provider/docker/config_test.go @@ -46,8 +46,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: "Host(`foo.bar`)", expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -99,8 +100,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: "Host(`{{ .Name }}.foo.bar`)", expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -154,8 +156,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: `Host("{{ .Name }}.{{ index .Labels "traefik.domain" }}")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -207,8 +210,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: `Host("{{ .Toto }}")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -255,8 +259,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: ``, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -303,8 +308,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: DefaultTemplateRule, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -393,8 +399,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -431,8 +438,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -469,8 +477,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -505,8 +514,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -573,8 +583,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -657,8 +668,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -714,8 +726,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -770,8 +783,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -824,8 +838,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -879,8 +894,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -935,8 +951,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -995,8 +1012,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1069,8 +1087,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1151,8 +1170,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1214,8 +1234,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1271,8 +1292,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1351,8 +1373,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1434,8 +1457,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1530,8 +1554,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1610,8 +1635,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1701,8 +1727,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1776,8 +1803,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1851,8 +1879,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1910,8 +1939,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1965,8 +1995,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2020,8 +2051,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2075,8 +2107,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2111,8 +2144,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2149,8 +2183,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2186,8 +2221,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2225,8 +2261,9 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "bar")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2264,8 +2301,9 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "foo")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2319,8 +2357,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2359,6 +2398,70 @@ func Test_buildConfiguration(t *testing.T) { }, }, }, + { + desc: "Middlewares used in TCP router", + containers: []dockerData{ + { + ServiceName: "Test", + Name: "Test", + Labels: map[string]string{ + "traefik.tcp.routers.Test.rule": "HostSNI(`foo.bar`)", + "traefik.tcp.middlewares.Middleware1.ipwhitelist.sourcerange": "foobar, fiibar", + "traefik.tcp.routers.Test.middlewares": "Middleware1", + }, + NetworkSettings: networkSettings{ + Ports: nat.PortMap{ + nat.Port("80/tcp"): []nat.PortBinding{}, + }, + Networks: map[string]*networkData{ + "bridge": { + Name: "bridge", + Addr: "127.0.0.1", + }, + }, + }, + }, + }, + expected: &dynamic.Configuration{ + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "Test": { + Service: "Test", + Rule: "HostSNI(`foo.bar`)", + Middlewares: []string{"Middleware1"}, + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{ + "Middleware1": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"foobar", "fiibar"}, + }, + }, + }, + Services: map[string]*dynamic.TCPService{ + "Test": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "127.0.0.1:80", + }, + }, + TerminationDelay: Int(100), + }, + }, + }, + }, + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + }, + }, { desc: "tcp with label", containers: []dockerData{ @@ -2391,6 +2494,7 @@ func Test_buildConfiguration(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "Test": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -2458,8 +2562,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2492,7 +2597,8 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "Test": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -2552,6 +2658,7 @@ func Test_buildConfiguration(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -2620,8 +2727,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2699,8 +2807,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2766,8 +2875,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2801,7 +2911,8 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -2858,8 +2969,9 @@ func Test_buildConfiguration(t *testing.T) { useBindPortIP: true, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, diff --git a/pkg/provider/ecs/config_test.go b/pkg/provider/ecs/config_test.go index ad2506694..d627598a6 100644 --- a/pkg/provider/ecs/config_test.go +++ b/pkg/provider/ecs/config_test.go @@ -39,8 +39,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: "Host(`foo.bar`)", expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -87,8 +88,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: "Host(`{{ .Name }}.foo.bar`)", expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -137,8 +139,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: `Host("{{ .Name }}.{{ index .Labels "traefik.domain" }}")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -185,8 +188,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: `Host("{{ .Toto }}")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -228,8 +232,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: ``, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -271,8 +276,9 @@ func TestDefaultRule(t *testing.T) { defaultRule: DefaultTemplateRule, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -356,8 +362,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -389,8 +396,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -422,8 +430,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -453,8 +462,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -511,8 +521,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -585,8 +596,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -637,8 +649,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -688,8 +701,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -737,8 +751,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -787,8 +802,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -838,8 +854,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -893,8 +910,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -957,8 +975,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1024,8 +1043,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1077,8 +1097,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1129,8 +1150,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1199,8 +1221,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1272,8 +1295,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1353,8 +1377,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1423,8 +1448,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1499,8 +1525,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1565,8 +1592,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1630,8 +1658,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1684,8 +1713,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1734,8 +1764,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1784,8 +1815,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1839,8 +1871,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1903,8 +1936,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1953,8 +1987,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1984,8 +2019,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2017,8 +2053,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2051,8 +2088,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2084,8 +2122,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2118,8 +2157,9 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "bar")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2152,8 +2192,9 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "foo")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2202,8 +2243,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2242,6 +2284,65 @@ func Test_buildConfiguration(t *testing.T) { }, }, }, + { + desc: "Middlewares used in TCP router", + containers: []ecsInstance{ + instance( + name("Test"), + labels(map[string]string{ + "traefik.tcp.routers.Test.rule": "HostSNI(`foo.bar`)", + "traefik.tcp.middlewares.Middleware1.ipwhitelist.sourcerange": "foobar, fiibar", + "traefik.tcp.routers.Test.middlewares": "Middleware1", + }), + iMachine( + mState(ec2.InstanceStateNameRunning), + mPrivateIP("127.0.0.1"), + mPorts( + mPort(0, 80, "tcp"), + ), + ), + ), + }, + expected: &dynamic.Configuration{ + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "Test": { + Service: "Test", + Rule: "HostSNI(`foo.bar`)", + Middlewares: []string{"Middleware1"}, + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{ + "Middleware1": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"foobar", "fiibar"}, + }, + }, + }, + Services: map[string]*dynamic.TCPService{ + "Test": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "127.0.0.1:80", + }, + }, + TerminationDelay: Int(100), + }, + }, + }, + }, + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + }, + }, { desc: "tcp with label", containers: []ecsInstance{ @@ -2269,6 +2370,7 @@ func Test_buildConfiguration(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "Test": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -2331,8 +2433,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2360,7 +2463,8 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "Test": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -2415,6 +2519,7 @@ func Test_buildConfiguration(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -2478,8 +2583,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2547,8 +2653,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -2609,8 +2716,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2639,7 +2747,8 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ diff --git a/pkg/provider/file/file.go b/pkg/provider/file/file.go index 37ee21d9f..ac7044f3f 100644 --- a/pkg/provider/file/file.go +++ b/pkg/provider/file/file.go @@ -210,8 +210,9 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st ServersTransports: make(map[string]*dynamic.ServersTransport), }, TCP: &dynamic.TCPConfiguration{ - Routers: make(map[string]*dynamic.TCPRouter), - Services: make(map[string]*dynamic.TCPService), + Routers: make(map[string]*dynamic.TCPRouter), + Services: make(map[string]*dynamic.TCPService), + Middlewares: make(map[string]*dynamic.TCPMiddleware), }, TLS: &dynamic.TLSConfiguration{ Stores: make(map[string]tls.Store), @@ -290,6 +291,14 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st } } + for name, conf := range c.TCP.Middlewares { + if _, exists := configuration.TCP.Middlewares[name]; exists { + logger.WithField(log.MiddlewareName, name).Warn("TCP middleware already configured, skipping") + } else { + configuration.TCP.Middlewares[name] = conf + } + } + for name, conf := range c.TCP.Services { if _, exists := configuration.TCP.Services[name]; exists { logger.WithField(log.ServiceName, name).Warn("TCP service already configured, skipping") @@ -412,8 +421,9 @@ func (p *Provider) decodeConfiguration(filePath, content string) (*dynamic.Confi ServersTransports: make(map[string]*dynamic.ServersTransport), }, TCP: &dynamic.TCPConfiguration{ - Routers: make(map[string]*dynamic.TCPRouter), - Services: make(map[string]*dynamic.TCPService), + Routers: make(map[string]*dynamic.TCPRouter), + Services: make(map[string]*dynamic.TCPService), + Middlewares: make(map[string]*dynamic.TCPMiddleware), }, TLS: &dynamic.TLSConfiguration{ Stores: make(map[string]tls.Store), diff --git a/pkg/provider/kubernetes/crd/client.go b/pkg/provider/kubernetes/crd/client.go index 1931f599a..549ae575d 100644 --- a/pkg/provider/kubernetes/crd/client.go +++ b/pkg/provider/kubernetes/crd/client.go @@ -36,6 +36,7 @@ type Client interface { GetIngressRouteTCPs() []*v1alpha1.IngressRouteTCP GetIngressRouteUDPs() []*v1alpha1.IngressRouteUDP GetMiddlewares() []*v1alpha1.Middleware + GetMiddlewareTCPs() []*v1alpha1.MiddlewareTCP GetTraefikService(namespace, name string) (*v1alpha1.TraefikService, bool, error) GetTraefikServices() []*v1alpha1.TraefikService GetTLSOptions() []*v1alpha1.TLSOption @@ -166,6 +167,7 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (< factoryCrd := externalversions.NewSharedInformerFactoryWithOptions(c.csCrd, resyncPeriod, externalversions.WithNamespace(ns), externalversions.WithTweakListOptions(matchesLabelSelector)) factoryCrd.Traefik().V1alpha1().IngressRoutes().Informer().AddEventHandler(eventHandler) factoryCrd.Traefik().V1alpha1().Middlewares().Informer().AddEventHandler(eventHandler) + factoryCrd.Traefik().V1alpha1().MiddlewareTCPs().Informer().AddEventHandler(eventHandler) factoryCrd.Traefik().V1alpha1().IngressRouteTCPs().Informer().AddEventHandler(eventHandler) factoryCrd.Traefik().V1alpha1().IngressRouteUDPs().Informer().AddEventHandler(eventHandler) factoryCrd.Traefik().V1alpha1().TLSOptions().Informer().AddEventHandler(eventHandler) @@ -270,6 +272,20 @@ func (c *clientWrapper) GetMiddlewares() []*v1alpha1.Middleware { return result } +func (c *clientWrapper) GetMiddlewareTCPs() []*v1alpha1.MiddlewareTCP { + var result []*v1alpha1.MiddlewareTCP + + for ns, factory := range c.factoriesCrd { + middlewares, err := factory.Traefik().V1alpha1().MiddlewareTCPs().Lister().List(labels.Everything()) + if err != nil { + log.Errorf("Failed to list TCP middlewares in namespace %s: %v", ns, err) + } + result = append(result, middlewares...) + } + + return result +} + // GetTraefikService returns the named service from the given namespace. func (c *clientWrapper) GetTraefikService(namespace, name string) (*v1alpha1.TraefikService, bool, error) { if !c.isWatchedNamespace(namespace) { diff --git a/pkg/provider/kubernetes/crd/client_mock_test.go b/pkg/provider/kubernetes/crd/client_mock_test.go index 07c39f766..5e018ca6d 100644 --- a/pkg/provider/kubernetes/crd/client_mock_test.go +++ b/pkg/provider/kubernetes/crd/client_mock_test.go @@ -34,6 +34,7 @@ type clientMock struct { ingressRouteTCPs []*v1alpha1.IngressRouteTCP ingressRouteUDPs []*v1alpha1.IngressRouteUDP middlewares []*v1alpha1.Middleware + middlewareTCPs []*v1alpha1.MiddlewareTCP tlsOptions []*v1alpha1.TLSOption tlsStores []*v1alpha1.TLSStore traefikServices []*v1alpha1.TraefikService @@ -66,6 +67,8 @@ func newClientMock(paths ...string) clientMock { c.ingressRouteUDPs = append(c.ingressRouteUDPs, o) case *v1alpha1.Middleware: c.middlewares = append(c.middlewares, o) + case *v1alpha1.MiddlewareTCP: + c.middlewareTCPs = append(c.middlewareTCPs, o) case *v1alpha1.TraefikService: c.traefikServices = append(c.traefikServices, o) case *v1alpha1.TLSOption: @@ -101,6 +104,10 @@ func (c clientMock) GetMiddlewares() []*v1alpha1.Middleware { return c.middlewares } +func (c clientMock) GetMiddlewareTCPs() []*v1alpha1.MiddlewareTCP { + return c.middlewareTCPs +} + func (c clientMock) GetTraefikService(namespace, name string) (*v1alpha1.TraefikService, bool, error) { for _, svc := range c.traefikServices { if svc.Namespace == namespace && svc.Name == name { diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware.yml new file mode 100644 index 000000000..b36e821b2 --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware.yml @@ -0,0 +1,41 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: MiddlewareTCP +metadata: + name: ipwhitelist + namespace: default +spec: + ipWhiteList: + sourceRange: + - 127.0.0.1/32 + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: MiddlewareTCP +metadata: + name: ipwhitelist + namespace: foo +spec: + ipWhiteList: + sourceRange: + - 127.0.0.1/32 +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRouteTCP +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - match: HostSNI(`foo.com`) + services: + - name: whoamitcp + port: 8000 + + middlewares: + - name: ipwhitelist + - name: ipwhitelist + namespace: foo diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_crossprovider.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_crossprovider.yml new file mode 100644 index 000000000..b672e56e9 --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_crossprovider.yml @@ -0,0 +1,44 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: MiddlewareTCP +metadata: + name: ipwhitelist + namespace: default +spec: + ipWhiteList: + sourceRange: + - 127.0.0.1/32 + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: MiddlewareTCP +metadata: + name: ipwhitelist + namespace: foo +spec: + ipWhiteList: + sourceRange: + - 127.0.0.1/32 +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRouteTCP +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - match: HostSNI(`foo.com`) + services: + - name: whoamitcp + port: 8000 + + middlewares: + - name: ipwhitelist + - name: ipwhitelist + namespace: foo + - name: ipwhitelist@file + - name: ipwhitelist-foo@file + namespace: foo diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_with_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_with_cross_namespace.yml new file mode 100644 index 000000000..af8dd075d --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_middleware_with_cross_namespace.yml @@ -0,0 +1,48 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: MiddlewareTCP +metadata: + name: ipwhitelist + namespace: default +spec: + ipWhiteList: + sourceRange: + - 127.0.0.1/32 + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: MiddlewareTCP +metadata: + name: ipwhitelist + namespace: cross-ns +spec: + ipWhiteList: + sourceRange: + - 127.0.0.1/32 +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRouteTCP +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - match: HostSNI(`foo.com`) + services: + - name: whoamitcp + port: 8000 + + middlewares: + - name: ipwhitelist + + - match: HostSNI(`bar.com`) + services: + - name: whoamitcp + port: 8000 + + middlewares: + - name: ipwhitelist + namespace: cross-ns diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_middlewaretcp.go new file mode 100644 index 000000000..8e24f1c2f --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_middlewaretcp.go @@ -0,0 +1,138 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016-2020 Containous SAS; 2020-2021 Traefik Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeMiddlewareTCPs implements MiddlewareTCPInterface +type FakeMiddlewareTCPs struct { + Fake *FakeTraefikV1alpha1 + ns string +} + +var middlewaretcpsResource = schema.GroupVersionResource{Group: "traefik.containo.us", Version: "v1alpha1", Resource: "middlewaretcps"} + +var middlewaretcpsKind = schema.GroupVersionKind{Group: "traefik.containo.us", Version: "v1alpha1", Kind: "MiddlewareTCP"} + +// Get takes name of the middlewareTCP, and returns the corresponding middlewareTCP object, and an error if there is any. +func (c *FakeMiddlewareTCPs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.MiddlewareTCP, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(middlewaretcpsResource, c.ns, name), &v1alpha1.MiddlewareTCP{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.MiddlewareTCP), err +} + +// List takes label and field selectors, and returns the list of MiddlewareTCPs that match those selectors. +func (c *FakeMiddlewareTCPs) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.MiddlewareTCPList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(middlewaretcpsResource, middlewaretcpsKind, c.ns, opts), &v1alpha1.MiddlewareTCPList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.MiddlewareTCPList{ListMeta: obj.(*v1alpha1.MiddlewareTCPList).ListMeta} + for _, item := range obj.(*v1alpha1.MiddlewareTCPList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested middlewareTCPs. +func (c *FakeMiddlewareTCPs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(middlewaretcpsResource, c.ns, opts)) + +} + +// Create takes the representation of a middlewareTCP and creates it. Returns the server's representation of the middlewareTCP, and an error, if there is any. +func (c *FakeMiddlewareTCPs) Create(ctx context.Context, middlewareTCP *v1alpha1.MiddlewareTCP, opts v1.CreateOptions) (result *v1alpha1.MiddlewareTCP, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(middlewaretcpsResource, c.ns, middlewareTCP), &v1alpha1.MiddlewareTCP{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.MiddlewareTCP), err +} + +// Update takes the representation of a middlewareTCP and updates it. Returns the server's representation of the middlewareTCP, and an error, if there is any. +func (c *FakeMiddlewareTCPs) Update(ctx context.Context, middlewareTCP *v1alpha1.MiddlewareTCP, opts v1.UpdateOptions) (result *v1alpha1.MiddlewareTCP, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(middlewaretcpsResource, c.ns, middlewareTCP), &v1alpha1.MiddlewareTCP{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.MiddlewareTCP), err +} + +// Delete takes name of the middlewareTCP and deletes it. Returns an error if one occurs. +func (c *FakeMiddlewareTCPs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(middlewaretcpsResource, c.ns, name), &v1alpha1.MiddlewareTCP{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeMiddlewareTCPs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(middlewaretcpsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.MiddlewareTCPList{}) + return err +} + +// Patch applies the patch and returns the patched middlewareTCP. +func (c *FakeMiddlewareTCPs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.MiddlewareTCP, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(middlewaretcpsResource, c.ns, name, pt, data, subresources...), &v1alpha1.MiddlewareTCP{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.MiddlewareTCP), err +} diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go index e07955385..af47edde8 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/fake/fake_traefik_client.go @@ -52,6 +52,10 @@ func (c *FakeTraefikV1alpha1) Middlewares(namespace string) v1alpha1.MiddlewareI return &FakeMiddlewares{c, namespace} } +func (c *FakeTraefikV1alpha1) MiddlewareTCPs(namespace string) v1alpha1.MiddlewareTCPInterface { + return &FakeMiddlewareTCPs{c, namespace} +} + func (c *FakeTraefikV1alpha1) ServersTransports(namespace string) v1alpha1.ServersTransportInterface { return &FakeServersTransports{c, namespace} } diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go index bfc76aeee..242386c1a 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/generated_expansion.go @@ -34,6 +34,8 @@ type IngressRouteUDPExpansion interface{} type MiddlewareExpansion interface{} +type MiddlewareTCPExpansion interface{} + type ServersTransportExpansion interface{} type TLSOptionExpansion interface{} diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middlewaretcp.go new file mode 100644 index 000000000..af56499ed --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/middlewaretcp.go @@ -0,0 +1,186 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016-2020 Containous SAS; 2020-2021 Traefik Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + scheme "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned/scheme" + v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// MiddlewareTCPsGetter has a method to return a MiddlewareTCPInterface. +// A group's client should implement this interface. +type MiddlewareTCPsGetter interface { + MiddlewareTCPs(namespace string) MiddlewareTCPInterface +} + +// MiddlewareTCPInterface has methods to work with MiddlewareTCP resources. +type MiddlewareTCPInterface interface { + Create(ctx context.Context, middlewareTCP *v1alpha1.MiddlewareTCP, opts v1.CreateOptions) (*v1alpha1.MiddlewareTCP, error) + Update(ctx context.Context, middlewareTCP *v1alpha1.MiddlewareTCP, opts v1.UpdateOptions) (*v1alpha1.MiddlewareTCP, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.MiddlewareTCP, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.MiddlewareTCPList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.MiddlewareTCP, err error) + MiddlewareTCPExpansion +} + +// middlewareTCPs implements MiddlewareTCPInterface +type middlewareTCPs struct { + client rest.Interface + ns string +} + +// newMiddlewareTCPs returns a MiddlewareTCPs +func newMiddlewareTCPs(c *TraefikV1alpha1Client, namespace string) *middlewareTCPs { + return &middlewareTCPs{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the middlewareTCP, and returns the corresponding middlewareTCP object, and an error if there is any. +func (c *middlewareTCPs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.MiddlewareTCP, err error) { + result = &v1alpha1.MiddlewareTCP{} + err = c.client.Get(). + Namespace(c.ns). + Resource("middlewaretcps"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of MiddlewareTCPs that match those selectors. +func (c *middlewareTCPs) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.MiddlewareTCPList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.MiddlewareTCPList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("middlewaretcps"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested middlewareTCPs. +func (c *middlewareTCPs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("middlewaretcps"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a middlewareTCP and creates it. Returns the server's representation of the middlewareTCP, and an error, if there is any. +func (c *middlewareTCPs) Create(ctx context.Context, middlewareTCP *v1alpha1.MiddlewareTCP, opts v1.CreateOptions) (result *v1alpha1.MiddlewareTCP, err error) { + result = &v1alpha1.MiddlewareTCP{} + err = c.client.Post(). + Namespace(c.ns). + Resource("middlewaretcps"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(middlewareTCP). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a middlewareTCP and updates it. Returns the server's representation of the middlewareTCP, and an error, if there is any. +func (c *middlewareTCPs) Update(ctx context.Context, middlewareTCP *v1alpha1.MiddlewareTCP, opts v1.UpdateOptions) (result *v1alpha1.MiddlewareTCP, err error) { + result = &v1alpha1.MiddlewareTCP{} + err = c.client.Put(). + Namespace(c.ns). + Resource("middlewaretcps"). + Name(middlewareTCP.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(middlewareTCP). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the middlewareTCP and deletes it. Returns an error if one occurs. +func (c *middlewareTCPs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("middlewaretcps"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *middlewareTCPs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("middlewaretcps"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched middlewareTCP. +func (c *middlewareTCPs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.MiddlewareTCP, err error) { + result = &v1alpha1.MiddlewareTCP{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("middlewaretcps"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go index ab4d0b375..2d2f8b383 100644 --- a/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go +++ b/pkg/provider/kubernetes/crd/generated/clientset/versioned/typed/traefik/v1alpha1/traefik_client.go @@ -38,6 +38,7 @@ type TraefikV1alpha1Interface interface { IngressRouteTCPsGetter IngressRouteUDPsGetter MiddlewaresGetter + MiddlewareTCPsGetter ServersTransportsGetter TLSOptionsGetter TLSStoresGetter @@ -65,6 +66,10 @@ func (c *TraefikV1alpha1Client) Middlewares(namespace string) MiddlewareInterfac return newMiddlewares(c, namespace) } +func (c *TraefikV1alpha1Client) MiddlewareTCPs(namespace string) MiddlewareTCPInterface { + return newMiddlewareTCPs(c, namespace) +} + func (c *TraefikV1alpha1Client) ServersTransports(namespace string) ServersTransportInterface { return newServersTransports(c, namespace) } diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go index 9d130626f..90adc6103 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/generic.go @@ -69,6 +69,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Traefik().V1alpha1().IngressRouteUDPs().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("middlewares"): return &genericInformer{resource: resource.GroupResource(), informer: f.Traefik().V1alpha1().Middlewares().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("middlewaretcps"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Traefik().V1alpha1().MiddlewareTCPs().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("serverstransports"): return &genericInformer{resource: resource.GroupResource(), informer: f.Traefik().V1alpha1().ServersTransports().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("tlsoptions"): diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go index 0fc9d02b8..9f06f1b04 100644 --- a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/interface.go @@ -40,6 +40,8 @@ type Interface interface { IngressRouteUDPs() IngressRouteUDPInformer // Middlewares returns a MiddlewareInformer. Middlewares() MiddlewareInformer + // MiddlewareTCPs returns a MiddlewareTCPInformer. + MiddlewareTCPs() MiddlewareTCPInformer // ServersTransports returns a ServersTransportInformer. ServersTransports() ServersTransportInformer // TLSOptions returns a TLSOptionInformer. @@ -81,6 +83,11 @@ func (v *version) Middlewares() MiddlewareInformer { return &middlewareInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } +// MiddlewareTCPs returns a MiddlewareTCPInformer. +func (v *version) MiddlewareTCPs() MiddlewareTCPInformer { + return &middlewareTCPInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // ServersTransports returns a ServersTransportInformer. func (v *version) ServersTransports() ServersTransportInformer { return &serversTransportInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middlewaretcp.go new file mode 100644 index 000000000..8d83310fe --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/informers/externalversions/traefik/v1alpha1/middlewaretcp.go @@ -0,0 +1,98 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016-2020 Containous SAS; 2020-2021 Traefik Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + versioned "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/clientset/versioned" + internalinterfaces "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1" + traefikv1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// MiddlewareTCPInformer provides access to a shared informer and lister for +// MiddlewareTCPs. +type MiddlewareTCPInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.MiddlewareTCPLister +} + +type middlewareTCPInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewMiddlewareTCPInformer constructs a new informer for MiddlewareTCP type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewMiddlewareTCPInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredMiddlewareTCPInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredMiddlewareTCPInformer constructs a new informer for MiddlewareTCP type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredMiddlewareTCPInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TraefikV1alpha1().MiddlewareTCPs(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TraefikV1alpha1().MiddlewareTCPs(namespace).Watch(context.TODO(), options) + }, + }, + &traefikv1alpha1.MiddlewareTCP{}, + resyncPeriod, + indexers, + ) +} + +func (f *middlewareTCPInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredMiddlewareTCPInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *middlewareTCPInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&traefikv1alpha1.MiddlewareTCP{}, f.defaultInformer) +} + +func (f *middlewareTCPInformer) Lister() v1alpha1.MiddlewareTCPLister { + return v1alpha1.NewMiddlewareTCPLister(f.Informer().GetIndexer()) +} diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go index f5eac1051..b0b4a5ffb 100644 --- a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/expansion_generated.go @@ -58,6 +58,14 @@ type MiddlewareListerExpansion interface{} // MiddlewareNamespaceLister. type MiddlewareNamespaceListerExpansion interface{} +// MiddlewareTCPListerExpansion allows custom methods to be added to +// MiddlewareTCPLister. +type MiddlewareTCPListerExpansion interface{} + +// MiddlewareTCPNamespaceListerExpansion allows custom methods to be added to +// MiddlewareTCPNamespaceLister. +type MiddlewareTCPNamespaceListerExpansion interface{} + // ServersTransportListerExpansion allows custom methods to be added to // ServersTransportLister. type ServersTransportListerExpansion interface{} diff --git a/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middlewaretcp.go new file mode 100644 index 000000000..6ca3b9356 --- /dev/null +++ b/pkg/provider/kubernetes/crd/generated/listers/traefik/v1alpha1/middlewaretcp.go @@ -0,0 +1,107 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016-2020 Containous SAS; 2020-2021 Traefik Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// MiddlewareTCPLister helps list MiddlewareTCPs. +// All objects returned here must be treated as read-only. +type MiddlewareTCPLister interface { + // List lists all MiddlewareTCPs in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.MiddlewareTCP, err error) + // MiddlewareTCPs returns an object that can list and get MiddlewareTCPs. + MiddlewareTCPs(namespace string) MiddlewareTCPNamespaceLister + MiddlewareTCPListerExpansion +} + +// middlewareTCPLister implements the MiddlewareTCPLister interface. +type middlewareTCPLister struct { + indexer cache.Indexer +} + +// NewMiddlewareTCPLister returns a new MiddlewareTCPLister. +func NewMiddlewareTCPLister(indexer cache.Indexer) MiddlewareTCPLister { + return &middlewareTCPLister{indexer: indexer} +} + +// List lists all MiddlewareTCPs in the indexer. +func (s *middlewareTCPLister) List(selector labels.Selector) (ret []*v1alpha1.MiddlewareTCP, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.MiddlewareTCP)) + }) + return ret, err +} + +// MiddlewareTCPs returns an object that can list and get MiddlewareTCPs. +func (s *middlewareTCPLister) MiddlewareTCPs(namespace string) MiddlewareTCPNamespaceLister { + return middlewareTCPNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// MiddlewareTCPNamespaceLister helps list and get MiddlewareTCPs. +// All objects returned here must be treated as read-only. +type MiddlewareTCPNamespaceLister interface { + // List lists all MiddlewareTCPs in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.MiddlewareTCP, err error) + // Get retrieves the MiddlewareTCP from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.MiddlewareTCP, error) + MiddlewareTCPNamespaceListerExpansion +} + +// middlewareTCPNamespaceLister implements the MiddlewareTCPNamespaceLister +// interface. +type middlewareTCPNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all MiddlewareTCPs in the indexer for a given namespace. +func (s middlewareTCPNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.MiddlewareTCP, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.MiddlewareTCP)) + }) + return ret, err +} + +// Get retrieves the MiddlewareTCP from the indexer for a given namespace and name. +func (s middlewareTCPNamespaceLister) Get(name string) (*v1alpha1.MiddlewareTCP, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("middlewaretcp"), name) + } + return obj.(*v1alpha1.MiddlewareTCP), nil +} diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index 086757fe9..7b1299aff 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -266,6 +266,14 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) } } + for _, middlewareTCP := range client.GetMiddlewareTCPs() { + id := provider.Normalize(makeID(middlewareTCP.Namespace, middlewareTCP.Name)) + + conf.TCP.Middlewares[id] = &dynamic.TCPMiddleware{ + IPWhiteList: middlewareTCP.Spec.IPWhiteList, + } + } + cb := configBuilder{client, p.AllowCrossNamespace} for _, service := range client.GetTraefikServices() { diff --git a/pkg/provider/kubernetes/crd/kubernetes_tcp.go b/pkg/provider/kubernetes/crd/kubernetes_tcp.go index 115522032..e283ecbdf 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_tcp.go +++ b/pkg/provider/kubernetes/crd/kubernetes_tcp.go @@ -17,8 +17,9 @@ import ( func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client Client, tlsConfigs map[string]*tls.CertAndStores) *dynamic.TCPConfiguration { conf := &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, } for _, ingressRouteTCP := range client.GetIngressRouteTCPs() { @@ -52,6 +53,12 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client continue } + mds, err := p.makeMiddlewareTCPKeys(ctx, ingressRouteTCP.Namespace, route.Middlewares) + if err != nil { + logger.Errorf("Failed to create middleware keys: %v", err) + continue + } + serviceName := makeID(ingressRouteTCP.Namespace, key) for _, service := range route.Services { @@ -88,6 +95,7 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client conf.Routers[serviceName] = &dynamic.TCPRouter{ EntryPoints: ingressRouteTCP.Spec.EntryPoints, + Middlewares: mds, Rule: route.Match, Service: serviceName, } @@ -125,6 +133,35 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client return conf } +func (p *Provider) makeMiddlewareTCPKeys(ctx context.Context, ingRouteTCPNamespace string, middlewares []v1alpha1.ObjectReference) ([]string, error) { + var mds []string + + for _, mi := range middlewares { + if strings.Contains(mi.Name, providerNamespaceSeparator) { + if len(mi.Namespace) > 0 { + log.FromContext(ctx). + WithField(log.MiddlewareName, mi.Name). + Warnf("namespace %q is ignored in cross-provider context", mi.Namespace) + } + mds = append(mds, mi.Name) + continue + } + + ns := ingRouteTCPNamespace + if len(mi.Namespace) > 0 { + if !isNamespaceAllowed(p.AllowCrossNamespace, ingRouteTCPNamespace, mi.Namespace) { + return nil, fmt.Errorf("middleware %s/%s is not in the IngressRouteTCP namespace %s", mi.Namespace, mi.Name, ingRouteTCPNamespace) + } + + ns = mi.Namespace + } + + mds = append(mds, makeID(ns, mi.Name)) + } + + return mds, nil +} + func (p *Provider) createLoadBalancerServerTCP(client Client, parentNamespace string, service v1alpha1.ServiceTCP) (*dynamic.TCPService, error) { ns := parentNamespace if len(service.Namespace) > 0 { diff --git a/pkg/provider/kubernetes/crd/kubernetes_test.go b/pkg/provider/kubernetes/crd/kubernetes_test.go index 51b1dd465..c0c3640b3 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_test.go +++ b/pkg/provider/kubernetes/crd/kubernetes_test.go @@ -42,8 +42,9 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -76,6 +77,113 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Rule: "HostSNI(`foo.com`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{ + "default-test.route-fdd3e9338e47a45efefc": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.1:8000", + }, + { + Address: "10.10.0.2:8000", + }, + }, + }, + }, + }, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "Simple Ingress Route, with foo entrypoint and middleware", + paths: []string{"tcp/services.yml", "tcp/with_middleware.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + ServersTransports: map[string]*dynamic.ServersTransport{}, + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "default-test.route-fdd3e9338e47a45efefc": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-fdd3e9338e47a45efefc", + Middlewares: []string{"default-ipwhitelist", "foo-ipwhitelist"}, + Rule: "HostSNI(`foo.com`)", + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{ + "default-ipwhitelist": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + "foo-ipwhitelist": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + }, + Services: map[string]*dynamic.TCPService{ + "default-test.route-fdd3e9338e47a45efefc": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.1:8000", + }, + { + Address: "10.10.0.2:8000", + }, + }, + }, + }, + }, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "Simple Ingress Route, with foo entrypoint and crossprovider middleware", + paths: []string{"tcp/services.yml", "tcp/with_middleware_crossprovider.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + ServersTransports: map[string]*dynamic.ServersTransport{}, + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "default-test.route-fdd3e9338e47a45efefc": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-fdd3e9338e47a45efefc", + Middlewares: []string{"default-ipwhitelist", "foo-ipwhitelist", "ipwhitelist@file", "ipwhitelist-foo@file"}, + Rule: "HostSNI(`foo.com`)", + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{ + "default-ipwhitelist": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + "foo-ipwhitelist": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + }, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -115,6 +223,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Rule: "HostSNI(`bar.com`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -167,6 +276,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Rule: "HostSNI(`foo.com`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -207,6 +317,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Rule: "HostSNI(`foo.com`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -273,6 +384,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Rule: "HostSNI(`foo.com`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -349,8 +461,9 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -370,8 +483,9 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -409,6 +523,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -451,6 +566,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -514,6 +630,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -575,6 +692,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -635,6 +753,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -684,6 +803,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -733,6 +853,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -773,6 +894,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -814,6 +936,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Rule: "HostSNI(`foo.com`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -861,6 +984,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -904,6 +1028,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Rule: "HostSNI(`foo.com`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -941,6 +1066,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Rule: "HostSNI(`foo.com`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -978,7 +1104,8 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Rule: "HostSNI(`foo.com`)", }, }, - Services: map[string]*dynamic.TCPService{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -1024,6 +1151,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Rule: "HostSNI(`*`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-673acf455cb2dab0b43a": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -1112,6 +1240,48 @@ func TestLoadIngressRouteTCPs(t *testing.T) { TLS: &dynamic.TLSConfiguration{}, }, }, + { + desc: "TCP with proxyProtocol Version", + paths: []string{"tcp/services.yml", "tcp/with_proxyprotocol.yml"}, + expected: &dynamic.Configuration{ + TLS: &dynamic.TLSConfiguration{}, + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "default-test.route-fdd3e9338e47a45efefc": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-fdd3e9338e47a45efefc", + Rule: "HostSNI(`foo.com`)", + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{ + "default-test.route-fdd3e9338e47a45efefc": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.1:8000", + }, + { + Address: "10.10.0.2:8000", + }, + }, + ProxyProtocol: &dynamic.ProxyProtocol{Version: 2}, + }, + }, + }, + }, + HTTP: &dynamic.HTTPConfiguration{ + ServersTransports: map[string]*dynamic.ServersTransport{}, + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + }, + }, } for _, test := range testCases { @@ -1149,8 +1319,9 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -1170,8 +1341,9 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -1212,8 +1384,9 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -1267,8 +1440,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -1320,8 +1494,9 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -1382,8 +1557,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -1451,8 +1627,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -1503,8 +1680,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -1548,8 +1726,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -1671,8 +1850,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -1737,8 +1917,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -1828,8 +2009,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2005,8 +2187,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2068,8 +2251,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2151,8 +2335,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2221,8 +2406,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2242,8 +2428,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2263,8 +2450,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2293,8 +2481,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2355,8 +2544,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2402,8 +2592,9 @@ func TestLoadIngressRoutes(t *testing.T) { Options: map[string]tls.Options{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2466,8 +2657,9 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2529,8 +2721,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2591,8 +2784,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2642,8 +2836,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2693,8 +2888,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2738,8 +2934,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2781,8 +2978,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2823,8 +3021,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2865,8 +3064,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2907,8 +3107,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, TLS: &dynamic.TLSConfiguration{}, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2949,8 +3150,9 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -2983,47 +3185,6 @@ func TestLoadIngressRoutes(t *testing.T) { TLS: &dynamic.TLSConfiguration{}, }, }, - { - desc: "TCP with proxyProtocol Version", - paths: []string{"tcp/services.yml", "tcp/with_proxyprotocol.yml"}, - expected: &dynamic.Configuration{ - TLS: &dynamic.TLSConfiguration{}, - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{ - "default-test.route-fdd3e9338e47a45efefc": { - EntryPoints: []string{"foo"}, - Service: "default-test.route-fdd3e9338e47a45efefc", - Rule: "HostSNI(`foo.com`)", - }, - }, - Services: map[string]*dynamic.TCPService{ - "default-test.route-fdd3e9338e47a45efefc": { - LoadBalancer: &dynamic.TCPServersLoadBalancer{ - Servers: []dynamic.TCPServer{ - { - Address: "10.10.0.1:8000", - }, - { - Address: "10.10.0.2:8000", - }, - }, - ProxyProtocol: &dynamic.ProxyProtocol{Version: 2}, - }, - }, - }, - }, - HTTP: &dynamic.HTTPConfiguration{ - ServersTransports: map[string]*dynamic.ServersTransport{}, - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{}, - }, - }, - }, { desc: "TLS with tls store", paths: []string{"services.yml", "with_tls_store.yml"}, @@ -3043,8 +3204,9 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -3088,8 +3250,9 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -3133,8 +3296,9 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -3171,8 +3335,9 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -3209,8 +3374,9 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -3247,8 +3413,9 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -3268,8 +3435,9 @@ func TestLoadIngressRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{ @@ -3332,8 +3500,9 @@ func TestLoadIngressRouteUDPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -3377,8 +3546,9 @@ func TestLoadIngressRouteUDPs(t *testing.T) { Services: map[string]*dynamic.Service{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, TLS: &dynamic.TLSConfiguration{}, }, @@ -3426,8 +3596,9 @@ func TestLoadIngressRouteUDPs(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -3491,8 +3662,9 @@ func TestLoadIngressRouteUDPs(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -3572,8 +3744,9 @@ func TestLoadIngressRouteUDPs(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -3608,8 +3781,9 @@ func TestLoadIngressRouteUDPs(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -3644,8 +3818,9 @@ func TestLoadIngressRouteUDPs(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -3670,8 +3845,9 @@ func TestLoadIngressRouteUDPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -3692,8 +3868,9 @@ func TestLoadIngressRouteUDPs(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -4042,8 +4219,9 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -4063,8 +4241,9 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -4114,8 +4293,9 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -4207,8 +4387,9 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -4330,8 +4511,9 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -4390,6 +4572,131 @@ func TestCrossNamespace(t *testing.T) { TLS: &dynamic.TLSConfiguration{}, }, }, + { + desc: "TCP middleware cross namespace disallowed", + paths: []string{"tcp/services.yml", "tcp/with_middleware_with_cross_namespace.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "default-test.route-fdd3e9338e47a45efefc": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-fdd3e9338e47a45efefc", + Middlewares: []string{"default-ipwhitelist"}, + Rule: "HostSNI(`foo.com`)", + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{ + "default-ipwhitelist": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + "cross-ns-ipwhitelist": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + }, + Services: map[string]*dynamic.TCPService{ + "default-test.route-fdd3e9338e47a45efefc": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.1:8000", + }, + { + Address: "10.10.0.2:8000", + }, + }, + }, + }, + }, + }, + HTTP: &dynamic.HTTPConfiguration{ + ServersTransports: map[string]*dynamic.ServersTransport{}, + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "TCP middleware cross namespace allowed", + paths: []string{"tcp/services.yml", "tcp/with_middleware_with_cross_namespace.yml"}, + allowCrossNamespace: true, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "default-test.route-fdd3e9338e47a45efefc": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-fdd3e9338e47a45efefc", + Middlewares: []string{"default-ipwhitelist"}, + Rule: "HostSNI(`foo.com`)", + }, + "default-test.route-f44ce589164e656d231c": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-f44ce589164e656d231c", + Middlewares: []string{"cross-ns-ipwhitelist"}, + Rule: "HostSNI(`bar.com`)", + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{ + "default-ipwhitelist": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + "cross-ns-ipwhitelist": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"127.0.0.1/32"}, + }, + }, + }, + Services: map[string]*dynamic.TCPService{ + "default-test.route-f44ce589164e656d231c": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.1:8000", + }, + { + Address: "10.10.0.2:8000", + }, + }, + }, + }, + "default-test.route-fdd3e9338e47a45efefc": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.1:8000", + }, + { + Address: "10.10.0.2:8000", + }, + }, + }, + }, + }, + }, + HTTP: &dynamic.HTTPConfiguration{ + ServersTransports: map[string]*dynamic.ServersTransport{}, + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, { desc: "TCP cross namespace allowed", paths: []string{"tcp/services.yml", "tcp/with_cross_namespace.yml"}, @@ -4413,6 +4720,7 @@ func TestCrossNamespace(t *testing.T) { Rule: "HostSNI(`foo.com`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-test.route-fdd3e9338e47a45efefc": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -4448,7 +4756,8 @@ func TestCrossNamespace(t *testing.T) { Rule: "HostSNI(`foo.com`)", }, }, - Services: map[string]*dynamic.TCPService{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -4493,8 +4802,9 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.Service{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, TLS: &dynamic.TLSConfiguration{}, }, @@ -4514,8 +4824,9 @@ func TestCrossNamespace(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ ServersTransports: map[string]*dynamic.ServersTransport{}, @@ -4555,6 +4866,8 @@ func TestCrossNamespace(t *testing.T) { crdObjects = append(crdObjects, o) case *v1alpha1.Middleware: crdObjects = append(crdObjects, o) + case *v1alpha1.MiddlewareTCP: + crdObjects = append(crdObjects, o) case *v1alpha1.TraefikService: crdObjects = append(crdObjects, o) case *v1alpha1.TLSOption: @@ -4584,7 +4897,7 @@ func TestCrossNamespace(t *testing.T) { p := Provider{} p.SetDefaults() - p.AllowCrossNamespace = func(b bool) *bool { return &b }(test.allowCrossNamespace) + p.AllowCrossNamespace = Bool(test.allowCrossNamespace) conf := p.loadConfigurationFromCRD(context.Background(), client) assert.Equal(t, test.expected, conf) }) diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go index a508328e7..ef3af41cb 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroutetcp.go @@ -18,6 +18,8 @@ type IngressRouteTCPSpec struct { type RouteTCP struct { Match string `json:"match"` Services []ServiceTCP `json:"services,omitempty"` + // Middlewares contains references to MiddlewareTCP resources. + Middlewares []ObjectReference `json:"middlewares,omitempty"` } // TLSTCP contains the TLS certificates configuration of the routes. @@ -34,23 +36,11 @@ type TLSTCP struct { SecretName string `json:"secretName,omitempty"` Passthrough bool `json:"passthrough,omitempty"` // Options is a reference to a TLSOption, that specifies the parameters of the TLS connection. - Options *TLSOptionTCPRef `json:"options,omitempty"` + Options *ObjectReference `json:"options,omitempty"` // Store is a reference to a TLSStore, that specifies the parameters of the TLS store. - Store *TLSStoreTCPRef `json:"store,omitempty"` - CertResolver string `json:"certResolver,omitempty"` - Domains []types.Domain `json:"domains,omitempty"` -} - -// TLSOptionTCPRef is a ref to the TLSOption resources. -type TLSOptionTCPRef struct { - Name string `json:"name"` - Namespace string `json:"namespace,omitempty"` -} - -// TLSStoreTCPRef is a ref to the TLSStore resources. -type TLSStoreTCPRef struct { - Name string `json:"name"` - Namespace string `json:"namespace,omitempty"` + Store *ObjectReference `json:"store,omitempty"` + CertResolver string `json:"certResolver,omitempty"` + Domains []types.Domain `json:"domains,omitempty"` } // ServiceTCP defines an upstream to proxy traffic. diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/middlewaretcp.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/middlewaretcp.go new file mode 100644 index 000000000..27a796ad6 --- /dev/null +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/middlewaretcp.go @@ -0,0 +1,34 @@ +package v1alpha1 + +import ( + "github.com/traefik/traefik/v2/pkg/config/dynamic" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MiddlewareTCP is a specification for a MiddlewareTCP resource. +type MiddlewareTCP struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata"` + + Spec MiddlewareTCPSpec `json:"spec"` +} + +// +k8s:deepcopy-gen=true + +// MiddlewareTCPSpec holds the MiddlewareTCP configuration. +type MiddlewareTCPSpec struct { + IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MiddlewareTCPList is a list of MiddlewareTCP resources. +type MiddlewareTCPList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []MiddlewareTCP `json:"items"` +} diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/objectreference.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/objectreference.go new file mode 100644 index 000000000..c28d4a96d --- /dev/null +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/objectreference.go @@ -0,0 +1,7 @@ +package v1alpha1 + +// ObjectReference is a generic reference to a Traefik resource. +type ObjectReference struct { + Name string `json:"name"` + Namespace string `json:"namespace,omitempty"` +} diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go index 2f5163604..e87a2ff65 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/register.go @@ -41,6 +41,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &IngressRouteUDPList{}, &Middleware{}, &MiddlewareList{}, + &MiddlewareTCP{}, + &MiddlewareTCPList{}, &TLSOption{}, &TLSOptionList{}, &TLSStore{}, diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go index eb264ce72..05b41d74c 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/zz_generated.deepcopy.go @@ -746,6 +746,87 @@ func (in *MiddlewareSpec) DeepCopy() *MiddlewareSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MiddlewareTCP) DeepCopyInto(out *MiddlewareTCP) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MiddlewareTCP. +func (in *MiddlewareTCP) DeepCopy() *MiddlewareTCP { + if in == nil { + return nil + } + out := new(MiddlewareTCP) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MiddlewareTCP) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MiddlewareTCPList) DeepCopyInto(out *MiddlewareTCPList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]MiddlewareTCP, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MiddlewareTCPList. +func (in *MiddlewareTCPList) DeepCopy() *MiddlewareTCPList { + if in == nil { + return nil + } + out := new(MiddlewareTCPList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MiddlewareTCPList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MiddlewareTCPSpec) DeepCopyInto(out *MiddlewareTCPSpec) { + *out = *in + if in.IPWhiteList != nil { + in, out := &in.IPWhiteList, &out.IPWhiteList + *out = new(dynamic.TCPIPWhiteList) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MiddlewareTCPSpec. +func (in *MiddlewareTCPSpec) DeepCopy() *MiddlewareTCPSpec { + if in == nil { + return nil + } + out := new(MiddlewareTCPSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MirrorService) DeepCopyInto(out *MirrorService) { *out = *in @@ -792,6 +873,22 @@ func (in *Mirroring) DeepCopy() *Mirroring { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectReference) DeepCopyInto(out *ObjectReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectReference. +func (in *ObjectReference) DeepCopy() *ObjectReference { + if in == nil { + return nil + } + out := new(ObjectReference) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RateLimit) DeepCopyInto(out *RateLimit) { *out = *in @@ -878,6 +975,11 @@ func (in *RouteTCP) DeepCopyInto(out *RouteTCP) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Middlewares != nil { + in, out := &in.Middlewares, &out.Middlewares + *out = make([]ObjectReference, len(*in)) + copy(*out, *in) + } return } @@ -1238,22 +1340,6 @@ func (in *TLSOptionSpec) DeepCopy() *TLSOptionSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TLSOptionTCPRef) DeepCopyInto(out *TLSOptionTCPRef) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSOptionTCPRef. -func (in *TLSOptionTCPRef) DeepCopy() *TLSOptionTCPRef { - if in == nil { - return nil - } - out := new(TLSOptionTCPRef) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TLSOptionUDPRef) DeepCopyInto(out *TLSOptionUDPRef) { *out = *in @@ -1363,33 +1449,17 @@ func (in *TLSStoreSpec) DeepCopy() *TLSStoreSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TLSStoreTCPRef) DeepCopyInto(out *TLSStoreTCPRef) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSStoreTCPRef. -func (in *TLSStoreTCPRef) DeepCopy() *TLSStoreTCPRef { - if in == nil { - return nil - } - out := new(TLSStoreTCPRef) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TLSTCP) DeepCopyInto(out *TLSTCP) { *out = *in if in.Options != nil { in, out := &in.Options, &out.Options - *out = new(TLSOptionTCPRef) + *out = new(ObjectReference) **out = **in } if in.Store != nil { in, out := &in.Store, &out.Store - *out = new(TLSStoreTCPRef) + *out = new(ObjectReference) **out = **in } if in.Domains != nil { diff --git a/pkg/provider/kubernetes/gateway/kubernetes_test.go b/pkg/provider/kubernetes/gateway/kubernetes_test.go index d34d3fd87..13c17bc02 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes_test.go +++ b/pkg/provider/kubernetes/gateway/kubernetes_test.go @@ -32,8 +32,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -55,8 +56,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -78,8 +80,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -101,8 +104,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -124,8 +128,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -147,8 +152,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -170,8 +176,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -193,8 +200,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -216,8 +224,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -239,8 +248,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -262,8 +272,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -285,8 +296,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -308,8 +320,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -331,8 +344,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -354,8 +368,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -378,8 +393,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -401,8 +417,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -424,8 +441,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -456,8 +474,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -509,8 +528,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -538,8 +558,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -595,8 +616,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -658,8 +680,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -711,8 +734,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -764,8 +788,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -817,8 +842,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -898,8 +924,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -973,8 +1000,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1056,8 +1084,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1134,8 +1163,9 @@ func TestLoadHTTPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -1225,8 +1255,9 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1248,8 +1279,9 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1271,8 +1303,9 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1294,8 +1327,9 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1317,8 +1351,9 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1340,8 +1375,9 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1370,6 +1406,7 @@ func TestLoadTCPRoutes(t *testing.T) { Rule: "HostSNI(`*`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-tcp-app-1-my-tcp-gateway-tcp-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -1429,6 +1466,7 @@ func TestLoadTCPRoutes(t *testing.T) { Rule: "HostSNI(`*`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-tcp-app-1-my-tcp-gateway-tcp-1-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -1498,8 +1536,9 @@ func TestLoadTCPRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1528,6 +1567,7 @@ func TestLoadTCPRoutes(t *testing.T) { Rule: "HostSNI(`*`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -1585,6 +1625,7 @@ func TestLoadTCPRoutes(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -1660,8 +1701,9 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1683,8 +1725,9 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1706,8 +1749,9 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1729,8 +1773,9 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1752,8 +1797,9 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1775,8 +1821,9 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1806,8 +1853,9 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1829,8 +1877,9 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1852,8 +1901,9 @@ func TestLoadTLSRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1883,6 +1933,7 @@ func TestLoadTLSRoutes(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-tcp-app-1-my-tls-gateway-tcp-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -1947,6 +1998,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-tls-app-1-my-tls-gateway-tcp-673acf455cb2dab0b43a-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -2009,6 +2061,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-tcp-app-1-my-tls-gateway-tls-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -2093,6 +2146,7 @@ func TestLoadTLSRoutes(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-tcp-app-1-my-gateway-tls-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -2161,6 +2215,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-tls-app-1-my-gateway-tls-673acf455cb2dab0b43a-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -2216,6 +2271,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-tls-app-1-my-gateway-tls-673acf455cb2dab0b43a-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -2271,6 +2327,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-tls-app-1-my-gateway-tls-2279fe75c5156dc5eb26-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -2326,6 +2383,7 @@ func TestLoadTLSRoutes(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-tls-app-1-my-gateway-tls-177bd313b8e78ce821eb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -2394,8 +2452,9 @@ func TestLoadMixedRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2417,8 +2476,9 @@ func TestLoadMixedRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2440,8 +2500,9 @@ func TestLoadMixedRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2463,8 +2524,9 @@ func TestLoadMixedRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -2511,6 +2573,7 @@ func TestLoadMixedRoutes(t *testing.T) { }, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "default-tcp-app-1-my-gateway-tcp-e3b0c44298fc1c149afb-wrr": { Weighted: &dynamic.TCPWeightedRoundRobin{ @@ -2633,8 +2696,9 @@ func TestLoadMixedRoutes(t *testing.T) { Services: map[string]*dynamic.UDPService{}, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, diff --git a/pkg/provider/kubernetes/k8s/parser.go b/pkg/provider/kubernetes/k8s/parser.go index dac0380ad..f7336c5bd 100644 --- a/pkg/provider/kubernetes/k8s/parser.go +++ b/pkg/provider/kubernetes/k8s/parser.go @@ -12,7 +12,7 @@ import ( // MustParseYaml parses a YAML to objects. func MustParseYaml(content []byte) []runtime.Object { - acceptedK8sTypes := regexp.MustCompile(`^(Deployment|Endpoints|Service|Ingress|IngressRoute|IngressRouteTCP|IngressRouteUDP|Middleware|Secret|TLSOption|TLSStore|TraefikService|IngressClass|ServersTransport|GatewayClass|Gateway|HTTPRoute|TCPRoute|TLSRoute)$`) + acceptedK8sTypes := regexp.MustCompile(`^(Deployment|Endpoints|Service|Ingress|IngressRoute|IngressRouteTCP|IngressRouteUDP|Middleware|MiddlewareTCP|Secret|TLSOption|TLSStore|TraefikService|IngressClass|ServersTransport|GatewayClass|Gateway|HTTPRoute|TCPRoute|TLSRoute)$`) files := strings.Split(string(content), "---") retVal := make([]runtime.Object, 0, len(files)) diff --git a/pkg/provider/marathon/config_test.go b/pkg/provider/marathon/config_test.go index 872e18018..1f00c7ad6 100644 --- a/pkg/provider/marathon/config_test.go +++ b/pkg/provider/marathon/config_test.go @@ -47,8 +47,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -85,8 +86,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -109,8 +111,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -149,8 +152,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -187,6 +191,58 @@ func TestBuildConfiguration(t *testing.T) { }, }, }, + { + desc: "TCP with IP whitelist", + applications: withApplications( + application( + appID("/app"), + appPorts(80), + + withLabel("traefik.tcp.routers.Test.rule", "HostSNI(`foo.bar`)"), + withLabel("traefik.tcp.middlewares.Middleware1.ipwhitelist.sourcerange", "foobar, fiibar"), + withLabel("traefik.tcp.routers.Test.middlewares", "Middleware1"), + withTasks(localhostTask(taskPorts(80))), + )), + expected: &dynamic.Configuration{ + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "Test": { + Service: "app", + Rule: "HostSNI(`foo.bar`)", + Middlewares: []string{"Middleware1"}, + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{ + "Middleware1": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"foobar", "fiibar"}, + }, + }, + }, + Services: map[string]*dynamic.TCPService{ + "app": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "localhost:80", + }, + }, + TerminationDelay: Int(100), + }, + }, + }, + }, + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + }, + }, { desc: "2 applications in the same service", applications: withApplications( @@ -207,8 +263,9 @@ func TestBuildConfiguration(t *testing.T) { ), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -260,8 +317,9 @@ func TestBuildConfiguration(t *testing.T) { ), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -311,8 +369,9 @@ func TestBuildConfiguration(t *testing.T) { ), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -361,8 +420,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -405,8 +465,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -446,8 +507,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -487,8 +549,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -529,8 +592,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -572,8 +636,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -624,8 +689,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -664,8 +730,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -731,8 +798,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -792,8 +860,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -846,8 +915,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -893,8 +963,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -939,8 +1010,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -981,8 +1053,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1023,8 +1096,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1068,8 +1142,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1093,8 +1168,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1118,8 +1194,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1143,8 +1220,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1169,8 +1247,9 @@ func TestBuildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "bar")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1195,8 +1274,9 @@ func TestBuildConfiguration(t *testing.T) { constraints: `MarathonConstraint("rack_id:CLUSTER:rack-2")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1221,8 +1301,9 @@ func TestBuildConfiguration(t *testing.T) { constraints: `MarathonConstraint("rack_id:CLUSTER:rack-1")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1263,8 +1344,9 @@ func TestBuildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "bar")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1304,8 +1386,9 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -1353,6 +1436,7 @@ func TestBuildConfiguration(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "app": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -1407,8 +1491,9 @@ func TestBuildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1428,7 +1513,8 @@ func TestBuildConfiguration(t *testing.T) { )), expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "app": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -1473,6 +1559,7 @@ func TestBuildConfiguration(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -1528,8 +1615,9 @@ func TestBuildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -1559,6 +1647,7 @@ func TestBuildConfiguration(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -1604,6 +1693,7 @@ func TestBuildConfiguration(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -1676,8 +1766,9 @@ func TestBuildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ diff --git a/pkg/provider/rancher/config_test.go b/pkg/provider/rancher/config_test.go index 6111ab17b..bac70649f 100644 --- a/pkg/provider/rancher/config_test.go +++ b/pkg/provider/rancher/config_test.go @@ -33,8 +33,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -85,8 +86,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -151,8 +153,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -216,8 +219,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -259,8 +263,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -286,8 +291,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -316,8 +322,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -363,8 +370,9 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "bar")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -394,8 +402,9 @@ func Test_buildConfiguration(t *testing.T) { constraints: `Label("traefik.tags", "foo")`, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -441,8 +450,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -481,6 +491,62 @@ func Test_buildConfiguration(t *testing.T) { }, }, }, + { + desc: "Middlewares used in TCP router", + containers: []rancherData{ + { + Name: "Test", + Labels: map[string]string{ + "traefik.tcp.routers.Test.rule": "HostSNI(`foo.bar`)", + "traefik.tcp.middlewares.Middleware1.ipwhitelist.sourcerange": "foobar, fiibar", + "traefik.tcp.routers.Test.middlewares": "Middleware1", + }, + Port: "80/tcp", + Containers: []string{"127.0.0.1"}, + Health: "", + State: "", + }, + }, + expected: &dynamic.Configuration{ + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "Test": { + Service: "Test", + Rule: "HostSNI(`foo.bar`)", + Middlewares: []string{"Middleware1"}, + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{ + "Middleware1": { + IPWhiteList: &dynamic.TCPIPWhiteList{ + SourceRange: []string{"foobar", "fiibar"}, + }, + }, + }, + Services: map[string]*dynamic.TCPService{ + "Test": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "127.0.0.1:80", + }, + }, + TerminationDelay: Int(100), + }, + }, + }, + }, + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + }, + }, + }, { desc: "Port in labels", containers: []rancherData{ @@ -497,8 +563,9 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -551,6 +618,7 @@ func Test_buildConfiguration(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "Test": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -610,8 +678,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -636,7 +705,8 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "Test": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -684,6 +754,7 @@ func Test_buildConfiguration(t *testing.T) { Rule: "HostSNI(`foo.bar`)", }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -744,8 +815,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -780,6 +852,7 @@ func Test_buildConfiguration(t *testing.T) { TLS: &dynamic.RouterTCPTLSConfig{}, }, }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -866,8 +939,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{ @@ -911,7 +985,8 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ @@ -966,8 +1041,9 @@ func Test_buildConfiguration(t *testing.T) { }, }, TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, HTTP: &dynamic.HTTPConfiguration{ Routers: map[string]*dynamic.Router{}, @@ -993,7 +1069,8 @@ func Test_buildConfiguration(t *testing.T) { }, expected: &dynamic.Configuration{ TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, Services: map[string]*dynamic.TCPService{ "foo": { LoadBalancer: &dynamic.TCPServersLoadBalancer{ diff --git a/pkg/server/aggregator.go b/pkg/server/aggregator.go index 856cce022..2a7dfc3d3 100644 --- a/pkg/server/aggregator.go +++ b/pkg/server/aggregator.go @@ -18,8 +18,9 @@ func mergeConfiguration(configurations dynamic.Configurations, defaultEntryPoint ServersTransports: make(map[string]*dynamic.ServersTransport), }, TCP: &dynamic.TCPConfiguration{ - Routers: make(map[string]*dynamic.TCPRouter), - Services: make(map[string]*dynamic.TCPService), + Routers: make(map[string]*dynamic.TCPRouter), + Services: make(map[string]*dynamic.TCPService), + Middlewares: make(map[string]*dynamic.TCPMiddleware), }, UDP: &dynamic.UDPConfiguration{ Routers: make(map[string]*dynamic.UDPRouter), @@ -63,6 +64,9 @@ func mergeConfiguration(configurations dynamic.Configurations, defaultEntryPoint for routerName, router := range configuration.TCP.Routers { conf.TCP.Routers[provider.MakeQualifiedName(pvd, routerName)] = router } + for middlewareName, middleware := range configuration.TCP.Middlewares { + conf.TCP.Middlewares[provider.MakeQualifiedName(pvd, middlewareName)] = middleware + } for serviceName, service := range configuration.TCP.Services { conf.TCP.Services[provider.MakeQualifiedName(pvd, serviceName)] = service } diff --git a/pkg/server/configurationwatcher.go b/pkg/server/configurationwatcher.go index 1d71fe472..c7541de80 100644 --- a/pkg/server/configurationwatcher.go +++ b/pkg/server/configurationwatcher.go @@ -253,7 +253,7 @@ func isEmptyConfiguration(conf *dynamic.Configuration) bool { httpEmpty := conf.HTTP.Routers == nil && conf.HTTP.Services == nil && conf.HTTP.Middlewares == nil tlsEmpty := conf.TLS == nil || conf.TLS.Certificates == nil && conf.TLS.Stores == nil && conf.TLS.Options == nil - tcpEmpty := conf.TCP.Routers == nil && conf.TCP.Services == nil + tcpEmpty := conf.TCP.Routers == nil && conf.TCP.Services == nil && conf.TCP.Middlewares == nil udpEmpty := conf.UDP.Routers == nil && conf.UDP.Services == nil return httpEmpty && tlsEmpty && tcpEmpty && udpEmpty diff --git a/pkg/server/configurationwatcher_test.go b/pkg/server/configurationwatcher_test.go index 724d90450..276b6bc83 100644 --- a/pkg/server/configurationwatcher_test.go +++ b/pkg/server/configurationwatcher_test.go @@ -70,8 +70,9 @@ func TestNewConfigurationWatcher(t *testing.T) { th.WithLoadBalancerServices(), ), TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ @@ -225,8 +226,9 @@ func TestListenProvidersDoesNotSkipFlappingConfiguration(t *testing.T) { th.WithMiddlewares(), ), TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -284,8 +286,9 @@ func TestListenProvidersPublishesConfigForEachProvider(t *testing.T) { th.WithMiddlewares(), ), TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Services: map[string]*dynamic.TCPService{}, + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, }, TLS: &dynamic.TLSConfiguration{ Options: map[string]tls.Options{ diff --git a/pkg/server/middleware/tcp/middlewares.go b/pkg/server/middleware/tcp/middlewares.go new file mode 100644 index 000000000..4ea1697bb --- /dev/null +++ b/pkg/server/middleware/tcp/middlewares.go @@ -0,0 +1,110 @@ +package tcpmiddleware + +import ( + "context" + "fmt" + "strings" + + "github.com/traefik/traefik/v2/pkg/config/runtime" + ipwhitelist "github.com/traefik/traefik/v2/pkg/middlewares/tcp/ipwhitelist" + "github.com/traefik/traefik/v2/pkg/server/provider" + "github.com/traefik/traefik/v2/pkg/tcp" +) + +type middlewareStackType int + +const ( + middlewareStackKey middlewareStackType = iota +) + +// Builder the middleware builder. +type Builder struct { + configs map[string]*runtime.TCPMiddlewareInfo +} + +// NewBuilder creates a new Builder. +func NewBuilder(configs map[string]*runtime.TCPMiddlewareInfo) *Builder { + return &Builder{configs: configs} +} + +// BuildChain creates a middleware chain. +func (b *Builder) BuildChain(ctx context.Context, middlewares []string) *tcp.Chain { + chain := tcp.NewChain() + + for _, name := range middlewares { + middlewareName := provider.GetQualifiedName(ctx, name) + + chain = chain.Append(func(next tcp.Handler) (tcp.Handler, error) { + constructorContext := provider.AddInContext(ctx, middlewareName) + if midInf, ok := b.configs[middlewareName]; !ok || midInf.TCPMiddleware == nil { + return nil, fmt.Errorf("middleware %q does not exist", middlewareName) + } + + var err error + if constructorContext, err = checkRecursion(constructorContext, middlewareName); err != nil { + b.configs[middlewareName].AddError(err, true) + return nil, err + } + + constructor, err := b.buildConstructor(constructorContext, middlewareName) + if err != nil { + b.configs[middlewareName].AddError(err, true) + return nil, err + } + + handler, err := constructor(next) + if err != nil { + b.configs[middlewareName].AddError(err, true) + return nil, err + } + + return handler, nil + }) + } + + return &chain +} + +func checkRecursion(ctx context.Context, middlewareName string) (context.Context, error) { + currentStack, ok := ctx.Value(middlewareStackKey).([]string) + if !ok { + currentStack = []string{} + } + + if inSlice(middlewareName, currentStack) { + return ctx, fmt.Errorf("could not instantiate middleware %s: recursion detected in %s", middlewareName, strings.Join(append(currentStack, middlewareName), "->")) + } + + return context.WithValue(ctx, middlewareStackKey, append(currentStack, middlewareName)), nil +} + +func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) (tcp.Constructor, error) { + config := b.configs[middlewareName] + if config == nil || config.TCPMiddleware == nil { + return nil, fmt.Errorf("invalid middleware %q configuration", middlewareName) + } + + var middleware tcp.Constructor + + // IPWhiteList + if config.IPWhiteList != nil { + middleware = func(next tcp.Handler) (tcp.Handler, error) { + return ipwhitelist.New(ctx, next, *config.IPWhiteList, middlewareName) + } + } + + if middleware == nil { + return nil, fmt.Errorf("invalid middleware %q configuration: invalid middleware type or middleware does not exist", middlewareName) + } + + return middleware, nil +} + +func inSlice(element string, stack []string) bool { + for _, value := range stack { + if value == element { + return true + } + } + return false +} diff --git a/pkg/server/router/tcp/router.go b/pkg/server/router/tcp/router.go index 397a4bf3c..0621775dc 100644 --- a/pkg/server/router/tcp/router.go +++ b/pkg/server/router/tcp/router.go @@ -23,29 +23,36 @@ const ( defaultTLSStoreName = "default" ) +type middlewareBuilder interface { + BuildChain(ctx context.Context, names []string) *tcp.Chain +} + // NewManager Creates a new Manager. func NewManager(conf *runtime.Configuration, serviceManager *tcpservice.Manager, + middlewaresBuilder middlewareBuilder, httpHandlers map[string]http.Handler, httpsHandlers map[string]http.Handler, tlsManager *traefiktls.Manager, ) *Manager { return &Manager{ - serviceManager: serviceManager, - httpHandlers: httpHandlers, - httpsHandlers: httpsHandlers, - tlsManager: tlsManager, - conf: conf, + serviceManager: serviceManager, + middlewaresBuilder: middlewaresBuilder, + httpHandlers: httpHandlers, + httpsHandlers: httpsHandlers, + tlsManager: tlsManager, + conf: conf, } } // Manager is a route/router manager. type Manager struct { - serviceManager *tcpservice.Manager - httpHandlers map[string]http.Handler - httpsHandlers map[string]http.Handler - tlsManager *traefiktls.Manager - conf *runtime.Configuration + serviceManager *tcpservice.Manager + middlewaresBuilder middlewareBuilder + httpHandlers map[string]http.Handler + httpsHandlers map[string]http.Handler + tlsManager *traefiktls.Manager + conf *runtime.Configuration } func (m *Manager) getTCPRouters(ctx context.Context, entryPoints []string) map[string]map[string]*runtime.TCPRouterInfo { @@ -239,7 +246,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string continue } - handler, err := m.serviceManager.BuildTCP(ctxRouter, routerConfig.Service) + handler, err := m.buildTCPHandler(ctxRouter, routerConfig) if err != nil { routerConfig.AddError(err, true) logger.Error(err) @@ -299,6 +306,27 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string return router, nil } +func (m *Manager) buildTCPHandler(ctx context.Context, router *runtime.TCPRouterInfo) (tcp.Handler, error) { + var qualifiedNames []string + for _, name := range router.Middlewares { + qualifiedNames = append(qualifiedNames, provider.GetQualifiedName(ctx, name)) + } + router.Middlewares = qualifiedNames + + if router.Service == "" { + return nil, errors.New("the service is missing on the router") + } + + sHandler, err := m.serviceManager.BuildTCP(ctx, router.Service) + if err != nil { + return nil, err + } + + mHandler := m.middlewaresBuilder.BuildChain(ctx, router.Middlewares) + + return tcp.NewChain().Extend(*mHandler).Then(sHandler) +} + func findTLSOptionName(tlsOptionsForHost map[string]string, host string) string { tlsOptions, ok := tlsOptionsForHost[host] if ok { diff --git a/pkg/server/router/tcp/router_test.go b/pkg/server/router/tcp/router_test.go index ab261377b..156721aa6 100644 --- a/pkg/server/router/tcp/router_test.go +++ b/pkg/server/router/tcp/router_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/traefik/traefik/v2/pkg/config/dynamic" "github.com/traefik/traefik/v2/pkg/config/runtime" + tcpmiddleware "github.com/traefik/traefik/v2/pkg/server/middleware/tcp" "github.com/traefik/traefik/v2/pkg/server/service/tcp" traefiktls "github.com/traefik/traefik/v2/pkg/tls" ) @@ -302,7 +303,9 @@ func TestRuntimeConfiguration(t *testing.T) { }, []*traefiktls.CertAndStores{}) - routerManager := NewManager(conf, serviceManager, + middlewaresBuilder := tcpmiddleware.NewBuilder(conf.TCPMiddlewares) + + routerManager := NewManager(conf, serviceManager, middlewaresBuilder, nil, nil, tlsManager) _ = routerManager.BuildHandlers(context.Background(), entryPoints) @@ -532,7 +535,9 @@ func TestDomainFronting(t *testing.T) { "web": http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {}), } - routerManager := NewManager(conf, serviceManager, nil, httpsHandler, tlsManager) + middlewaresBuilder := tcpmiddleware.NewBuilder(conf.TCPMiddlewares) + + routerManager := NewManager(conf, serviceManager, middlewaresBuilder, nil, httpsHandler, tlsManager) routers := routerManager.BuildHandlers(context.Background(), entryPoints) diff --git a/pkg/server/routerfactory.go b/pkg/server/routerfactory.go index 25687c28c..58f4b0244 100644 --- a/pkg/server/routerfactory.go +++ b/pkg/server/routerfactory.go @@ -8,6 +8,7 @@ import ( "github.com/traefik/traefik/v2/pkg/log" "github.com/traefik/traefik/v2/pkg/metrics" "github.com/traefik/traefik/v2/pkg/server/middleware" + middlewaretcp "github.com/traefik/traefik/v2/pkg/server/middleware/tcp" "github.com/traefik/traefik/v2/pkg/server/router" routertcp "github.com/traefik/traefik/v2/pkg/server/router/tcp" routerudp "github.com/traefik/traefik/v2/pkg/server/router/udp" @@ -81,7 +82,9 @@ func (f *RouterFactory) CreateRouters(rtConf *runtime.Configuration) (map[string // TCP svcTCPManager := tcp.NewManager(rtConf) - rtTCPManager := routertcp.NewManager(rtConf, svcTCPManager, handlersNonTLS, handlersTLS, f.tlsManager) + middlewaresTCPBuilder := middlewaretcp.NewBuilder(rtConf.TCPMiddlewares) + + rtTCPManager := routertcp.NewManager(rtConf, svcTCPManager, middlewaresTCPBuilder, handlersNonTLS, handlersTLS, f.tlsManager) routersTCP := rtTCPManager.BuildHandlers(ctx, f.entryPointsTCP) // UDP diff --git a/pkg/tcp/chain.go b/pkg/tcp/chain.go new file mode 100644 index 000000000..cc192b667 --- /dev/null +++ b/pkg/tcp/chain.go @@ -0,0 +1,86 @@ +package tcp + +import ( + "fmt" +) + +// Constructor A constructor for a piece of TCP middleware. +// Some TCP middleware use this constructor out of the box, +// so in most cases you can just pass somepackage.New. +type Constructor func(Handler) (Handler, error) + +// Chain is a chain for TCP handlers. +// Chain acts as a list of tcp.Handler constructors. +// Chain is effectively immutable: +// once created, it will always hold +// the same set of constructors in the same order. +type Chain struct { + constructors []Constructor +} + +// NewChain creates a new TCP chain, +// memorizing the given list of TCP middleware constructors. +// New serves no other function, +// constructors are only called upon a call to Then(). +func NewChain(constructors ...Constructor) Chain { + return Chain{constructors: constructors} +} + +// Then adds an handler at the end of the chain. +func (c Chain) Then(h Handler) (Handler, error) { + if h == nil { + return nil, fmt.Errorf("cannot add a nil handler to the chain") + } + + for i := range c.constructors { + handler, err := c.constructors[len(c.constructors)-1-i](h) + if err != nil { + return nil, err + } + h = handler + } + + return h, nil +} + +// Append extends a chain, adding the specified constructors +// as the last ones in the request flow. +// +// Append returns a new chain, leaving the original one untouched. +// +// stdChain := tcp.NewChain(m1, m2) +// extChain := stdChain.Append(m3, m4) +// // requests in stdChain go m1 -> m2 +// // requests in extChain go m1 -> m2 -> m3 -> m4 +func (c Chain) Append(constructors ...Constructor) Chain { + newCons := make([]Constructor, 0, len(c.constructors)+len(constructors)) + newCons = append(newCons, c.constructors...) + newCons = append(newCons, constructors...) + + return Chain{newCons} +} + +// Extend extends a chain by adding the specified chain +// as the last one in the request flow. +// +// Extend returns a new chain, leaving the original one untouched. +// +// stdChain := tcp.NewChain(m1, m2) +// ext1Chain := tcp.NewChain(m3, m4) +// ext2Chain := stdChain.Extend(ext1Chain) +// // requests in stdChain go m1 -> m2 +// // requests in ext1Chain go m3 -> m4 +// // requests in ext2Chain go m1 -> m2 -> m3 -> m4 +// +// Another example: +// aHtmlAfterNosurf := tcp.NewChain(m2) +// aHtml := tcp.NewChain(m1, func(h tcp.Handler) tcp.Handler { +// csrf := nosurf.New(h) +// csrf.SetFailureHandler(aHtmlAfterNosurf.ThenFunc(csrfFail)) +// return csrf +// }).Extend(aHtmlAfterNosurf) +// // requests to aHtml hitting nosurfs success handler go m1 -> nosurf -> m2 -> target-handler +// // requests to aHtml hitting nosurfs failure handler go m1 -> nosurf -> m2 -> csrfFail +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.constructors...) +} diff --git a/pkg/tcp/chain_test.go b/pkg/tcp/chain_test.go new file mode 100644 index 000000000..3460d9d7d --- /dev/null +++ b/pkg/tcp/chain_test.go @@ -0,0 +1,176 @@ +package tcp + +import ( + "net" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type HandlerTCPFunc func(WriteCloser) + +// ServeTCP calls f(conn). +func (f HandlerTCPFunc) ServeTCP(conn WriteCloser) { + f(conn) +} + +// A constructor for middleware +// that writes its own "tag" into the Conn and does nothing else. +// Useful in checking if a chain is behaving in the right order. +func tagMiddleware(tag string) Constructor { + return func(h Handler) (Handler, error) { + return HandlerTCPFunc(func(conn WriteCloser) { + _, err := conn.Write([]byte(tag)) + if err != nil { + panic("Unexpected") + } + h.ServeTCP(conn) + }), nil + } +} + +var testApp = HandlerTCPFunc(func(conn WriteCloser) { + _, err := conn.Write([]byte("app\n")) + if err != nil { + panic("unexpected") + } +}) + +type myWriter struct { + data []byte +} + +func (mw *myWriter) Close() error { + panic("implement me") +} + +func (mw *myWriter) LocalAddr() net.Addr { + panic("implement me") +} + +func (mw *myWriter) RemoteAddr() net.Addr { + panic("implement me") +} + +func (mw *myWriter) SetDeadline(t time.Time) error { + panic("implement me") +} + +func (mw *myWriter) SetReadDeadline(t time.Time) error { + panic("implement me") +} + +func (mw *myWriter) SetWriteDeadline(t time.Time) error { + panic("implement me") +} + +func (mw *myWriter) Read(b []byte) (n int, err error) { + panic("implement me") +} + +func (mw *myWriter) Write(b []byte) (n int, err error) { + mw.data = append(mw.data, b...) + return len(mw.data), nil +} + +func (mw *myWriter) CloseWrite() error { + return nil +} + +func TestNewChain(t *testing.T) { + c1 := func(h Handler) (Handler, error) { + return nil, nil + } + + c2 := func(h Handler) (Handler, error) { + return h, nil + } + + slice := []Constructor{c1, c2} + + chain := NewChain(slice...) + for k := range slice { + assert.ObjectsAreEqual(chain.constructors[k], slice[k]) + } +} + +func TestThenWorksWithNoMiddleware(t *testing.T) { + handler, err := NewChain().Then(testApp) + require.NoError(t, err) + + assert.ObjectsAreEqual(handler, testApp) +} + +func TestThenTreatsNilAsError(t *testing.T) { + handler, err := NewChain().Then(nil) + require.Error(t, err) + assert.Nil(t, handler) +} + +func TestThenOrdersHandlersCorrectly(t *testing.T) { + t1 := tagMiddleware("t1\n") + t2 := tagMiddleware("t2\n") + t3 := tagMiddleware("t3\n") + + chained, err := NewChain(t1, t2, t3).Then(testApp) + require.NoError(t, err) + + conn := &myWriter{} + chained.ServeTCP(conn) + + assert.Equal(t, "t1\nt2\nt3\napp\n", string(conn.data)) +} + +func TestAppendAddsHandlersCorrectly(t *testing.T) { + chain := NewChain(tagMiddleware("t1\n"), tagMiddleware("t2\n")) + newChain := chain.Append(tagMiddleware("t3\n"), tagMiddleware("t4\n")) + + assert.Len(t, chain.constructors, 2) + assert.Len(t, newChain.constructors, 4) + + chained, err := newChain.Then(testApp) + require.NoError(t, err) + + conn := &myWriter{} + chained.ServeTCP(conn) + + assert.Equal(t, "t1\nt2\nt3\nt4\napp\n", string(conn.data)) +} + +func TestAppendRespectsImmutability(t *testing.T) { + chain := NewChain(tagMiddleware("")) + newChain := chain.Append(tagMiddleware("")) + + if &chain.constructors[0] == &newChain.constructors[0] { + t.Error("Apppend does not respect immutability") + } +} + +func TestExtendAddsHandlersCorrectly(t *testing.T) { + chain1 := NewChain(tagMiddleware("t1\n"), tagMiddleware("t2\n")) + chain2 := NewChain(tagMiddleware("t3\n"), tagMiddleware("t4\n")) + newChain := chain1.Extend(chain2) + + assert.Len(t, chain1.constructors, 2) + assert.Len(t, chain2.constructors, 2) + assert.Len(t, newChain.constructors, 4) + + chained, err := newChain.Then(testApp) + require.NoError(t, err) + + conn := &myWriter{} + chained.ServeTCP(conn) + + assert.Equal(t, "t1\nt2\nt3\nt4\napp\n", string(conn.data)) +} + +func TestExtendRespectsImmutability(t *testing.T) { + chain := NewChain(tagMiddleware("")) + newChain := chain.Extend(NewChain(tagMiddleware(""))) + + if &chain.constructors[0] == &newChain.constructors[0] { + t.Error("Extend does not respect immutability") + } +} diff --git a/webui/src/_mixins/GetTableProps.js b/webui/src/_mixins/GetTableProps.js index dc9a39209..014a397bb 100644 --- a/webui/src/_mixins/GetTableProps.js +++ b/webui/src/_mixins/GetTableProps.js @@ -126,6 +126,9 @@ const propsByType = { }, 'http-middlewares': { columns: columnsByResource.middlewares + }, + 'tcp-middlewares': { + columns: columnsByResource.middlewares } } diff --git a/webui/src/_services/TcpService.js b/webui/src/_services/TcpService.js index 3ca965e24..e5645e9b1 100644 --- a/webui/src/_services/TcpService.js +++ b/webui/src/_services/TcpService.js @@ -39,9 +39,29 @@ function getServiceByName (name) { }) } +function getAllMiddlewares (params) { + return APP.api.get(`${apiBase}/middlewares?search=${params.query}&status=${params.status}&per_page=${params.limit}&page=${params.page}`) + .then(response => { + const { data = [], headers } = response + const total = getTotal(headers, params) + console.log('Success -> TcpService -> getAllMiddlewares', response.data) + return { data, total } + }) +} + +function getMiddlewareByName (name) { + return APP.api.get(`${apiBase}/middlewares/${name}`) + .then(body => { + console.log('Success -> TcpService -> getMiddlewareByName', body.data) + return body.data + }) +} + export default { getAllRouters, getRouterByName, getAllServices, - getServiceByName + getServiceByName, + getAllMiddlewares, + getMiddlewareByName } diff --git a/webui/src/components/_commons/MainTable.vue b/webui/src/components/_commons/MainTable.vue index d84b9bfbb..85ae32e55 100644 --- a/webui/src/components/_commons/MainTable.vue +++ b/webui/src/components/_commons/MainTable.vue @@ -12,7 +12,7 @@ - + No data available diff --git a/webui/src/components/_commons/PanelMiddlewares.vue b/webui/src/components/_commons/PanelMiddlewares.vue index 35b526335..63714ff29 100644 --- a/webui/src/components/_commons/PanelMiddlewares.vue +++ b/webui/src/components/_commons/PanelMiddlewares.vue @@ -38,1029 +38,1049 @@ - - -
-
-
ERRORS
- - {{ errorMsg }} - -
-
-
- - -
-
-
PREFIX
- - {{ exData(middleware).prefix }} - -
-
-
- - - -
-
-
USERS
- - {{ user }} - -
-
-
- - -
-
-
Users File
- - {{ exData(middleware).usersFile }} - -
-
-
- - -
-
-
Realm
- - {{ exData(middleware).realm }} - -
-
-
- - -
-
-
Remove Header
- -
-
-
- - -
-
-
Header Field
- - {{ exData(middleware).headerField }} - -
-
-
- - - -
-
-
Chain
- - {{ mi }} - -
-
-
- - - -
-
-
Max Request Body Bytes
- - {{ exData(middleware).maxRequestBodyBytes }} - -
-
-
Mem Request Body Bytes
- - {{ exData(middleware).memRequestBodyBytes }} - -
-
-
- - -
-
-
Max Response Body Bytes
- - {{ exData(middleware).maxResponseBodyBytes }} - -
-
-
Mem Response Body Bytes
- - {{ exData(middleware).memResponseBodyBytes }} - -
-
-
- - -
-
-
Retry Expression
- - {{ exData(middleware).retryExpression }} - -
-
-
- - - -
-
-
Expression
- - {{ exData(middleware).expression }} - -
-
-
- - - -
-
-
Compress
- -
-
-
- - - -
-
-
Service
- - {{ exData(middleware).service }} - {{ exData(middleware).service }} - -
-
-
- - -
-
-
Query
- - {{ exData(middleware).query }} - -
-
-
- - -
-
-
Status
- - {{ st }} - -
-
-
- - - -
-
-
Address
- - {{ exData(middleware).address }} - -
-
-
- - -
-
-
TLS
- -
-
-
Trust Forward Headers
- -
-
-
- - -
-
-
Auth Response Headers
- - {{ respHeader }} - -
-
-
- - -
-
-
Auth Request Headers
- - {{ reqHeader }} - -
-
-
- - - -
-
-
Custom Request Headers
- - {{ key }}: {{ val }} - -
-
-
- - -
-
-
Custom Response Headers
- - {{ key }}: {{ val }} - -
-
-
- - -
-
-
Access Control Allow Credentials
- -
-
-
- - -
-
-
Access Control Allow Headers
- - {{ val }} - -
-
-
- - -
-
-
Access Control Allow Methods
- - {{ val }} - -
-
-
- - -
-
-
Access Control Allow Origin
- - {{ val }} - -
-
-
- - -
-
-
Access Control Expose Headers
- - {{ val }} - -
-
-
- - -
-
-
Access Control Max Age
- - {{ exData(middleware).accessControlMaxAge }} - -
-
-
- - -
-
-
Add Vary Header
- -
-
-
- - -
-
-
Allowed Hosts
- - {{ val }} - -
-
-
- - -
-
-
Hosts Proxy Headers
- - {{ val }} - -
-
-
- - -
-
-
SSL Redirect
- -
-
-
- - -
-
-
SSL Temporary Redirect
- -
-
-
- - -
-
-
SSL Host
- - {{ exData(middleware).sslHost }} - -
-
-
- - -
-
-
SSL Proxy Headers
- - {{ val }} - -
-
-
- - -
-
-
SSL Force Host
- -
-
-
- - -
-
-
STS Seconds
- - {{ exData(middleware).stsSeconds }} - -
-
-
- - -
-
-
STS Include Subdomains
- -
-
-
- - -
-
-
STS Preload
- -
-
-
- - -
-
-
Force STS Header
- -
-
-
- - -
-
-
Frame Deny
- -
-
-
- - -
-
-
Custom Frame Options Value
- - {{ exData(middleware).customFrameOptionsValue }} - -
-
-
- - -
-
-
Content Type Nosniff
- -
-
-
- - -
-
-
Browser XSS Filter
- -
-
-
- - -
-
-
Custom Browser XSS Value
- - {{ exData(middleware).customBrowserXSSValue }} - -
-
-
- - -
-
-
Content Security Policy
- - {{ exData(middleware).contentSecurityPolicy }} - -
-
-
- - -
-
-
Public Key
- - {{ exData(middleware).publicKey }} - -
-
-
- - -
-
-
Referrer Policy
- - {{ exData(middleware).referrerPolicy }} - -
-
-
- - -
-
-
Feature Policy
- - {{ exData(middleware).featurePolicy }} - -
-
-
- - -
-
-
Is Development
- -
-
-
- - - -
-
-
Source Range
- - {{ range }} - -
-
-
- - -
-
-
IP Strategy
-
-
- Depth : - - {{ exData(middleware).ipStrategy.depth }} - -
-
-
+ + + +
+
+
ERRORS
- Excluded IPs: - - - {{ excludedIPs }} + v-for="(errorMsg, index) in middleware.error" :key="index" + class="app-chip app-chip-error"> + {{ errorMsg }}
-
- + - - -
-
-
Average
- - {{ exData(middleware).average }} - -
-
-
Burst
- - {{ exData(middleware).burst }} - -
-
-
- - - -
-
-
AMOUNT
- - {{ exData(middleware).amount }} - -
-
-
- - - -
-
-
IP STRATEGY
-
-
- Depth : - - {{ exData(middleware).sourceCriterion.ipStrategy.depth }} - -
-
-
+ + +
+
+
PREFIX
- Excluded IPs: - - - {{ excludedIPs }} + {{ exData(middleware).prefix }}
-
- - - -
-
-
REQUEST HEADER NAME
- - {{ exData(middleware).sourceCriterion.requestHeaderName }} - + + + + +
+
+
USERS
+ + {{ user }} + +
-
-
REQUEST HOST
- + + + +
+
+
Users File
+ + {{ exData(middleware).usersFile }} + +
-
+
+ + +
+
+
Realm
+ + {{ exData(middleware).realm }} + +
+
+
+ + +
+
+
Remove Header
+ +
+
+
+ + +
+
+
Header Field
+ + {{ exData(middleware).headerField }} + +
+
+
+ + + +
+
+
Chain
+ + {{ mi }} + +
+
+
+ + + +
+
+
Max Request Body Bytes
+ + {{ exData(middleware).maxRequestBodyBytes }} + +
+
+
Mem Request Body Bytes
+ + {{ exData(middleware).memRequestBodyBytes }} + +
+
+
+ + +
+
+
Max Response Body Bytes
+ + {{ exData(middleware).maxResponseBodyBytes }} + +
+
+
Mem Response Body Bytes
+ + {{ exData(middleware).memResponseBodyBytes }} + +
+
+
+ + +
+
+
Retry Expression
+ + {{ exData(middleware).retryExpression }} + +
+
+
+ + + +
+
+
Expression
+ + {{ exData(middleware).expression }} + +
+
+
+ + + +
+
+
Compress
+ +
+
+
+ + + +
+
+
Service
+ + {{ exData(middleware).service }} + {{ exData(middleware).service }} + +
+
+
+ + +
+
+
Query
+ + {{ exData(middleware).query }} + +
+
+
+ + +
+
+
Status
+ + {{ st }} + +
+
+
+ + + +
+
+
Address
+ + {{ exData(middleware).address }} + +
+
+
+ + +
+
+
TLS
+ +
+
+
Trust Forward Headers
+ +
+
+
+ + +
+
+
Auth Response Headers
+ + {{ respHeader }} + +
+
+
+ + +
+
+
Auth Request Headers
+ + {{ reqHeader }} + +
+
+
+ + + +
+
+
Custom Request Headers
+ + {{ key }}: {{ val }} + +
+
+
+ + +
+
+
Custom Response Headers
+ + {{ key }}: {{ val }} + +
+
+
+ + +
+
+
Access Control Allow Credentials
+ +
+
+
+ + +
+
+
Access Control Allow Headers
+ + {{ val }} + +
+
+
+ + +
+
+
Access Control Allow Methods
+ + {{ val }} + +
+
+
+ + +
+
+
Access Control Allow Origin
+ + {{ val }} + +
+
+
+ + +
+
+
Access Control Expose Headers
+ + {{ val }} + +
+
+
+ + +
+
+
Access Control Max Age
+ + {{ exData(middleware).accessControlMaxAge }} + +
+
+
+ + +
+
+
Add Vary Header
+ +
+
+
+ + +
+
+
Allowed Hosts
+ + {{ val }} + +
+
+
+ + +
+
+
Hosts Proxy Headers
+ + {{ val }} + +
+
+
+ + +
+
+
SSL Redirect
+ +
+
+
+ + +
+
+
SSL Temporary Redirect
+ +
+
+
+ + +
+
+
SSL Host
+ + {{ exData(middleware).sslHost }} + +
+
+
+ + +
+
+
SSL Proxy Headers
+ + {{ val }} + +
+
+
+ + +
+
+
SSL Force Host
+ +
+
+
+ + +
+
+
STS Seconds
+ + {{ exData(middleware).stsSeconds }} + +
+
+
+ + +
+
+
STS Include Subdomains
+ +
+
+
+ + +
+
+
STS Preload
+ +
+
+
+ + +
+
+
Force STS Header
+ +
+
+
+ + +
+
+
Frame Deny
+ +
+
+
+ + +
+
+
Custom Frame Options Value
+ + {{ exData(middleware).customFrameOptionsValue }} + +
+
+
+ + +
+
+
Content Type Nosniff
+ +
+
+
+ + +
+
+
Browser XSS Filter
+ +
+
+
+ + +
+
+
Custom Browser XSS Value
+ + {{ exData(middleware).customBrowserXSSValue }} + +
+
+
+ + +
+
+
Content Security Policy
+ + {{ exData(middleware).contentSecurityPolicy }} + +
+
+
+ + +
+
+
Public Key
+ + {{ exData(middleware).publicKey }} + +
+
+
+ + +
+
+
Referrer Policy
+ + {{ exData(middleware).referrerPolicy }} + +
+
+
+ + +
+
+
Feature Policy
+ + {{ exData(middleware).featurePolicy }} + +
+
+
+ + +
+
+
Is Development
+ +
+
+
+ + + +
+
+
Source Range
+ + {{ range }} + +
+
+
+ + +
+
+
IP Strategy
+
+
+ Depth : + + {{ exData(middleware).ipStrategy.depth }} + +
+
+
+ + Excluded IPs: + + + {{ excludedIPs }} + +
+
+
+
+ + + +
+
+
Average
+ + {{ exData(middleware).average }} + +
+
+
Burst
+ + {{ exData(middleware).burst }} + +
+
+
+ + + +
+
+
AMOUNT
+ + {{ exData(middleware).amount }} + +
+
+
+ + + +
+
+
IP STRATEGY
+
+
+ Depth : + + {{ exData(middleware).sourceCriterion.ipStrategy.depth }} + +
+
+
+ + Excluded IPs: + + + {{ excludedIPs }} + +
+
+
+
+ + +
+
+
REQUEST HEADER NAME
+ + {{ exData(middleware).sourceCriterion.requestHeaderName }} + +
+
+
REQUEST HOST
+ +
+
+
+ + + +
+
+
PEM
+ +
+
+
+ + +
Info:
+
+
+
Not After
+ +
+
+
Not Before
+ +
+
+
Sans
+ +
+
+
+ + +
Info Subject:
+
+
+
country
+ +
+
+
Province
+ +
+
+
+ +
+
+
Locality
+ +
+
+
Organization
+ +
+
+
+ +
+
+
Common Name
+ +
+
+
Serial Number
+ +
+
+
+ +
+
+
Domain Component
+ +
+
+
+ + +
Info Issuer:
+
+
+
country
+ +
+
+
Province
+ +
+
+
+ +
+
+
Locality
+ +
+
+
Organization
+ +
+
+
+ +
+
+
Common Name
+ +
+
+
Serial Number
+ +
+
+
+ +
+
+
Domain Component
+ +
+
+
+ + + +
+
+
Regex
+ + {{ exData(middleware).regex }} + +
+
+
+ + +
+
+
Replacement
+ + {{ exData(middleware).replacement }} + +
+
+
+ + +
+
+
Permanent
+ +
+
+
+ + + +
+
+
Scheme
+ + {{ exData(middleware).scheme }} + +
+
+
+ + + +
+
+
Path
+ + {{ exData(middleware).path }} + +
+
+
+ + + +
+
+
Regex
+ + {{ exData(middleware).regex }} + +
+
+
+ + +
+
+
Replacement
+ + {{ exData(middleware).replacement }} + +
+
+
+ + + +
+
+
Attempts
+ + {{ exData(middleware).attempts }} + +
+
+
+ + + +
+
+
Prefixes
+ + {{ prefix }} + +
+
+
+ + + +
+
+
Regex
+ + {{ exp }} + +
+
+
- - -
-
-
PEM
- + + + +
+
+
Source Range
+ + {{ range }} + +
-
- - - -
Info:
-
-
-
Not After
- -
-
-
Not Before
- -
-
-
Sans
- -
-
-
- - -
Info Subject:
-
-
-
country
- -
-
-
Province
- -
-
-
- -
-
-
Locality
- -
-
-
Organization
- -
-
-
- -
-
-
Common Name
- -
-
-
Serial Number
- -
-
-
- -
-
-
Domain Component
- -
-
-
- - -
Info Issuer:
-
-
-
country
- -
-
-
Province
- -
-
-
- -
-
-
Locality
- -
-
-
Organization
- -
-
-
- -
-
-
Common Name
- -
-
-
Serial Number
- -
-
-
- -
-
-
Domain Component
- -
-
-
- - - -
-
-
Regex
- - {{ exData(middleware).regex }} - -
-
-
- - -
-
-
Replacement
- - {{ exData(middleware).replacement }} - -
-
-
- - -
-
-
Permanent
- -
-
-
- - - -
-
-
Scheme
- - {{ exData(middleware).scheme }} - -
-
-
- - - -
-
-
Path
- - {{ exData(middleware).path }} - -
-
-
- - - -
-
-
Regex
- - {{ exData(middleware).regex }} - -
-
-
- - -
-
-
Replacement
- - {{ exData(middleware).replacement }} - -
-
-
- - - -
-
-
Attempts
- - {{ exData(middleware).attempts }} - -
-
-
- - - -
-
-
Prefixes
- - {{ prefix }} - -
-
-
- - - -
-
-
Regex
- - {{ exp }} - -
-
+
@@ -1093,6 +1113,9 @@ export default { BooleanState }, computed: { + protocol () { + return this.$route.meta.protocol + }, isDense () { return this.dense !== undefined } diff --git a/webui/src/components/_commons/PanelTLS.vue b/webui/src/components/_commons/PanelTLS.vue index eb25e0985..8987d0a15 100644 --- a/webui/src/components/_commons/PanelTLS.vue +++ b/webui/src/components/_commons/PanelTLS.vue @@ -21,7 +21,7 @@
- +
PASSTHROUGH
diff --git a/webui/src/components/_commons/ToolBar.vue b/webui/src/components/_commons/ToolBar.vue index b508d09c2..58c130a97 100644 --- a/webui/src/components/_commons/ToolBar.vue +++ b/webui/src/components/_commons/ToolBar.vue @@ -7,7 +7,7 @@ - + diff --git a/webui/src/pages/_commons/MiddlewareDetail.vue b/webui/src/pages/_commons/MiddlewareDetail.vue index 8b4c19942..51a42fd5c 100644 --- a/webui/src/pages/_commons/MiddlewareDetail.vue +++ b/webui/src/pages/_commons/MiddlewareDetail.vue @@ -96,6 +96,7 @@ export default { }, computed: { ...mapGetters('http', { http_middlewareByName: 'middlewareByName' }), + ...mapGetters('tcp', { tcp_middlewareByName: 'middlewareByName' }), protocol () { return this.$route.meta.protocol }, @@ -111,6 +112,7 @@ export default { }, methods: { ...mapActions('http', { http_getMiddlewareByName: 'getMiddlewareByName', http_getRouterByName: 'getRouterByName' }), + ...mapActions('tcp', { tcp_getMiddlewareByName: 'getMiddlewareByName', tcp_getRouterByName: 'getRouterByName' }), refreshAll () { if (this.middlewareByName.loading) { return @@ -160,6 +162,7 @@ export default { beforeDestroy () { clearInterval(this.timeOutGetAll) this.$store.commit('http/getMiddlewareByNameClear') + this.$store.commit('tcp/getMiddlewareByNameClear') } } diff --git a/webui/src/pages/_commons/RouterDetail.vue b/webui/src/pages/_commons/RouterDetail.vue index 2aa29492c..2e95d0d18 100644 --- a/webui/src/pages/_commons/RouterDetail.vue +++ b/webui/src/pages/_commons/RouterDetail.vue @@ -125,7 +125,7 @@
-
+
Middlewares
@@ -194,7 +194,7 @@ export default { ...mapGetters('tcp', { tcp_routerByName: 'routerByName' }), ...mapGetters('udp', { udp_routerByName: 'routerByName' }), hasMiddlewares () { - return this.$route.meta.protocol === 'http' && this.middlewares.length > 0 + return this.$route.meta.protocol !== 'udp' && this.middlewares.length > 0 }, protocol () { return this.$route.meta.protocol @@ -204,11 +204,14 @@ export default { }, getRouterByName () { return this[`${this.protocol}_getRouterByName`] + }, + getMiddlewareByName () { + return this[`${this.protocol}_getMiddlewareByName`] } }, methods: { - ...mapActions('http', { http_getRouterByName: 'getRouterByName', getMiddlewareByName: 'getMiddlewareByName' }), - ...mapActions('tcp', { tcp_getRouterByName: 'getRouterByName' }), + ...mapActions('http', { http_getRouterByName: 'getRouterByName', http_getMiddlewareByName: 'getMiddlewareByName' }), + ...mapActions('tcp', { tcp_getRouterByName: 'getRouterByName', tcp_getMiddlewareByName: 'getMiddlewareByName' }), ...mapActions('udp', { udp_getRouterByName: 'getRouterByName' }), ...mapActions('entrypoints', { getEntrypointsByName: 'getByName' }), refreshAll () { diff --git a/webui/src/pages/tcp/Middlewares.vue b/webui/src/pages/tcp/Middlewares.vue new file mode 100644 index 000000000..735341134 --- /dev/null +++ b/webui/src/pages/tcp/Middlewares.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/webui/src/pages/tcp/Routers.vue b/webui/src/pages/tcp/Routers.vue index 897d5bf32..2702c8110 100644 --- a/webui/src/pages/tcp/Routers.vue +++ b/webui/src/pages/tcp/Routers.vue @@ -85,7 +85,7 @@ export default { } }, beforeDestroy () { - this.$store.commit('http/getAllRoutersClear') + this.$store.commit('tcp/getAllRoutersClear') } } diff --git a/webui/src/pages/tcp/Services.vue b/webui/src/pages/tcp/Services.vue index e904f5e2e..99492e2db 100644 --- a/webui/src/pages/tcp/Services.vue +++ b/webui/src/pages/tcp/Services.vue @@ -85,7 +85,7 @@ export default { } }, beforeDestroy () { - this.$store.commit('http/getAllServicesClear') + this.$store.commit('tcp/getAllServicesClear') } } diff --git a/webui/src/pages/udp/Routers.vue b/webui/src/pages/udp/Routers.vue index c46900430..e73826fa1 100644 --- a/webui/src/pages/udp/Routers.vue +++ b/webui/src/pages/udp/Routers.vue @@ -84,7 +84,7 @@ export default { } }, beforeDestroy () { - this.$store.commit('http/getAllRoutersClear') + this.$store.commit('udp/getAllRoutersClear') } } diff --git a/webui/src/pages/udp/Services.vue b/webui/src/pages/udp/Services.vue index 988ace32b..3f6229607 100644 --- a/webui/src/pages/udp/Services.vue +++ b/webui/src/pages/udp/Services.vue @@ -85,7 +85,7 @@ export default { } }, beforeDestroy () { - this.$store.commit('http/getAllServicesClear') + this.$store.commit('udp/getAllServicesClear') } } diff --git a/webui/src/router/routes.js b/webui/src/router/routes.js index 53565cf9d..943cad526 100644 --- a/webui/src/router/routes.js +++ b/webui/src/router/routes.js @@ -156,6 +156,32 @@ const routes = [ protocol: 'tcp', title: 'TCP Service Detail' } + }, + { + path: 'middlewares', + name: 'tcpMiddlewares', + components: { + default: () => import('pages/tcp/Middlewares.vue'), + NavBar: () => import('components/_commons/ToolBar.vue') + }, + props: { default: true, NavBar: true }, + meta: { + protocol: 'tcp', + title: 'TCP Middlewares' + } + }, + { + path: 'middlewares/:name', + name: 'tcpMiddlewareDetail', + components: { + default: () => import('pages/_commons/MiddlewareDetail.vue'), + NavBar: () => import('components/_commons/ToolBar.vue') + }, + props: { default: true, NavBar: true }, + meta: { + protocol: 'tcp', + title: 'TCP Middleware Detail' + } } ] }, diff --git a/webui/src/store/tcp/actions.js b/webui/src/store/tcp/actions.js index d6638bad5..f728c6d5b 100644 --- a/webui/src/store/tcp/actions.js +++ b/webui/src/store/tcp/actions.js @@ -51,3 +51,29 @@ export function getServiceByName ({ commit }, name) { return Promise.reject(error) }) } + +export function getAllMiddlewares ({ commit }, params) { + commit('getAllMiddlewaresRequest') + return TcpService.getAllMiddlewares(params) + .then(body => { + commit('getAllMiddlewaresSuccess', { body, ...params }) + return body + }) + .catch(error => { + commit('getAllMiddlewaresFailure', error) + return Promise.reject(error) + }) +} + +export function getMiddlewareByName ({ commit }, name) { + commit('getMiddlewareByNameRequest') + return TcpService.getMiddlewareByName(name) + .then(body => { + commit('getMiddlewareByNameSuccess', body) + return body + }) + .catch(error => { + commit('getMiddlewareByNameFailure', error) + return Promise.reject(error) + }) +} diff --git a/webui/src/store/tcp/getters.js b/webui/src/store/tcp/getters.js index 2b9611e94..2f822b452 100644 --- a/webui/src/store/tcp/getters.js +++ b/webui/src/store/tcp/getters.js @@ -25,3 +25,17 @@ export function allServices (state) { export function serviceByName (state) { return state.serviceByName } + +// ---------------------------- +// all Middlewares +// ---------------------------- +export function allMiddlewares (state) { + return state.allMiddlewares +} + +// ---------------------------- +// Middleware by Name +// ---------------------------- +export function middlewareByName (state) { + return state.middlewareByName +} diff --git a/webui/src/store/tcp/mutations.js b/webui/src/store/tcp/mutations.js index 69df42013..da98bd00d 100644 --- a/webui/src/store/tcp/mutations.js +++ b/webui/src/store/tcp/mutations.js @@ -103,3 +103,55 @@ export function getServiceByNameFailure (state, error) { export function getServiceByNameClear (state) { state.serviceByName = {} } + +// ---------------------------- +// Get All Middlewares +// ---------------------------- +export function getAllMiddlewaresRequest (state) { + withPagination('request', { statePath: 'allMiddlewares' })(state) +} + +export function getAllMiddlewaresSuccess (state, data) { + const { query = '', status = '' } = data + const currentState = state.allMiddlewares + + const isSameContext = currentState.currentQuery === query && currentState.currentStatus === status + + state.allMiddlewares = { + ...state.allMiddlewares, + currentQuery: query, + currentStatus: status + } + + withPagination('success', { + isSameContext, + statePath: 'allMiddlewares' + })(state, data) +} + +export function getAllMiddlewaresFailure (state, error) { + withPagination('failure', { statePath: 'allMiddlewares' })(state, error) +} + +export function getAllMiddlewaresClear (state) { + state.allMiddlewares = {} +} + +// ---------------------------- +// Get Middleware By Name +// ---------------------------- +export function getMiddlewareByNameRequest (state) { + state.middlewareByName.loading = true +} + +export function getMiddlewareByNameSuccess (state, body) { + state.middlewareByName = { item: body, loading: false } +} + +export function getMiddlewareByNameFailure (state, error) { + state.middlewareByName = { error } +} + +export function getMiddlewareByNameClear (state) { + state.middlewareByName = {} +} diff --git a/webui/src/store/tcp/mutations.spec.js b/webui/src/store/tcp/mutations.spec.js index cd955b806..d9f0555cb 100644 --- a/webui/src/store/tcp/mutations.spec.js +++ b/webui/src/store/tcp/mutations.spec.js @@ -7,7 +7,10 @@ const { getAllRoutersFailure, getAllServicesRequest, getAllServicesSuccess, - getAllServicesFailure + getAllServicesFailure, + getAllMiddlewaresRequest, + getAllMiddlewaresSuccess, + getAllMiddlewaresFailure } = store.mutations describe('tcp mutations', function () { @@ -194,4 +197,96 @@ describe('tcp mutations', function () { expect(state.allServices.items.length).to.equal(3) }) }) + + /* Middlewares */ + describe('tcp middlewares mutations', function () { + it('getAllMiddlewaresRequest', function () { + const state = { + allMiddlewares: { + items: [{}, {}, {}] + } + } + + getAllMiddlewaresRequest(state) + + expect(state.allMiddlewares.loading).to.equal(true) + expect(state.allMiddlewares.items.length).to.equal(3) + }) + + it('getAllMiddlewaresSuccess page 1', function () { + const state = { + allMiddlewares: { + loading: true + } + } + + const data = { + body: { + data: [{}, {}, {}], + total: 3 + }, + query: 'test query', + status: 'warning', + page: 1 + } + + getAllMiddlewaresSuccess(state, data) + + expect(state.allMiddlewares.loading).to.equal(false) + expect(state.allMiddlewares.total).to.equal(3) + expect(state.allMiddlewares.items.length).to.equal(3) + expect(state.allMiddlewares.currentPage).to.equal(1) + expect(state.allMiddlewares.currentQuery).to.equal('test query') + expect(state.allMiddlewares.currentStatus).to.equal('warning') + }) + + it('getAllMiddlewaresSuccess page 2', function () { + const state = { + allMiddlewares: { + loading: false, + items: [{ id: 1 }, { id: 2 }, { id: 3 }], + total: 3, + currentPage: 1, + currentQuery: 'test query', + currentStatus: 'warning' + } + } + + const data = { + body: { + data: [{ id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }], + total: 4 + }, + query: 'test query', + status: 'warning', + page: 2 + } + + getAllMiddlewaresSuccess(state, data) + + expect(state.allMiddlewares.loading).to.equal(false) + expect(state.allMiddlewares.total).to.equal(7) + expect(state.allMiddlewares.items.length).to.equal(7) + expect(state.allMiddlewares.currentPage).to.equal(2) + expect(state.allMiddlewares.currentQuery).to.equal('test query') + expect(state.allMiddlewares.currentStatus).to.equal('warning') + }) + + it('getAllMiddlewaresFailing', function () { + const state = { + allMiddlewares: { + items: [{}, {}, {}], + loading: true + } + } + + const error = { message: 'invalid request: page: 3, per_page: 10' } + + getAllMiddlewaresFailure(state, error) + + expect(state.allMiddlewares.loading).to.equal(false) + expect(state.allMiddlewares.endReached).to.equal(true) + expect(state.allMiddlewares.items.length).to.equal(3) + }) + }) }) diff --git a/webui/src/store/tcp/state.js b/webui/src/store/tcp/state.js index 0eb429a34..0557a4fdd 100644 --- a/webui/src/store/tcp/state.js +++ b/webui/src/store/tcp/state.js @@ -2,5 +2,7 @@ export default { allRouters: {}, routerByName: {}, allServices: {}, - serviceByName: {} + serviceByName: {}, + allMiddlewares: {}, + middlewareByName: {} }