当前位置:首页 > 文章列表 > Golang > Go问答 > 使用 Node.js 的 aws-sdk 包成功获取 AWS STS AssumeRole 的临时凭证,但使用 Golang 的 aws-sdk 获取相同凭证和角色 ARN 失败

使用 Node.js 的 aws-sdk 包成功获取 AWS STS AssumeRole 的临时凭证,但使用 Golang 的 aws-sdk 获取相同凭证和角色 ARN 失败

来源:stackoverflow 2024-02-06 08:21:25 0浏览 收藏

来到golang学习网的大家,相信都是编程学习爱好者,希望在这里学习Golang相关编程知识。下面本篇文章就来带大家聊聊《使用 Node.js 的 aws-sdk 包成功获取 AWS STS AssumeRole 的临时凭证,但使用 Golang 的 aws-sdk 获取相同凭证和角色 ARN 失败》,介绍一下,希望对大家的知识积累有所帮助,助力实战开发!

问题内容

我有 golang 和 nodejs 代码来获取同一组凭据 accesskey、secretkey 和 rolearn 的临时凭据。 nodejs 代码给了我临时信用,而 go 代码给了我以下错误

操作错误 sts:assumerole,https 响应错误 statuscode:403,requestid:ebccfbf8-abed-4490-83ce-730d87d131,api 错误 accessdenied:用户:arn:aws:iam:::user/sts-user-1234无权对资源执行:sts:assumerole:arn:aws:iam:::role/sts-role-123 有人可以帮我解决这个问题吗?

下面是我的 go 代码的链接。

https://go.dev/play/p/txv2cttsitd

使用的软件包版本:

github.com/aws/aws-sdk-go-v2 v1.20.0 github.com/aws/aws-sdk-go-v2/config v1.18.29 github.com/aws/aws-sdk-go-v2 /service/sts v1.20.0

package main

import (
    "context"
    "errors"
    "fmt"
    "net/http"
    "os"

    "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"
)

// awsprovider ...
type awsprovider struct{}

// newawsprovider ...
// var newawsprovider connection = &awsprovider{}

var (
    defaultregion      = "us-east-1"
    defaultsessionname = "mcmp"
)

// connectionvalidation ...
type connectionvalidation struct {
    connectionid  string   `json:"connectionid" bson:"connectionid"`
    vaultconfigid string   `json:"vaultconfigid,omitempty"`
    provider      provider `json:"provider,omitempty" bson:"provider"`
    reference     string   `json:"reference,omitempty" bson:"reference"`
}

type provider struct {
    type        string                 `json:"type" bson:"type" validate:"required"`
    configdata  map[string]interface{} `json:"configdata,omitempty" bson:"configdata,omitempty"`
    credentials []fields               `json:"credentials,omitempty" bson:"credentials,omitempty"`
}

type fields struct {
    key   string `json:"key"`
    value string `json:"value"`
}

// validate ...
func validate(connection *connectionvalidation) (err error) {
    accesskey := ""
    secretkey := ""

    configdata := connection.provider.configdata
    if configdata["delegatedaccess"] != nil {
        delegatedaccess, ok := configdata["delegatedaccess"].(string)
        if !ok || delegatedaccess == "" {
            err = errors.new("invalid delegatedaccess")
            return
        }
        err = validatedelegatedaccess(connection, accesskey, secretkey, delegatedaccess)
        return
    }

    err = validateasset(accesskey, secretkey, defaultregion)
    return
}

// checkandaddproxy ...
func checkandaddproxy(config aws.config) aws.config {
    if os.getenv("https_proxy") != "" {
        httpclient := &http.client{
            transport: &http.transport{
                proxy: http.proxyfromenvironment,
            },
        }
        config.httpclient = httpclient
    }
    return config
}

func validatedelegatedaccess(connection *connectionvalidation, accesskey, secretkey, delegatedaccess string) (err error) {
    config, err := config.loaddefaultconfig(context.todo(), config.withregion(defaultregion))
    if err != nil {
        panic("configuration error validatedelegatedaccess, " + err.error())
    }
    config = checkandaddproxy(config)
    config.region = defaultregion

    config.credentials = aws.newcredentialscache(credentials.newstaticcredentialsprovider(accesskey, secretkey, ""))

    client := sts.newfromconfig(config)

    params := &sts.assumeroleinput{
        rolearn:         &delegatedaccess,
        rolesessionname: &defaultsessionname,
    }

    configdata := connection.provider.configdata
    if configdata["externalid"] != nil {
        externalid, ok := configdata["externalid"].(string)
        if !ok || externalid == "" {
            err = errors.new("invalid externalid")
            return
        }
        params.externalid = &externalid
    }

    _, err = client.assumerole(context.todo(), params)
    return
}

