awslabs/aws-sigv4-proxy

Proxy host override is not respected correctly and mixed with the signing host override

Opened this issue · 0 comments

Scenario

Having a private AWS API Gateway
with IAM auth
and associated with a VPC
and accessible via a VPCE endpoint
and exposed via Cloudflare through Argo Tunnel running in the same VPC (which forwards the external requests).

Problem

Using the signing proxy will set the Host header incorrectly to the signing host override instead of the host override.
See steps to reproduce below.

# 1. Build image
docker build -t aws-sigv4-proxy:latest .

# 2. Run container as
docker run --rm -ti \
     -v ~/.aws:/root/.aws \
     --network=bridge \
     -p 8080:8080 \
     -e "AWS_SDK_LOAD_CONFIG=true" \
     -e "AWS_PROFILE=my-sso-profile" \
     aws-sigv4-proxy:latest \
             --verbose \
             --log-failed-requests \
             --log-signing-process \
             --name execute-api \
             --region eu-west-1 \
             --host external.cloudflare-domain.com \
             --sign-host abcd123-vpce-abcd1234cbcdef0987.execute-api.eu-west-1.amazonaws.com

# 3. Invoke the proxy to sign the request and forward
curl -v -d '{"data":"something"}' http://localhost:8080/stage/endpoint

# 4. Proxy request (OBSERVE: Host is the signing host)
proxying request    request="POST /stage/endpoint HTTP/1.1\r\nHost: abcd123-vpce-abcd1234cbcdef0987.execute-api.eu-west-1.amazonaws.com\r\nTransfer-Encoding: ....

# 5. Response (FAILED)
request="POST https://external.cloudflare-domain.com/stage/endpoint" status_code=403

Request is rejected "403" because the proxy tries to send an incorrect request. Connect to "host override" then send a request in which the "Host" is the "signing host override".

Solution

After https://github.com/awslabs/aws-sigv4-proxy/blob/master/handler/proxy_client.go#L174 the override

if p.SigningHostOverride != "" {
    proxyReq.Host = p.SigningHostOverride
}

and signature generated https://github.com/awslabs/aws-sigv4-proxy/blob/master/handler/proxy_client.go#L186

if err := p.sign(proxyReq, service); err != nil {
    return nil, err
}

apply correction according to the host override parameter (this is missing)

if p.HostOverride != "" {
    proxyReq.Host = p.HostOverride
}

so the requests will be signed according to the "signing host override" while the request will be sent to the target host as specified in the "host override".