Search code examples
amazon-neptune

400 bad request when attempting connection to AWS Neptune with IAM enabled


I am unable to connect to neptune instance that has IAM enabled. I have followed the AWS documentation (corrected a few of my silly errors on the way) but without luck.

When I connect via my Java application using the SigV4Signer and when I use the gremlin console, I get a 400 bad request websocket error.

o.a.t.g.d.Handler$GremlinResponseHandler : Could not process the response

io.netty.handler.codec.http.websocketx.WebSocketHandshakeException: Invalid handshake response getStatus: 400 Bad Request
    at io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker13.verify(WebSocketClientHandshaker13.java:267)
    at io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker.finishHandshake(WebSocketClientHandshaker.java:302)
    at org.apache.tinkerpop.gremlin.driver.handler.WebSocketClientHandler.channelRead0(WebSocketClientHandler.java:69)

When I run com.amazon.neptune.gremlin.driver.example.NeptuneGremlinSigV4Example (from my machine over port-forwarding AND from the EC2 jumphost) I get:

java.util.concurrent.TimeoutException: Timed out while waiting for an available host - check the client configuration and connectivity to the server if this message persists

I am able to connect to my neptune instance using the older deprecated certificate mechanism. I am using a jumphost ec2 instance and port-forwarding.

I believe that the SigV4 aspect is working as in the neptune audit logs I can see attempts to connect with the aws_access_key:

1584098990319, <jumphost_ip>:47390, <db_instance_ip>:8182, HTTP_GET, [unknown], [unknown], "HttpObjectAggregator$AggregatedFullHttpRequest(decodeResult: success, version: HTTP/1.1, content: CompositeByteBuf(ridx: 0, widx: 0, cap: 0, components=0)) GET /gremlin HTTP/1.1 upgrade: websocket connection: upgrade sec-websocket-key: g44zxck9hTI9cZrq05V19Q== sec-websocket-origin: http://localhost:8182 sec-websocket-version: 13 Host: localhost:8182 X-Amz-Date: 20200313T112950Z Authorization: AWS4-HMAC-SHA256 Credential=<my_access_key>/20200313/eu-west-2/neptune-db/aws4_request, SignedHeaders=host;sec-websocket-key;sec-websocket-origin;sec-websocket-version;upgrade;x-amz-date, Signature=<the_signature> content-length: 0", /gremlin

But when I look

This is the policy that I created:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "neptune-db:*"
            ],
            "Resource": [
                "arn:aws:neptune-db:eu-west-2:<my_aws_account>:*/*"
            ]
        }
    ]
}

I have previously tried with a policy that references my cluster resource id. I created a new api user with this policy attached as its only permission. (I've tried this twice).

IAM is showing my that the graph-user I created has not successfully logged in (duh).

Seems that the issue is with the IAM set-up somewhere along the line. Is it possible to get more information out of AWS with regards to why the connection attempt is failing?

I am using the most recent release of Neptune and the 3.4.3 Gremlin Driver and console. I am using Java 8 when running the NeptuneGremlinSigV4Example and building the libraries to deploy to the console.

thanks


Solution

  • It appears from the audit log output that the SigV4 Signature that is being created is using localhost as the Host header. This is most likely due to the fact that you're using a proxy to connect to Neptune. By default, the NeptuneGremlinSigV4Example assumes that you're connecting directly to a Neptune endpoint and reuses the endpoint as the Host header in creating the Signature.

    To get around this, you can use the following example code that overrides this process and allows you to use a proxy and still sign the request properly.

    https://github.com/aws-samples/amazon-neptune-samples/tree/master/gremlin/gremlin-java-client-demo

    I was able to get this to work using the following.

    • Create an SSL tunnel from you local workstation to your EC2 jumphost:
    ssh -i <key-pem-file> -L 8182:<neptune-endpoint>:8182 ec2-user@<ec2-jumphost-hostname>
    
    • Set the following environment variables:
    export AWS_ACCESS_KEY_ID=<access_key>
    export AWS_SECRET_ACCESS_KEY=<secret_key>
    export SERVICE_REGION=<region_id>  (i.e. us-west-2)
    
    • Once the tunnel is up and your environment variables are set, use the following format with the Gremlin-Java-Client-Demo:
    java -jar target/gremlin-java-client-demo.jar --nlb-endpoint localhost --lb-port 8182 --neptune-endpoint <neptune-endpoint> --port 8182 --enable-ssl --enable-iam-auth