envoyproxy / ratelimit

Go/gRPC service designed to enable generic rate limit scenarios from different types of applications.
Apache License 2.0
2.21k stars 428 forks source link

Add TLS support to memcache #594

Closed isker closed 1 month ago

isker commented 1 month ago

Memcache supports TLS connections for client-server communication. Add support for configuring a TLS connection to memcached using TLS in a way that mirrors the existing redis configuration options.

Also, ensure that configuration options that apply to the "normal" enumeration of host:port pairs also apply to the DNS SRV discovery mechanism. I don't see a reason why they should not.

isker commented 1 month ago

Testing was all done manually. I don't see any memcache setup for the existing integration tests and I'm not keen on adding one 😬.

Testing steps:

  1. Generate cert:
    mkdir certs
    cd certs
    openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
          -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=localhost" \
          -addext "subjectAltName = DNS:localhost" \
          -keyout key.pem -out cert.pem
  2. Patch docker-compose.yml:

    
    diff --git a/docker-compose.yml b/docker-compose.yml
    index 6f1b9f0..95d05cb 100644
    --- a/docker-compose.yml
    +++ b/docker-compose.yml
    @@ -17,6 +17,9 @@ services:
       - 11211:11211
     networks:
       - ratelimit-network
    +    volumes:
    +      - ./certs:/etc/certs
    +    command: '-Z -o ssl_chain_cert=/etc/certs/cert.pem,ssl_key=/etc/certs/key.pem'
    
    # minimal container that builds the ratelimit service binary and exits.
    ratelimit-build:
    @@ -45,12 +48,14 @@ services:
       - 6070:6070
     depends_on:
       - redis
    +      - memcached
       - ratelimit-build
       - ratelimit-client-build
     networks:
       - ratelimit-network
     volumes:
       - binary:/usr/local/bin/
    +      - ./certs:/etc/certs/
       - ./examples:/data
     environment:
       - USE_STATSD=false
    @@ -60,6 +65,32 @@ services:
       - RUNTIME_ROOT=/data
       - RUNTIME_SUBDIRECTORY=ratelimit
       - MEMCACHE_HOST_PORT=memcached:11211
    +      - CONFIG_TYPE=FILE
    +      - BACKEND_TYPE=memcache
    +      - MEMCACHE_TLS=true
    +      - MEMCACHE_TLS_CACERT=/etc/certs/cert.pem
    +      - MEMCACHE_TLS_SKIP_HOSTNAME_VERIFICATION=true
    +
    +  envoy-proxy:
    +    image: envoyproxy/envoy-dev:latest
    +    entrypoint: "/usr/local/bin/envoy"
    +    command:
    +      - "--service-node proxy"
    +      - "--service-cluster proxy"
    +      - "--config-path /etc/envoy/envoy.yaml"
    +      - "--concurrency 1"
    +      - "--mode serve"
    +      - "--log-level info"
    +    volumes:
    +      - ./examples/envoy/proxy.yaml:/etc/envoy/envoy.yaml
    +    networks:
    +      - ratelimit-network
    +    expose:
    +      - "8888"
    +      - "8001"
    +    ports:
    +      - "8888:8888"
    +      - "8001:8001"
    
    networks:
    ratelimit-network:
3. Play traffic:
```sh
λ xh localhost:8888/twoheader
HTTP/1.1 503 Service Unavailable
Content-Length: 19
Content-Type: text/plain
Date: Sat, 25 May 2024 23:15:39 GMT
Server: envoy

no healthy upstream

λ xh localhost:8888/twoheader "foo: foo" "bar: banned" # Ban a particular header value
HTTP/1.1 429 Too Many Requests
Content-Length: 0
Date: Sat, 25 May 2024 23:15:41 GMT
Server: envoy
X-Envoy-Ratelimited: true
X-Ratelimit-Limit: 0, 0;w=60
X-Ratelimit-Remaining: 0
X-Ratelimit-Reset: 18
  1. Observe logs. No errors, and memcache stats are on stdout:
    
    ratelimit-1               | {"level":"debug","ts":1716679429.354725,"logger":"gostats.loggingsink","msg":"flushing counter","json":{"name":"ratelimit.memcache.multiget.__code=success","type":"counter","value":
    ratelimit-1               | {"level":"debug","ts":1716679429.354772,"logger":"gostats.loggingsink","msg":"flushing counter","json":{"name":"ratelimit.memcache.increment.__code=miss","type":"counter","value":"1
    ratelimit-1               | {"level":"debug","ts":1716679429.354772,"logger":"gostats.loggingsink","msg":"flushing counter","json":{"name":"ratelimit.memcache.increment.__code=miss","type":"counter","value":"1
    ratelimit-1               | {"level":"debug","ts":1716679429.354848,"logger":"gostats.loggingsink","msg":"flushing counter","json":{"name":"ratelimit.memcache.add.__code=success","type":"counter","value":"1.00
isker commented 1 month ago

Sorry @mattklein123, I think it's fixed now, please go again.

I struggle to run make precommit_install because I'm using nix, so I just tried (and failed) to eyeball everything 🙃.

isker commented 1 month ago

Thanks for taking a look at the repo!