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:
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.
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.