1

I am investigating if a hybrid AWS/Google Cloud infrastructure system is possible and one of the requirements I have is secure and simple authentication from one system to the other. Currently I need to connect to a restricted AWS S3 bucket from a Google Cloud VM instance.

My question is generally: Is there a way to do that at all and what would be the best approach towards that. I am sure everyone wants to have the opportunity to use multiple Cloud providers for their infrastructure with high security and ease of use and maintenance.

After some research I found that the only way that looks possible is through Web Identity Federation which is not designed for that purpose at all. Then after exploring the options from the Google's side, I found that service accounts look like they could be used to do the OAuth2 authentication and provide a token to access AWS through an STS client with the AssumeRoleWithWebIdentity action.

However, the STS client accepts only id_token which usually the client will get from the server if they log in to Google from an application that runs in their browser (Javascript, PHP, Python) while I am trying to do that from the system level with the Ruby SDKs. Currently the Google::Auth authorization object returns an access token which is not accepted by the Aws::STS::Client. I am trying to do something like that:

require 'aws-sdk'
require 'googleauth'

scopes =  ['https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/compute']
authorization = Google::Auth.get_application_default(scopes)
token = authorization.fetch_access_token!['access_token']
bucket_name  = 'xxx'
arn_role     = 'arn:aws:iam::xxx:role/xxx'
session_name = 'GoogleApps'
client = Aws::STS::Client.new(region: 'us_east-1')
resp = client.assume_role_with_web_identity({
  role_arn: arn_role,
  role_session_name: session_name,
  web_identity_token: token
})

As mentioned the fetch_access_token! is the only method that returns anything meaningful. There is a method that is supposed to return exactly what I need - decoded_id_token; however, it is null in that case. Running the code above results (as expected) in the following error:

The ID Token provided is not a valid JWT. (You may see this error if you sent an Access Token) (Aws::STS::Errors::InvalidIdentityToken)

I tried to find a way to authenticate with the service account as if I am performing a normal Google Sign In in order to obtain an id_token but without any success.

I have several other options to perform the same task that are less elegant than using that particular type of federation:

  • Creating an IAM account for the purpose and distributing the security credentials with a secure system like Hashicorp's Vault.
  • Using a mediator "jump" instance inside AWS which has access to the necessary resouce and can be ssh'd from the particular static external IPs of the VMs in Google Cloud.
  • Using a simple system that would generate externalIds to create access tokens ourselves and use that type of federation.

I don't mind using any technology to get the server-to-server(more like server-to-service but same holds true for server as well) federated authentication in a clean and secure way.

Sorry for the long questions and thanks in advance.

  • Are you missing a step? Maybe you need to use the token in hand to make an API call to request a JWT ID token, and then pass that JWT into STS AssumeRoleWithWebIdentity. Plus the assumed role needs to be created specifically for identity provider access (the IdP must be specified in the assumed IAM role's trust policy). – jarmod Mar 31 '16 at 14:30
  • @jarmod thanks for replying. I have the AWS IAM side set up as per the documentation for Web Identity Federation but it throws an error before hitting that code. The exact problem I have is that the request for JWT ID is null with the way I am trying to authenticate with the Google service account. I tried calling authorization.decoded_id_token but it is null. I just noticed that by calling get_application_default I am actually getting a GCE authorization which might not be what I want. – Stoyan Ivanov Mar 31 '16 at 15:13

2 Answers2

1

I know it quite a bit late for reply this thread since it 3 yrs old but for this error

The ID Token provided is not a valid JWT

what I found on my issues is firebase authentication return 2 token which is accessToken and idToken and you need to use "idToken" instead

  • more information you can view source code here https://www.javatips.net/api/eucalyptus-master/clc/modules/tokens/src/main/java/com/eucalyptus/tokens/TokensService.java and search for "The ID Token provided is not a valid JWT" then you will see that when it parse our token it will split with 3 dots which is idToken not acccess_token – Howtoautomate.in.th Jul 06 '20 at 11:30
0

We ended up not going that route due to priorities shift. The solution we chose, for when we want to do it, was Hashicorp's Vault to do the middleman API key exchange. It is secure enough and is relatively easy to implement and integrate. It also has the added benefit of giving your AWS account the ability to interact with other unsupported things via API.