AWS Custom Federation Broker:调用联合身份验证终端错误400 python

时间:2019-02-14 11:31:23

标签: python amazon-web-services boto3 federated-identity aws-sts

我正在尝试创建一个URL,该URL使联盟用户可以在访问以下内容后访问AWS管理控制台 [官方文档] [1]。我将Cognito与[enhanced authflow] [2]结合使用,以便通过用户名和密码对用户进行身份验证。这是代码:

################## 1. LOGIN ####################

cognito = boto3.client('cognito-idp', aws_access_key_id='', aws_secret_access_key='')
response = cognito.initiate_auth(
        ClientId = app_client_id,
        AuthFlow = 'USER_PASSWORD_AUTH',
        AuthParameters = {
             "USERNAME": username,
             "PASSWORD": password
        },
        ClientMetadata = { 'UserPoolId': user_pool_id }
)

id_token = response['AuthenticationResult']['IdToken'] 

################## 2. GET ID ####################

cognito_identity = boto3.client('cognito-identity', aws_access_key_id='', aws_secret_access_key='', region_name=region)

response = cognito_identity.get_id(
        IdentityPoolId = identity_pool_id,
        Logins = {
                'cognito-idp.{}.amazonaws.com/{}'.format(region, user_pool_id) : id_token 
        }
)

identity_id = response['IdentityId']

################## 3. RETRIEVE CREDENTIALS ####################

response = cognito_identity.get_credentials_for_identity(
        IdentityId = identity_id,
        Logins = {
            'cognito-idp.{}.amazonaws.com/{}'.format(region, user_pool_id) : id_token 
        }
)

access_key_id = response['Credentials']['AccessKeyId']
secret_key = response['Credentials']['SecretKey']
session_token = response['Credentials']['SessionToken']

对于下一步(假设角色和呼叫联合端点),我不使用上面链接的官方文档中的示例,因为它使用的是boto而不是boto3。这是代码:

sts_boto_3 = boto3.client('sts',  aws_access_key_id = access_key_id, 
                                   aws_secret_access_key = secret_key, 
                                   aws_session_token = session_token, 
                                   region_name = region)

    response = sts_boto_3.assume_role(
            RoleArn = role,
            RoleSessionName = role_session_name,
    )
    session_id = response['Credentials']['AccessKeyId']
    session_key = response['Credentials']['SecretAccessKey']
    session_token = response['Credentials']['SessionToken']
    session_string =  '{{"sessioId" : "{}" , "sessionKey": "{}", "sessionToken" : "{}"}}'.format(session_id, session_key, session_token)

    req_url = 'https://signin.aws.amazon.com/federation?Action=getSigninToken&SessionDuration={}&Session={}'.format(3600, urllib.quote_plus(session_string))
    r = requests.get(req_url)
    print r

结果是

<Response [503]>

我怎么了?

[编辑] session_string没有错误(sessioId代替sessionId)

session_string =  '{{"sessionId" : "{}" , "sessionKey": "{}", "sessionToken" : "{}"}}'.format(session_id, session_key, session_token)

现在响应为400错误请求

<Response [400]>

1 个答案:

答案 0 :(得分:0)

我添加了一个完整的示例,说明如何设置凭证和构建URL,使联合用户可以直接访问GitHub上的AWS管理控制台。

以下是构成URL的代码的重要部分:

def construct_federated_url(assume_role_arn, session_name, issuer, sts_client):
    """
    Constructs a URL that gives federated users direct access to the AWS Management
    Console.
    1. Acquires temporary credentials from AWS Security Token Service (AWS STS) that
       can be used to assume a role with limited permissions.
    2. Uses the temporary credentials to request a sign-in token from the
       AWS federation endpoint.
    3. Builds a URL that can be used in a browser to navigate to the AWS federation
       endpoint, includes the sign-in token for authentication, and redirects to
       the AWS Management Console with permissions defined by the role that was
       specified in step 1.
    For more information, see Enabling Custom Identity Broker Access to the AWS Console
    [https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html]
    in the AWS Identity and Access Management User Guide.
    :param assume_role_arn: The role that specifies the permissions that are granted.
                            The current user must have permission to assume the role.
    :param session_name: The name for the STS session.
    :param issuer: The organization that issues the URL.
    :param sts_client: A Boto3 STS instance that can assume the role.
    :return: The federated URL.
    """
    response = sts_client.assume_role(
        RoleArn=assume_role_arn, RoleSessionName=session_name)
    temp_credentials = response['Credentials']
    print(f"Assumed role {assume_role_arn} and got temporary credentials.")

    session_data = {
        'sessionId': temp_credentials['AccessKeyId'],
        'sessionKey': temp_credentials['SecretAccessKey'],
        'sessionToken': temp_credentials['SessionToken']
    }
    aws_federated_signin_endpoint = 'https://signin.aws.amazon.com/federation'

    # Make a request to the AWS federation endpoint to get a sign-in token.
    # The requests.get function URL-encodes the parameters and builds the query string
    # before making the request.
    response = requests.get(
        aws_federated_signin_endpoint,
        params={
            'Action': 'getSigninToken',
            'SessionDuration': str(datetime.timedelta(hours=12).seconds),
            'Session': json.dumps(session_data)
        })
    signin_token = json.loads(response.text)
    print(f"Got a sign-in token from the AWS sign-in federation endpoint.")

    # Make a federated URL that can be used to sign into the AWS Management Console.
    query_string = urllib.parse.urlencode({
        'Action': 'login',
        'Issuer': issuer,
        'Destination': 'https://console.aws.amazon.com/',
        'SigninToken': signin_token['SigninToken']
    })
    federated_url = f'{aws_federated_signin_endpoint}?{query_string}'
    return federated_url