Neptune在连接到启用了IAM的实例时抛出了Bad handshake错误。

huangapple go评论97阅读模式
英文:

Neptune throws Bad handshake error while connecting to a IAM Enabled Neptune Instance

问题

我有一个启用了 IAM 的 AWS Neptune 实例,我可以在没有身份验证的情况下执行 CRUD 操作,但是当我启用身份验证时,会出现 Bad Handshake 错误日志。

注意:Lambda 函数具有完整的 Neptune 权限

错误日志:
无法实例化新连接;将连接状态设置为关闭。
为连接池创建新连接时出错:websocket: bad handshake
'E0104: 无法建立成功的连接:websocket: bad handshake'

注意:如果禁用 IAM 身份验证,我可以执行查询。请帮忙解决。

尝试签署请求,但身份验证失败。

英文:

I have an IAM Enabled AWS Neptune instance, I am able to perform crud operations without authentication but when I Enabled authentication it's throws Bad Handshake error logs.

Note: Lambda function has Full Neptune permissions

package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
    "time"
    
    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
    
    gremlingo "github.com/apache/tinkerpop/gremlin-go/v3/driver"
    "github.com/aws/aws-sdk-go/aws/session"
    v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
    )

func main() {
    lambda.Start(lambdaHandler)
}

func lambdaHandler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    driverConn, g = connect()
    result, err = g.AddV("User").Property("userId", "Check").Next()
    if err != nil {
        fmt.Println(err)
    }
}

func connect() {
    awsSess, err := session.NewSesionWithOptions(session.Options{
        SharedCondfigState: session.SharedConfigEnable,
    }),
    if err != nil {
        log.Fatalf("Failed to creating session: %s", err)
    }
    
    db_endpoint := os.Genenv("DB_ENDPOINT")
    connString := "wss://" +db_endpoint+":8182/gremlin"
    
    // Signing Request
    req, _ := http.NewRequest(http.MethodGet, connString, nil)
    signer := v4.NewSigner(awsSess.Config.Credentials)
    headerToUse, err := signer.Sign(req, nil, "neptune", *awsSess.Config.Region, time.Now())
    
    driverRemoteConnection, err := gremlingo.NewDriverRemoteConnection(connString,
        func(settings *gremlingo.driverRemoteConnectionSettings) {
            settings.TraversalSource = "g"
            settings.AuthInfo.Header = headerToUse
        })
    return driverRemoteConnection, traversalSource(driverRemoteConnection)
}

func traversalSource(driverConn *gremlingo.DriverRemoteConnection) *gremlingo.GraphTraversalSource {
    return gremlingo.Traversal_().WithRemote(driverConn)
}

Error Logs:
Failed to instantiate the new connection; setting connection state to closed.
Error creating new connection for connection pool: websocket: bad handshake
'E0104: no successful connections could be made: websocket: bad handshake'

Note: I am able to execute queries if IAM Authentication is disabled. Please help.

Tried signing request but unable to authentication is failing.

答案1

得分: 3

在代码中有几个需要修复的地方,以便与 Neptune IAM 配合使用,前提是已经授予了所有必要的权限。

  1. Neptune 的 IAM 签名器中的服务名称应为 neptune-db,而不是 neptune
  2. 类型 *gremlingo.driverRemoteConnectionSettings 应为 *gremlingo.DriverRemoteConnectionSettings
  3. 用于 settings.AuthInfo.Header 的标头实际上不是签名器返回的标头,而是原始请求的标头,因此应为 settings.AuthInfo.Header = req.Header

将它们组合起来,//Signing Request 下的代码块应如下所示:

    // Signing Request
    req, _ := http.NewRequest(http.MethodGet, connString, nil)
    signer := v4.NewSigner(awsSess.Config.Credentials)
    _, err := signer.Sign(req, nil, "neptune-db", *awsSess.Config.Region, time.Now())
    
    driverRemoteConnection, err := gremlingo.NewDriverRemoteConnection(connString,
        func(settings *gremlingo.DriverRemoteConnectionSettings) {
            settings.TraversalSource = "g"
            settings.AuthInfo.Header = req.Header
        })

