hashicorp / consul

Consul is a distributed, highly available, and data center aware solution to connect and configure applications across dynamic, distributed infrastructure.
https://www.consul.io
Other
28.27k stars 4.41k forks source link

Change intention to deny doesn't take effect using native client #5277

Open jorgemarey opened 5 years ago

jorgemarey commented 5 years ago

Overview of the Issue

When using a native client (I'm ussing Go in this case) if I change a intention from allow to deny I keep having access to the service (ussing consul connect proxy). I have to restart the connect proxy for it to take effect. Going from deny to allow works fine. Using a connect proxy as client works fine too.

I'm using a HTTP connection from the Go client using the following transport

var svc *connect.Service
....
tr := &http.Transport{
    // TODO: timeouts
    DialTLS: svc.HTTPDialTLS, 
}
// when a we use a native golang client we must not enable http2
// see: https://github.com/hashicorp/consul/issues/4466
// http2.ConfigureTransport(tr)

Reproduction Steps

1) consul agent -dev -config-dir=/tmp/consul 2) register a service (HTTP server) 3) launch proxy: consul connect proxy -service -service-addr=127.0.0.1:8000 -listen ":21000" -register -log-level=DEBUG 4) use a native Go client to access the service through connect. 5) create an intention to deny access

Consul info for both Client and Server

Consul v1.4.0

mkeeler commented 5 years ago

@jorgemarey It sounds like you have a long-lived connections. In the proxy the intentions get validated only when the initial TLS connection is made. On the client side of things the intentions are validated when you first make the connection.

So there are two issues here:

  1. Our docs don't call this out like they should. There is a limitations section that mentions this for the Envoy proxy integration but there is nothing with the native client and builtin proxy.

  2. Both the proxy and native client need a way to do periodic rechecking of the intentions.

jorgemarey commented 5 years ago

Hi @mkeeler The thing is that I'm making single HTTP requests, my client is just working as a reverse proxy. Shouldn't the server (in this case the connect proxy receiving the connection) check if certificate is valid on each request?

The code that I have is the next one (simplified):

func (p *proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    var svc *connect.Service
    target, _ := url.Parse("https://my-service.service.consul/version")

    // configure the proxy and serve the request
    rp := httputil.NewSingleHostReverseProxy(target)
    rp.Transport = &http.Transport{
        DialTLS: svc.HTTPDialTLS, 
    }
    rp.ServeHTTP(w, r)
}

Then I'm making request to the listener that I'm launching with this Handler. I launched a "while curl" hopping that when I set to deny the intention it will stop responding, but that doesn't happen, instead if I do the same using the connect proxy as a client it works as expected (the while curl starts failing at the moment the intention is changed to deny.

Maybe I'm missing something...

Thanks!

waeljammal commented 3 years ago

I'm having this issue with connect native and GRPC as well, it works only after a service restart. Is there a way to work around this?