Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/shrikant0013/gcp-aws-webidentityfederation
AWS Auth using WebIdentityFederation from Google Cloud
https://github.com/shrikant0013/gcp-aws-webidentityfederation
aws gcp gcp-appengine-flex gcp-appengine-std jwt oauth2 openid-connect sts
Last synced: 12 days ago
JSON representation
AWS Auth using WebIdentityFederation from Google Cloud
- Host: GitHub
- URL: https://github.com/shrikant0013/gcp-aws-webidentityfederation
- Owner: shrikant0013
- License: mit
- Created: 2018-08-30T16:22:43.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2024-04-16T23:51:22.000Z (7 months ago)
- Last Synced: 2024-08-01T17:38:43.664Z (3 months ago)
- Topics: aws, gcp, gcp-appengine-flex, gcp-appengine-std, jwt, oauth2, openid-connect, sts
- Language: Python
- Size: 531 KB
- Stars: 15
- Watchers: 4
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Google Cloud to AWS authentication using Web Identity Federation
This sample shows how to make authenticated calls to AWS APIs from Google Cloud
![interaction diagram](docs/images/interaction-diagram.png)
> Note in above picture S3 is just example service. You can call any AWS API that supports auth based on AWS STS credentials.
> In GCP KMS, Datastore, Memcache are just shown for illustration purpose to suggest caching credentials in case of high QPS services.## Why use Web Identity Federation
* Based on OpenID Connect open standard## Use cases
* Securely call AWS APIs from outside AWS environment like Google Cloud or your data center.## Google Cloud to AWS Federation
1. Create a signed JWT using your system’s service account keys. This can be local operation or using Google Cloud signJWT API call (in case of GCP managed keys)
```json
{
"iss": "",
"aud": "https://www.googleapis.com/oauth2/v4/token",
"target_audience": "",
"iat": "now",
"exp": "<1 hour or some expiry, AWS allows max 1 hour>"
}
```
2. Make call to "https://www.googleapis.com/oauth2/v4/token" to exchange above token for Google signed token
```json
data = {
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": ""
}
```
3. Google should return you JWT which should look something like:
```json
{
"aud": "",
"iss": "https://accounts.google.com",
"email_verified": true,
"exp": 1535578337,
"azp": "",
"iat": 1535574737,
"email": "",
"sub": "99992499378790129023"
}
```
4. Make AWS STS WebIdentityFederation API call to retrieve temporary credentials
"https://sts.amazonaws.com/?DurationSeconds={DURATION}&Action=AssumeRoleWithWebIdentity&Version=2011-06-15&RoleSessionName={ROLE_SESSION}&RoleArn={ROLE_ARN}&WebIdentityToken={OPENIDTOKEN}"Where
* ROLE_SESSION = Temporary identifier for this session. Helps in tracking when analyzing Cloudtrail events
* ROLE_ARN = ARN role created in setup step 2 above
* OPENIDTOKEN = Signed Token received from Google in prior stepYou get AWS temporary credentials from above call that can be used to make signed requests to AWS
```xml
something-id
something-key
something-something
2017-12-22T04:02:22Z
```## Environment for Sample to Work
* This example should work on Google Cloud Appengine Standard/Flex
* You can also try out locally.## Prerequites
* Python 2.7 (should be easy to port to Python3)
* Python virtual environment
* Identity of your Google Cloud environment, service account should have `roles/iam.serviceAccountTokenCreator`
* Make note of Google account service account email, example `[email protected]`
* Make note of target audience in your AWS environment. This could be any string in URI format, example `https://.`### For running Google Cloud commands
* [Google Cloud SDK](https://cloud.google.com/sdk/) is installed and `gcloud` commands work## Setup
### AWS role setup
1. In your AWS account, create role wizard, choose `Web Identity` and from `Choose a web identity provider`, select `Google` as `Identity Provider`
![create-role-google-identity](docs/images/create-role-google-identity.png)2. For `Audience` field enter the Google Cloud environment's service account
3. Complete role creation, add role permissions as you wish
4. Edit `trust relationship` and add `oaud` condition as well as null checks.
5. Your trust policy should look something like below```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "accounts.google.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"accounts.google.com:oaud": "https://myservice.aud.my-corp.net",
"accounts.google.com:aud": "[email protected]"
},
"Null": {
"accounts.google.com:oaud": "false",
"accounts.google.com:aud": "false"
}
}
}
]
}
```
![aws-trust-policy](docs/images/aws-trust-policy.png)6. Make note of role arn `arn:aws:iam:::role/`
## To run the sample locally
Install python dependencies
```bash
pip install -r requirements.txt
```Setup required environment variables
```bash
export TARGET_AUDIENCE="https://."
```
`TARGET_AUDIENCE` should in URI format, example `https://myservice.aud.my-corp.net````bash
export AWS_ROLE_ARN="arn:aws:iam:::role/"
```If you are running locally, make sure you have activated your service account or google account correctly, you can do one of the following
* [gcloud auth activate-service-account](https://cloud.google.com/sdk/gcloud/reference/auth/activate-service-account) (Recommended)
* created service account keys and export environment variable
```bash
export GOOGLE_APPLICATION_CREDENTIALS=
```> Note: Creating service account keys is not recommended best practice. This approach should only be used in local test environment. Your test service account should have only least privileges
## To run the sample on Google Cloud Appengine Standard
Install python dependencies in vendored `lib` directory
```bash
pip install -r requirements.txt -t lib
```#### Deploy to Google Cloud
Ensure [app-std.yaml](app-std.yaml) have `TARGET_AUDIENCE` and `AWS_ROLE_ARN` correctly set under `env_variables:` section```bash
gcloud app deploy app-std.yaml --project
```> Since you are running on appengine make sure you have correctly setup `aud` in the AWS role above. Generally GAE AppEngine has service account of format `[email protected]`
## To run the sample on Google Cloud Appengine Flexible
#### Local deploy
```bash
python main.py
```
Visit `http://127.0.0.1:8080`> Note you would need `GOOGLE_APPLICATION_CREDENTIALS` environment for local environment to work
#### Deploy to Google Cloud
Ensure [app-flex.yaml](app-flex.yaml) have `TARGET_AUDIENCE` and `AWS_ROLE_ARN` correctly set under `env_variables:` section```bash
gcloud app deploy app-flex.yaml --project
```