需要注意的一点是,gremlin-go 目前没有自动刷新身份验证令牌的方法,这意味着在令牌过期后需要建立新的连接。

希望这能有所帮助。

英文:

There are a couple of things to fix in the code that should get it working with Neptune IAM, provided all necessary permissions are granted.

  1. The service name in IAM signer for Neptune should be neptune-db instead of neptune.
  2. The type *gremlingo.driverRemoteConnectionSettings should be *gremlingo.DriverRemoteConnectionSettings.
  3. The header to use for settings.AuthInfo.Header is actually not the header returned by the signer, but the header of the original request, so it should be settings.AuthInfo.Header = req.Header.

To put it together, the chunk of code under //Signing Request would look like this:

    // Signing Request
    req, _ := http.NewRequest(http.MethodGet, connString, nil)
    signer := v4.NewSigner(awsSess.Config.Credentials)
    _, err := signer.Sign(req, nil, "neptune-db", *awsSess.Config.Region, time.Now())
    
    driverRemoteConnection, err := gremlingo.NewDriverRemoteConnection(connString,
        func(settings *gremlingo.DriverRemoteConnectionSettings) {
            settings.TraversalSource = "g"
            settings.AuthInfo.Header = req.Header
        })

One thing to note is gremlin-go currently don't have a way to allow automatic refresh of the auth token, which means a new connection will have to be made after expiry.

Hopefully this helps.

答案2

得分: 1

您现在可以通过此pr进行自动刷新:https://github.com/apache/tinkerpop/pull/1989。

因此,这是一个利用新功能的代码示例。

package main

import (
	"context"
	"crypto/tls"
	"fmt"
	"net/http"
	"strings"
	"time"

	gremlingo "github.com/apache/tinkerpop/gremlin-go/v3/driver"
	v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
	"github.com/aws/aws-sdk-go-v2/config"
)

func main() {
	ctx := context.Background()
	db_endpoint := "a-gremilincluster-1.cluster-ro-randomstring.us-east-1.neptune.amazonaws.com"
	connString := "wss://" + db_endpoint + ":8181/gremlin"

	// Signing Request
	const emptyStringSHA256 = `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`
	req, err := http.NewRequest(http.MethodGet, connString, strings.NewReader(""))
	if err != nil {
		return
	}

	cfg, err := config.LoadDefaultConfig(ctx)
	if err != nil {
		fmt.Println(fmt.Errorf("unable to load AWS SDK config: %w", err))
	}
	cr, err := cfg.Credentials.Retrieve(ctx)
	if err != nil {
		fmt.Println(fmt.Errorf("unable to retrieve AWS credentials: %w", err))
	}
	signer := v4.NewSigner()

	gen := func() gremlingo.AuthInfoProvider {
		err := signer.SignHTTP(ctx, cr, req, emptyStringSHA256, "neptune-db", "us-east-1", time.Now())

		if err != nil {
			fmt.Println(err)
		}
		return gremlingo.HeaderAuthInfo(req.Header)
	}

	auth := gremlingo.NewDynamicAuth(gen)

	driverRemoteConnection, err := gremlingo.NewDriverRemoteConnection(connString,
		func(settings *gremlingo.DriverRemoteConnectionSettings) {
			settings.TraversalSource = "g"
			settings.AuthInfo = auth
			//settings.TlsConfig = &tls.Config{InsecureSkipVerify: true} Use this only if you're on a Mac running Go 1.18+ doing local dev. See https://github.com/golang/go/issues/51991

		})

	if err != nil {
		fmt.Println(err)
		return
	}
	// Cleanup
	defer driverRemoteConnection.Close()

	// Creating graph traversal
	g := gremlingo.Traversal().WithRemote(driverRemoteConnection)

	// Add a vertex with properties to the graph with the terminal step Iterate()
	promise := g.AddV("gremlin").Property("language", "go").Iterate()

	// The returned promised is a go channel to wait for all submitted steps to finish execution and return error.
	err = <-promise
	if err != nil {
		fmt.Println(err)
		return
	}
	// Get the value of the property
	result, err := g.V().HasLabel("gremlin").Values("language").ToList()
	if err != nil {
		fmt.Println(err)
		return
	}
	// Print the result
	for _, r := range result {
		fmt.Println(r.GetString())
	}
}

