英文:
Why Go cqlsh can't get a token while keeps running requests good?
问题
我的服务在AWS集群中运行,并使用Keyspaces。该服务具有一个角色,并获取AWS_SECRET_ACCESS_KEY
、AWS_ACCESS_KEY_ID
、AWS_SESSION_TOKEN
、AWS_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
是使用你的AccessKeyId
和SecretAccessKey
获取的临时凭证。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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论