AWS SSO 令牌可以自动刷新(通过浏览器登录)吗?

问题描述 投票:0回答:2

我有一个使用 AWS SDK Ruby v3 的 Ruby 应用程序,最近我添加了对使用 SSO 配置文件而不是静态“密钥 ID + 秘密”配置的支持。

新设置在一段时间内运行良好,直到令牌“过期”并且我开始出现

Aws::Errors::InvalidSSOToken
异常,此时用户需要手动运行 CLI 的
aws sso login
才能获取浏览器登录屏幕。

我希望跳过手动 AWS CLI 运行步骤 - 如果开发工具包可以直接执行

aws sso login
步骤(使用正确的配置文件)。

我可能可以使用正确的参数来实现

exec
- 但我想以“SDK 方式”实现。

ruby amazon-web-services sdk single-sign-on aws-cli
2个回答
1
投票

是的,可以。您可以在收到

InvalidSSOToken
时添加错误处理程序,然后进行 SSO 身份验证。

我从未尝试过SDK方式。我尝试过

exec
cli 命令
aws sso login
(因为它更容易)。它将创建一个包含
cache.json
token
值的
expiresAt
文件。

这是我用作参考的项目:https://github.com/NeilJed/aws-sso-credentials/blob/master/awssso

这是您可以用作检查令牌是否过期的参考部分。 https://github.com/NeilJed/aws-sso-credentials/blob/master/awssso#L110-L137

这是通过 SDK 但使用 Python 执行此操作的另一个示例: https://stackoverflow.com/a/71850591/22277802


0
投票

正在进行中的示例代码

这不是一个完整的实现,而是我要进行的测试的一些草稿本。下面代码的当前状态是,运行后,

Aws
API 无需额外凭据即可工作,但我有一些担忧。

@tsal-troser 致敬,他在自己的回答中指出了用于创建此示例代码的 Python 示例,以及编写该 Python 代码的 @2ps

require 'aws-sdk-core'

class SSOConfig
    def initialize profile = nil
        profile = 'default' if profile.to_s.empty?
        @profile = profile
        raise "No AWS config file found!" unless File.exists? "#{ENV['HOME']}/.aws/config"
        @config = File.readlines("#{ENV['HOME']}/.aws/config").collect(&:chomp)
        @profile_config = @config.select do |l| 
            (l =~ /^\[profile #{@profile}\]$/ .. l =~ /^(?!\[profile #{@profile}\])(\[|$)/) ? true : false
        end
        raise "Failed to find session for profile #{profile!}" if session.to_s.empty?
        @session_config = @config.select do |l| 
            (l =~ /^\[sso-session #{session}\]$/ .. l =~ /^(?!\[sso-session #{session}\])(\[|$)/) ? true : false
        end
    end
    
    def session
        @profile_config.select do |l|
            l =~ /^sso_session/
        end.collect do |l|
            (l.split /\s*=\s*/).last
        end.first
    end
    
    def start_url
        @session_config.select do |l|
            l =~ /^sso_start_url/
        end.collect do |l|
            (l.split /\s*=\s*/).last
        end.first
    end
    
    def account_id
        @profile_config.select do |l|
            l =~ /^sso_account_id/
        end.collect do |l|
            (l.split /\s*=\s*/).last
        end.first
    end
    
    def region
        'us-east-1' # can we use other regions?
    end
    
    def client_name
        'MyClientName' # change to what you want
    end

    def try_renew_token
        puts "SSO token has expired! Trying to re-authorize SSO session..."
        oidc_client = Aws::SSOOIDC::Client.new(region: self.region)
        creds = oidc_client.register_client(client_name: self.client_name, client_type: 'public')
        auth = oidc_client.start_device_authorization(
            client_id: creds.client_id,
            client_secret: creds.client_secret,
            start_url: self.start_url)
        puts "Verification code: #{auth.user_code}"
        puts "Open your browser with this url: #{auth.verification_uri_complete}"
        puts "When complete, press ENTER here"
        STDIN.getch
        puts ""
        token = oidc_client.create_token(
            grant_type: 'urn:ietf:params:oauth:grant-type:device_code', 
            device_code: auth.device_code,
            client_id: creds.client_id,
            client_secret: creds.client_secret)
        sso_client = Aws::SSO::Client.new(region: self.region)
        account_roles = sso_client.list_account_roles(
            access_token: token.access_token,
            account_id: self.account_id)
        role = account_roles.role_list.first
        role_creds = sso_client.get_role_credentials(
            role_name: role.role_name,
            account_id: role.account_id,
            access_token: token.access_token)
        Aws.config[:credentials] = Class.new do
            def initialize creds
                @creds = creds
            end
            def credentials
                Aws::Credentials.new(@creds.access_key_id, @creds.secret_access_key, @creds.session_token)
            end
        end.new(role_creds.role_credentials)
        true
    end
end

用法:抓住

Aws::Errors::InvalidSSOToken
时,拨打
SSOConfig.new("your-profile").try_renew_token
。调用成功返回后,
Aws.config[:credentials]
会加载凭据提供程序,该提供程序将返回正确的凭据。

担心:
  1. 我没有做太多测试,但我认为结果不会持久 - 我们可能应该在
    ~/.aws/sso/cache
    或其他东西中写入一些内容。
  2. 我希望有一种方法可以使用真正的
    CredentialProvider
    ,而不是这种奇怪的黑客。
  3. 除了我们可以读取配置的基本健全性检查外,没有错误检查 - 它会抛出而不是返回
    false

(我关闭了语法高亮,因为 StackOverflow 无法处理我的 Ruby 代码,而且颜色很乱)

© www.soinside.com 2019 - 2024. All rights reserved.