首页 > 其他分享 >通过STS来对AWS资源进行更灵活的权限控制

通过STS来对AWS资源进行更灵活的权限控制

时间:2024-04-24 19:56:33浏览次数:21  
标签:string err nil AWS aws STS cfg bucket 权限

一、前言

背景:一个S3 bucket,存储用户的文件,每个用户只允许上传、下载自己目录下的文件。

如何让Policy更灵活、更动态,可以让获取到的权限凭证可以匹配到单个终端用户的S3文件目录下。

本节主要介绍,以编程方式调用 AWS Security Token Service (AWS STS) 的API,获取访问AWS资源的临时安全凭证,并将这些凭证下发给终端用户,用于后续终端用户发起访问AWS资源请求时进行身份验证。

二、整体图

 

  1. 终端用户的客户端发出访问请求到服务器端。
  2. 服务器端调用STS API,以获取临时安全凭证。
  3. STS服务返回临时安全凭证。
  4. Server将获取到的临时安全凭证下发给客户端。
  5. 客户端使用临时安全凭证来访问AWS资源(本文中指S3 bucket)。

三、程序

package main

import (
    "context"
    "errors"
    "fmt"
    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/credentials"
    "github.com/aws/aws-sdk-go-v2/service/sts"
    "strconv"
    "strings"
    "time"
)

func main() {
    var bucketName = "{bucket名称}"
    var authPaths = []string{"uid"} //uid可替换用户真实uid对应的目录,可支持多层级目录
    var expire int32 = 3600 //STS token有效期
    cfg := &StoreClientConf{
        RoleArn:         "{roleArn}",
        Region:          "{bucket region}",
        AccessKeyID:     "{bucket ak}",
        AccessKeySecret: "{bucket sk}",
    }
    client := NewAwsClient(cfg)
    stsInfo, err := client.GetStsCredentials(context.Background(), bucketName, authPaths, expire)
    if err != nil {
        fmt.Println("client.GetStsCredentials err: " + err.Error())
        return
    }
    fmt.Println("sts ak: " + stsInfo.AccessKeyId)
    fmt.Println("sts sk: " + stsInfo.AccessSecret)
    fmt.Println("sts token: " + stsInfo.SecurityToken)
}

type AwsClient struct {
    roleArn         string
    region          string
    accessKeyID     string
    accessKeySecret string
}

type StoreClientConf struct {
    RoleArn         string
    Region          string
    AccessKeyID     string
    AccessKeySecret string
}

type StsCredentials struct {
    AccessKeyId   string
    AccessSecret  string
    SecurityToken string
    ExpireTime    int64
}

func NewAwsClient(cfg *StoreClientConf) *AwsClient {
    return &AwsClient{
        roleArn:         cfg.RoleArn,
        region:          cfg.Region,
        accessKeyID:     cfg.AccessKeyID,
        accessKeySecret: cfg.AccessKeySecret,
    }
}

func (s *AwsClient) loadConfig(ctx context.Context) (aws.Config, error) {
    cfg, err := config.LoadDefaultConfig(ctx,
        config.WithRegion(s.region),
        config.WithCredentialsProvider(credentials.StaticCredentialsProvider{
            Value: aws.Credentials{
                AccessKeyID: s.accessKeyID, SecretAccessKey: s.accessKeySecret, SessionToken: "",
                Source: "",
            },
        }),
    )
    if err != nil {
        fmt.Println("awsClient LoadDefaultConfig err:" + err.Error())
        return aws.Config{}, errors.New("awsClient LoadDefaultConfig err")
    }

    return cfg, nil
}

// 定义自己想要的policy
func (s *AwsClient) authPolicy(ctx context.Context, bucket string, authPaths []string) string {
    var resource []string
    for _, v := range authPaths {
        path := strings.TrimRight(v, "/") //去除最后一个/
        resource = append(resource, `"arn:aws:s3:::` + bucket+ `/` + path + `/*"`)
    }
    policy := `{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:GetObject",
                "s3:GetObjectAttributes",
                "s3:GetObjectTagging",
                "s3:PutObject",
                "s3:PutObjectTagging",
                "s3:UploadPart"
            ],
            "Effect": "Allow",
            "Resource": [` + strings.Join(resource, ",") + `]
        }
    ]
}`
    return policy
}

