为什么在持续运行请求的情况下,Go cqlsh无法获取令牌?

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

Why Go cqlsh can't get a token while keeps running requests good?

问题

我的服务在AWS集群中运行,并使用Keyspaces。该服务具有一个角色,并获取AWS_SECRET_ACCESS_KEYAWS_ACCESS_KEY_IDAWS_SESSION_TOKENAWS_SECURITY_TOKEN环境变量。

要连接Keyspaces,我执行以下操作:


import (
	"context"
	"time"
	
	credentialsV1 "github.com/aws/aws-sdk-go/aws/credentials"
	ec2rolecredsV1 "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
	ec2metadataV1 "github.com/aws/aws-sdk-go/aws/ec2metadata"
	aws_sess "github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sigv4-auth-cassandra-gocql-driver-plugin/sigv4"
	"github.com/gocql/gocql"
)

type Repository struct {
	session *gocql.Session
    ...
}

func (r *Repository) ConnectCassandra(ctx context.Context) {
	awsSession, err := aws_sess.NewSession()

	creds := credentialsV1.NewChainCredentials(
		[]credentialsV1.Provider{
			&credentialsV1.EnvProvider{},
			&ec2rolecredsV1.EC2RoleProvider{
				Client: ec2metadataV1.New(awsSession),
			},
		},
	)

	value, err := creds.Get()

	auth := sigv4.NewAwsAuthenticator()
	auth.SessionToken = value.SessionToken
	auth.AccessKeyId = value.AccessKeyID
	auth.SecretAccessKey = value.SecretAccessKey

	cluster := gocql.NewCluster(Host)

	cluster.Timeout = 10 * time.Second
	cluster.ConnectTimeout = 10 * time.Second
	cluster.Consistency = gocql.LocalQuorum
	cluster.Keyspace = Keyspace
	cluster.Port = Port

	cluster.Authenticator = auth

	r.session, err = cluster.CreateSession()

}

func (r *Repository) GetData() (*Data, error) {
	iter := r.session.Query(...)

	scanner := iter.Scanner()

	for scanner.Next() {
		...
	}
}

该服务定期请求一些数据。经过一段时间(约24小时)后,我开始收到错误消息:

2022/02/10 20:29:50 error: failed to connect to XX.XX.XX.XX:9142 due to error: Authentication failure: Session token expired at Wed Feb 09 10:11:42 UTC 2022

与此同时,请求在没有错误的情况下继续运行。显然,这意味着最终gocql驱动程序检索到了一个令牌。但为什么我会收到这些错误消息,出了什么问题?我应该做出什么改变,以停止收到错误消息,并确保一切正常工作?

英文:

My service runs in AWS cluster and uses Keyspaces. The service has a role and gets, AWS_SECRET_ACCESS_KEY, AWS_ACCESS_KEY_ID, AWS_SESSION_TOKEN, AWS_SECURITY_TOKEN env vars.

To connect Keyspaces I do the following:


import (
	"context"
	"time"
	
	credentialsV1 "github.com/aws/aws-sdk-go/aws/credentials"
	ec2rolecredsV1 "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
	ec2metadataV1 "github.com/aws/aws-sdk-go/aws/ec2metadata"
	aws_sess "github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sigv4-auth-cassandra-gocql-driver-plugin/sigv4"
	"github.com/gocql/gocql"
)

type Repository struct {
	session *gocql.Session
    ...
}

func (r *Repository) ConnectCassandra(ctx context.Context) {
	awsSession, err := aws_sess.NewSession()

	creds := credentialsV1.NewChainCredentials(
		[]credentialsV1.Provider{
			&credentialsV1.EnvProvider{},
			&ec2rolecredsV1.EC2RoleProvider{
				Client: ec2metadataV1.New(awsSession),
			},
		},
	)

	value, err := creds.Get()

	auth := sigv4.NewAwsAuthenticator()
	auth.SessionToken = value.SessionToken
	auth.AccessKeyId = value.AccessKeyID
	auth.SecretAccessKey = value.SecretAccessKey

	cluster := gocql.NewCluster(Host)

	cluster.Timeout = 10 * time.Second
	cluster.ConnectTimeout = 10 * time.Second
	cluster.Consistency = gocql.LocalQuorum
	cluster.Keyspace = Keyspace
	cluster.Port = Port

	cluster.Authenticator = auth

	r.session, err = cluster.CreateSession()

}

func (r *Repository) GetData() (*Data, error) {
	iter := r.session.Query(...)

	scanner := iter.Scanner()

	for scanner.Next() {
		...
	}
}

The service periodically requests some data. After some time (~24h) I start getting errors:

2022/02/10 20:29:50 error: failed to connect to XX.XX.XX.XX:9142 due to error: Authentication failure: Session token expired at Wed Feb 09 10:11:42 UTC 2022

Meanwhile requests are running with no errors. Obviously that means that finally gocql driver retrieves a token. But why I get these errors and what's done wrong? What should I change to stop getting and to be sure that everything works as it should?

答案1

得分: 1

一个SessionToken是使用你的AccessKeyIdSecretAccessKey获取的临时凭证。Session Token有一个过期时间,只在一段时间内有效。

当它过期时,使用该令牌进行的任何AWS API调用都会返回你遇到的过期错误。有几种处理这种情况的方法,但实质上你想通过获取新的令牌来“刷新”你正在使用的凭证,并重试失败的调用。

根据你的代码,你可能希望在你的Repository结构体上定义一个凭证刷新方法,当遇到特定的错误时可以调用该方法获取新的凭证,并重试失败的调用。

可以在这里阅读更多信息:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html

英文:

A SessionToken is a temporary credential that is retrieved using your AccessKeyId and SecretAccessKey. Session Tokens have an expiration, and are only valid for a period of time.

When it expires, any AWS API call made using that token will return that expiration error you are getting. There are a couple of ways to handle this, but effectively you want to 'refresh' the creds you are using by retrieving a new token, and retrying failed calls.

Looking at your code, you may want to define a cred refresh method on your Repository struct that can be called to get new creds again when that specific error is hit, and retry the failed call.

Can read more here: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html

huangapple
  • 本文由 发表于 2022年2月11日 04:39:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/71071976.html
匿名

发表评论

匿名网友

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

确定