func validateasset(accesskey, secretkey, region string) (err error) {
    config := *aws.newconfig()
    config.region = defaultregion
    config.credentials = aws.newcredentialscache(credentials.newstaticcredentialsprovider(accesskey, secretkey, ""))
    config = checkandaddproxy(config)

    client := sts.newfromconfig(config)

    input := &sts.getcalleridentityinput{}
    _, err = client.getcalleridentity(context.todo(), input)
    if err != nil {
        return err
    }
    return
}

func main() {
    fmt.println("---validate aws creds---")
    conn := connectionvalidation{
        connectionid: "id",
        provider: provider{type: "aws",
            configdata: map[string]interface{}{"accountnumber": "",
                "delegatedaccess": "",
                "externalid":      "12345"},
        },
    }
    err := validate(&conn)
    if err != nil {
        fmt.printf("\n --- error validate aws creds---%+v", err)
    } else {
        fmt.println("validate creds success")
    }

}

这是 nodejs 代码

软件包版本: "aws-sdk": "^2.1429.0"

var AWSClient = require('aws-sdk');
var proxy = require('proxy-agent');

var checkForProxy = function () {
  if (process.env.https_proxy !== undefined) {
    console.log("Configuring AWS client to use https proxy");
    AWSClient.config.update({
      httpOptions: { agent: proxy(process.env.https_proxy) }
    });
  }
}

async function getTempCredentials(result) {
  console.log('-- Inside credential-validator-service/getTempCredentials... --');
  try {
    return new Promise(function (resolve, reject) {
      if (result['delegatedAccess'] && result['accessKey'] && result['secretKey']) {
        AWSClient.config.update({
          accessKeyId: result['accessKey'],
          secretAccessKey: result['secretKey'],
          region:"us-east-1"
        });
        checkForProxy()
        console.log("AWSClient config-----")
        console.log(AWSClient.config)
        var sts = new AWSClient.STS();
        var params = {
          RoleArn: result['delegatedAccess'],
          RoleSessionName: "MCMP"
        };
        if (result['externalId']) {
          console.log("Found externalId in payload, validating ARN with externalId")
          params['ExternalId'] = result['externalId']
        }
        sts.assumeRole(params, function (err, result) {
          if (err) {
            console.log("Error occured " + JSON.stringify(err));
            reject(err);
          } else {
            console.log("Temporary credential retrieved successfully");
            resolve({
              "message": "Delegated Credentials fetched successfully",
              "delegatedcredentials": result['Credentials'],
              "translateCode": "CO200_FETCH_SUCCESS",
              "translateParameters": [],
              "statusCode": 200
            });
          }
        });
      } else {
        reject({
          "message": "Required credential details not found to fetch role, please provide arn, accessKey and secretKey",
          "translateCode": "CO400_FETCH_FAIL",
          "translateParameters": [],
          "statusCode": 400
        });
      }
    });
  } catch (error) {
    console.log.error("error while calling assume role of aws : " + JSON.stringify(error));
    return {
      "message": "System Failure. Due to: " + error.message,
      "translateCode": "CO500_ERR",
      "translateParameters": [error.message],
      "statusCode": 500
    }
  }
}

const checkDelegateAndUpdate = (body, callback) => {
  if (body.credentials.delegatedAccess) {
    const payload = {
      accessKey: body.credentials.passwordFields.accessKey,
      secretKey: body.credentials.passwordFields.secretKey,
      delegatedAccess: body.credentials.delegatedAccess,
      externalId: body.credentials.externalId
    };
    getTempCredentials(payload).then(({
      delegatedcredentials
    }) => {
      AWSClient.config.update({
        accessKeyId: delegatedcredentials.AccessKeyId,
        secretAccessKey: delegatedcredentials.SecretAccessKey,
        sessionToken: delegatedcredentials.SessionToken
      });
      callback(null, "Success");
    }).catch(err => {
      console.log("Error occured while fetching temporary credentials ", err.message);
      callback(err);
    });
  } else {
    AWSClient.config.update({
      accessKeyId: body.credentials.passwordFields.accessKey,
      secretAccessKey: body.credentials.passwordFields.secretKey
    });
    callback(null, "Success");
  }
}