英文:

You can now perform automatic refresh thanks to this pr: https://github.com/apache/tinkerpop/pull/1989.

As such, here's a code sample that takes advantage of the new functionality.

package main
import (
&quot;context&quot;
&quot;crypto/tls&quot;
&quot;fmt&quot;
&quot;net/http&quot;
&quot;strings&quot;
&quot;time&quot;
gremlingo &quot;github.com/apache/tinkerpop/gremlin-go/v3/driver&quot;
v4 &quot;github.com/aws/aws-sdk-go-v2/aws/signer/v4&quot;
&quot;github.com/aws/aws-sdk-go-v2/config&quot;
)
func main() {
ctx := context.Background()
db_endpoint := &quot;a-gremilincluster-1.cluster-ro-randomstring.us-east-1.neptune.amazonaws.com&quot;
connString := &quot;wss://&quot; + db_endpoint + &quot;:8181/gremlin&quot;
// Signing Request
const emptyStringSHA256 = `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`
req, err := http.NewRequest(http.MethodGet, connString, strings.NewReader(&quot;&quot;))
if err != nil {
return
}
cfg, err := config.LoadDefaultConfig(ctx)
if err != nil {
fmt.Println(fmt.Errorf(&quot;unable to load AWS SDK config: %w&quot;, err))
}
cr, err := cfg.Credentials.Retrieve(ctx)
if err != nil {
fmt.Println(fmt.Errorf(&quot;unable to retrieve AWS credentials: %w&quot;, err))
}
signer := v4.NewSigner()
gen := func() gremlingo.AuthInfoProvider {
err := signer.SignHTTP(ctx, cr, req, emptyStringSHA256, &quot;neptune-db&quot;, &quot;us-east-1&quot;, time.Now())
if err != nil {
fmt.Println(err)
}
return gremlingo.HeaderAuthInfo(req.Header)
}
auth := gremlingo.NewDynamicAuth(gen)
driverRemoteConnection, err := gremlingo.NewDriverRemoteConnection(connString,
func(settings *gremlingo.DriverRemoteConnectionSettings) {
settings.TraversalSource = &quot;g&quot;
settings.AuthInfo = auth
//settings.TlsConfig = &amp;tls.Config{InsecureSkipVerify: true} Use this only if you&#39;re on a Mac running Go 1.18+ doing local dev. See https://github.com/golang/go/issues/51991
})
if err != nil {
fmt.Println(err)
return
}
// Cleanup
defer driverRemoteConnection.Close()
// Creating graph traversal
g := gremlingo.Traversal_().WithRemote(driverRemoteConnection)
// Add a vertex with properties to the graph with the terminal step Iterate()
promise := g.AddV(&quot;gremlin&quot;).Property(&quot;language&quot;, &quot;go&quot;).Iterate()
// The returned promised is a go channel to wait for all submitted steps to finish execution and return error.
err = &lt;-promise
if err != nil {
fmt.Println(err)
return
}
// Get the value of the property
result, err := g.V().HasLabel(&quot;gremlin&quot;).Values(&quot;language&quot;).ToList()
if err != nil {
fmt.Println(err)
return
}
// Print the result
for _, r := range result {
fmt.Println(r.GetString())
}
}

huangapple
  • 本文由 发表于 2023年3月14日 15:54:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75730330.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定