func (s *AwsClient) GetStsCredentials(ctx context.Context, bucket string, authPaths []string, expired int32) (*StsCredentials, error) {
    // 1.拼装授权策略
    policy := s.authPolicy(ctx, bucket, authPaths)

    // 2.初始化client
    cfg, err := s.loadConfig(ctx)
    if err != nil {
        return nil, err
    }
    client := sts.NewFromConfig(cfg)

    // 3.调用s3接口,获取sts token
    roleSessionName := "s3bucket" + strconv.FormatInt(time.Now().Unix(), 10) //需要按用户的维度去修改
    input := &sts.AssumeRoleInput{
        RoleArn:         &s.roleArn,
        RoleSessionName: &roleSessionName,
        DurationSeconds: &expired,
        Policy: aws.String(policy),
    }
    resp, err := client.AssumeRole(ctx, input)
    if err != nil {
        fmt.Println("GetStsCredentials client.AssumeRole err:" + err.Error())
        return nil, err
    }
    if resp == nil {
        fmt.Println("GetStsCredentials response is nil")
        return nil, err
    }
    var expire int64
    if resp.Credentials != nil && resp.Credentials.Expiration != nil {
        expire = resp.Credentials.Expiration.Unix()
    }
    return &StsCredentials{
        AccessKeyId:   *resp.Credentials.AccessKeyId,
        AccessSecret:  *resp.Credentials.SecretAccessKey,
        SecurityToken: *resp.Credentials.SessionToken,
        ExpireTime: expire,
    }, nil
}

 

标签:string,err,nil,AWS,aws,STS,cfg,bucket,权限
From: https://www.cnblogs.com/573583868wuy/p/18156193

相关文章

  • 使用create-react-app,配置proxy报错(options.allowedHosts[0] should be a non-empty
    ​#使用create-react-app,配置proxy报错(options.allowedHosts[0]shouldbeanon-emptystring)今天在启动项目的时候遇到一个神奇的问题,这个问题具体报错信息是:Invalidoptionsobject.DevServerhasbeeninitializedusinganoptionsobjectthatdoesnotmatchtheAP......
  • 菜单权限表sqlite和mysql
    sqliteCREATETABLEsys_user(idTEXTPRIMARYKEY,nameTEXTNOTNULL,phoneTEXT,passwordTEXTNOTNULL,create_timeDA......
  • PostScript 是一种页面描述语言,最初由 Adobe 公司开发。它被设计用于描述页面的外观和
    PostScript的起源可以追溯到1982年,当时由Adobe公司的创始人之一约翰·沃诺克(JohnWarnock)和查尔斯·格什克(CharlesGeschke)共同开发。沃诺克和格什克当时都是在施乐帕克研究中心工作,他们在那里开始了对一种新的页面描述语言的研究和开发。当时的打印技术面临着一些挑战,......
  • DRF之权限组件源码分析
    DRF之权限组件源码分析【一】权限组件介绍DjangoRESTframework(DRF)中的权限组件用于控制API的访问权限。DRF内置了多个常用的权限类,同时也允许你创建自定义的权限类以满足特定需求。【二】内置权限类IsAuthenticated:要求用户在访问API时进行身份验证,即用户必须登录。IsA......
  • Udemy AWS SAA - RDS
    RelationalDatabaseServicesmanageDBusingSQLallowyoutocreatedatabasesinthecloudthataremanagedbyawsPostgres,MySQL,MariaDB,Oracle,MicrosoftSQLServer,AuroraStorageAutoScalingwhendetectyourunoutoffreedatabasestorage......
  • 无root权限,解决conda环境的报错ImportError: /lib/x86_64-linux-gnu/libstdc++.so.6:
    网上的方法都需要sudo或者root权限,但是服务器多是实验室公用,没有ruuto权限,因此更好的办法是通过conda只改自己虚拟环境的环境变量。问题原因问题的根本原因是Linux系统没有GLIBCXX_3.4.30动态链接库。这个库和gcc版本有关。因此要么你更换版本,要么找一个别的so链接到这个连接......
  • Cassandra节点重启失败 java.lang.RuntimeException: A node with address *** alread
    问题杀死一个节点后重启报节点已存在:java.lang.RuntimeException:Anodewithaddress***alreadyexists,cancellingjoin.Usecassandra.replace_addressifyouwanttoreplacethisnode.解决方法到另一个节点Cassandra的bin目录./nodetoolstatus查看需要重启......
  • 修改ubuntu里root用户的权限
    进入到root用户,若是不知道root用户的密码sudopasswdroot设置root的密码2.进入到以下目录cd/usr/share/lightdm/lightdm.conf.d/进行下列操作gedit50-unity-greeter.conf可以看到进入了这个界面这下面三行的内容都是我加进去的user-session=ubuntugreeter-sho......
  • Linux系列教程——Linux基本权限、Linux特殊权限、LinuxACL控制、Linux输入输出
    @目录1Linux基本权限1.权限基本概述1.什么是权限?2.为什么要有权限?3.权限与用户之间的关系?4.权限中的rwx分别代表什么含义?2.权限设置示例1.为什么要设定权限,我们又如何修改一个文件的权限?2.使用chmod设定权限示例3.权限设置案例3.权限设置案例4.属主属组设置2Linux特殊权限1.特......
  • 使用命令行 Windows 修改文件权限
    向文件添加管理员组和系统组的完全访问权限(F)icacls<file>/inheritance:r/grant"Administrators:F"/grant"SYSTEM:F"将<file>替换为你的文件名向文件添加指定用户(组)的完全访问权限(F)首先查询该用户的SID:$Get-LocalUser|Select-ObjectName,SIDName......