var testAccount = function (asset_payload, callback) {

  if (!asset_payload.credentials.passwordFields.accessKey ||
    !asset_payload.credentials.passwordFields.secretKey) {
    return callback(Error, null);
  } else {
    checkDelegateAndUpdate(asset_payload, (err, _res) => {
      if (err) {
        return callback(err, null);
      } else {
        AWSClient.config.update({
          accessKeyId: asset_payload.credentials.passwordFields.accessKey,
          secretAccessKey: asset_payload.credentials.passwordFields.secretKey
        });

        checkForProxy()
        var sts = new AWSClient.STS();
        sts.getCallerIdentity({}, function (err, response) {
          if (err) {
            return callback(err, null);
          } else {
            return callback(null, response);
          }
        });
      }
    });
  }
};

var requestPayload = {
    "basicInfo": {
        "accountName": "camaws",
        "serviceProviderType": "aws",
        "serviceProviderCode": "aws",
        "isActive": "Active",
        "accountType": "subaccount",
        "userType": "asset"
    },
    "advancedInfo": {
        "accountNumber": ""
    },
    "credentials": {
        "credentialName": "awscred",
        "purpose": ["assetIngestion"],
        "status": true,
        "externalId": "12345",
        "delegatedAccess": "",
        "passwordFields": {
            "accessKey": "",
            "secretKey": "",
            "additionalInfo": ""
        }
    }
}


testAccount(requestPayload, function (err, result) {
    if (err) {
        console.log(err)
    }else{
        console.log("success*********")
        console.log(result)
    }
});

正确答案


访问被拒绝意味着访问被拒绝。 因此,您的 IAM 策略可能不允许您担任该角色。 检查 sts 假设调用的参数。 可以在这里找到 go 承担角色的工作示例:https://www.go-on-aws.com/aws-go-sdk-v2/sts/crossaccount/ 出于安全原因,请确保永远不要将访问密钥和访问秘密直接放入代码中。

今天关于《使用 Node.js 的 aws-sdk 包成功获取 AWS STS AssumeRole 的临时凭证,但使用 Golang 的 aws-sdk 获取相同凭证和角色 ARN 失败》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!

版本声明
本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
rpcx lib 中的 StringToSliceByte 解析与使用rpcx lib 中的 StringToSliceByte 解析与使用
上一篇
rpcx lib 中的 StringToSliceByte 解析与使用
通过使用Go语言编写的方法来检测图像中的二维码
下一篇
通过使用Go语言编写的方法来检测图像中的二维码
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • PPTFake答辩PPT生成器:一键生成高效专业的答辩PPT
    PPTFake答辩PPT生成器
    PPTFake答辩PPT生成器,专为答辩准备设计,极致高效生成PPT与自述稿。智能解析内容,提供多样模板,数据可视化,贴心配套服务,灵活自主编辑,降低制作门槛,适用于各类答辩场景。
    3次使用
  • SEO标题Lovart AI:全球首个设计领域AI智能体,实现全链路设计自动化
    Lovart
    SEO摘要探索Lovart AI,这款专注于设计领域的AI智能体,通过多模态模型集成和智能任务拆解,实现全链路设计自动化。无论是品牌全案设计、广告与视频制作,还是文创内容创作,Lovart AI都能满足您的需求,提升设计效率,降低成本。
    3次使用
  • 美图AI抠图:行业领先的智能图像处理技术,3秒出图,精准无误
    美图AI抠图
    美图AI抠图,依托CVPR 2024竞赛亚军技术,提供顶尖的图像处理解决方案。适用于证件照、商品、毛发等多场景,支持批量处理,3秒出图,零PS基础也能轻松操作,满足个人与商业需求。
    26次使用
  • SEO标题PetGPT:智能桌面宠物程序,结合AI对话的个性化陪伴工具
    PetGPT
    SEO摘要PetGPT 是一款基于 Python 和 PyQt 开发的智能桌面宠物程序,集成了 OpenAI 的 GPT 模型,提供上下文感知对话和主动聊天功能。用户可高度自定义宠物的外观和行为,支持插件热更新和二次开发。适用于需要陪伴和效率辅助的办公族、学生及 AI 技术爱好者。
    24次使用
  • 可图AI图片生成:快手可灵AI2.0引领图像创作新时代
    可图AI图片生成
    探索快手旗下可灵AI2.0发布的可图AI2.0图像生成大模型,体验从文本生成图像、图像编辑到风格转绘的全链路创作。了解其技术突破、功能创新及在广告、影视、非遗等领域的应用,领先于Midjourney、DALL-E等竞品。
    50次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码