安全凭证服务(STS)

STS即Secure Token Service 是一种安全凭证服务,可以使用STS来完成对于临时用户的访问授权。对于跨用户短期访问s3资源时,可以使用STS服务。这样就不需要透露主账号AK/SK,只需要生成一个短期访问凭证给需要的用户使用即可,避免主账号AK/SK泄露带来的安全风险。

初始化STS服务

ak := "<your-access-key>"
sk := "<your-secret-access-key>"
endpoint := "<your-endpoint>"
config := &aws.Config{
    Credentials:      credentials.NewStaticCredentials(ak, sk, ""),
    Endpoint:         aws.String(endpoint),
    S3ForcePathStyle: aws.Bool(true),
    DisableSSL:       aws.Bool(true),
    LogLevel:         aws.LogLevel(aws.LogDebug),
    Region:           aws.String(region),
}
sess := session.Must(session.NewSession(config))
svc := sts.New(sess)

获取临时token

bucket := "<your-bucket-name>"
roleSessionName := "<your-session-name>"
arn := "arn:aws:iam:::role/xxxxxx"
policy := `{"Version":"2012-10-17","Statement":{"Effect":"Allow","Action":["s3:*"],"Resource":["arn:aws:s3:::%s","arn:aws:s3:::%s/*"]}}`
policy = fmt.Sprintf(policy, bucket, bucket)
fmt.Println("policy: ", policy)
out, err := svc.AssumeRole(&sts.AssumeRoleInput{
    Policy:          aws.String(policy),
    RoleArn:         aws.String(arn),
    RoleSessionName: aws.String(roleSessionName),
})
if err != nil {
    fmt.Println("err, ", err)
    return
}
fmt.Println("assumeRole success, ", out)
参数 类型 描述
RoleArn String 角色的ARN,在控制台创建角色后可以查看
Policy String 角色的policy,需要是json格式,限制长度1~2048
RoleSessionName String 角色会话名称,此字段为用户自定义,限制长度2~64
DurationSeconds Integer 会话有效期时间,默认为3600s

使用临时token

实现一个CredentialsProvider,支持更新ak/sk和token。

type MyCredProvider struct {
    sync.Mutex

    value *credentials.Value
}

func NewMyCredProvider(ak, sk, token string) *MyCredProvider{
    p := &MyCredProvider{
        value: &credentials.Value{
            AccessKeyID:     ak,
            SecretAccessKey: sk,
            SessionToken:    token,
            ProviderName:    "MyCredProvider",
        },
    }
    return p
}

func (p *MyCredProvider) Retrieve() (credentials.Value, error) {
    defer p.Unlock()
    p.Lock()

    return *p.value, nil
}

func (p *MyCredProvider) IsExpired() bool {
    return false
}

// 更新token
func (p *MyCredProvider) UpdateCred(ak, sk, token string) {
    defer p.Unlock()
    p.Lock()

    p.value.AccessKeyID = ak
    p.value.SecretAccessKey = sk
    p.value.SessionToken = token
}

使用临时token

ak := "<your-access-key>"
sk := "<your-secret-access-key>"
token := "<your-session-token>"
endpoint := "<your-endpoint>"
credProvider := NewMyCredProvider(ak, sk, token)
config := &aws.Config{
    Credentials:      credentials.NewCredentials(credProvider),
    Endpoint:         aws.String(endpoint),
    S3ForcePathStyle: aws.Bool(true),
    DisableSSL:       aws.Bool(true),
    LogLevel:         aws.LogLevel(aws.LogDebug),
    Region:           aws.String(region),
}
sess := session.Must(session.NewSession(config))
svc := s3.New(sess)