Metadata-Version: 2.4
Name: eks-gcp-wif
Version: 0.1.0
Summary: EKS to GCP authentication via Workload Identity Federation
Home-page: https://github.com/yourusername/eks-gcp-wif
Author: Sajal Bera
Author-email: sajal.bera@nielsen.com
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: boto3>=1.26.0
Requires-Dist: google-auth>=2.16.0
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# EKS Pod to GCP Authentication via Workload Identity Federation

This project demonstrates how to authenticate from an AWS EKS pod to Google Cloud Platform (GCP) services using Workload Identity Federation (WIF), without requiring GCP service account keys.

## What Does This Code Do?

This application runs in an EKS pod and updates a Google Sheet by:
1. Using the EKS pod's IAM role credentials
2. Exchanging those AWS credentials for GCP tokens via Workload Identity Federation
3. Impersonating a GCP service account
4. Making authenticated requests to Google Sheets API

All credentials automatically refresh when expired, making it suitable for long-running applications.

## Authentication Flow

```
┌─────────────────┐
│   EKS Pod       │
│   (IAM Role)    │
└────────┬────────┘
         │ 1. AWS credentials (auto-refresh)
         ▼
┌─────────────────────────┐
│ EKSCredentialSupplier   │
│ (boto3.Session)         │
└────────┬────────────────┘
         │ 2. Exchange via WIF
         ▼
┌─────────────────────────┐
│ GCP STS Token Service   │
│ (sts.googleapis.com)    │
└────────┬────────────────┘
         │ 3. Federated token
         ▼
┌─────────────────────────┐
│ Service Account         │
│ Impersonation           │
└────────┬────────────────┘
         │ 4. Access token
         ▼
┌─────────────────────────┐
│ Google Sheets API       │
└─────────────────────────┘
```

**Step-by-step:**
1. EKS pod IAM role provides AWS credentials (automatically refreshed by boto3)
2. AWS credentials are exchanged for a GCP federated token via Workload Identity Federation
3. Federated token is used to impersonate a GCP service account
4. Service account token is used to access Google APIs
5. All tokens automatically refresh when expired

## Prerequisites

### GCP Setup
1. Create a Workload Identity Pool and Provider configured for AWS
2. Create a GCP service account with necessary permissions
3. Grant the Workload Identity Pool permission to impersonate the service account
4. Share Google Sheet with the service account email

### AWS Setup
1. EKS cluster with IRSA (IAM Roles for Service Accounts) enabled
2. IAM role with trust policy for the EKS service account
3. Kubernetes service account annotated with the IAM role ARN

### Environment Variables
```bash
GCP_PROJECT_NUMBER=123456789
GCP_WIF_POOL_ID=my-pool
GCP_WIF_PROVIDER_ID=my-provider
GCP_SERVICE_ACCOUNT=my-sa@project.iam.gserviceaccount.com
AWS_REGION=us-east-1
```

## How to Use

### 1. Install Dependencies
```bash
pip install boto3 google-auth google-auth-httplib2
```

### 2. Configure Environment
Set environment variables or update `config.py`:
```python
GCP_PROJECT_NUMBER = "123456789"
WORKLOAD_IDENTITY_POOL = "my-pool"
WORKLOAD_IDENTITY_PROVIDER = "my-provider"
SERVICE_ACCOUNT_EMAIL = "my-sa@project.iam.gserviceaccount.com"
DOCUMENT_ID = "your-google-sheet-id"
```

### 3. Deploy to EKS
```bash
kubectl apply -f pod.yaml
```

### 4. Run
```bash
python main.py
```

## Core Code for WIF Integration

To integrate WIF authentication into your own codebase, copy these essential components:

### Required Imports
```python
import os
import boto3
from google.auth import aws, impersonated_credentials
from google.auth.transport.requests import AuthorizedSession
```

### EKSCredentialSupplier Class
```python
class EKSCredentialSupplier(aws.AwsSecurityCredentialsSupplier):
    """Supplies AWS credentials from EKS pod IAM role."""
    
    def __init__(self, region=None):
        self._session = boto3.Session()
        self._region = region or os.getenv("AWS_REGION", "us-east-1")
    
    def get_aws_security_credentials(self, context, request):
        credentials = self._session.get_credentials()
        return aws.AwsSecurityCredentials(
            access_key_id=credentials.access_key,
            secret_access_key=credentials.secret_key,
            session_token=credentials.token
        )
    
    def get_aws_region(self, context, request):
        return self._region
```

### Credential Setup Function
```python
def get_wif_credentials():
    """Get credentials using Workload Identity Federation."""
    project_number = os.getenv("GCP_PROJECT_NUMBER")
    pool_id = os.getenv("GCP_WIF_POOL_ID")
    provider_id = os.getenv("GCP_WIF_PROVIDER_ID")
    service_account = os.getenv("GCP_SERVICE_ACCOUNT")
    aws_region = os.getenv("AWS_REGION", "us-east-1")
    
    audience = f"//iam.googleapis.com/projects/{project_number}/locations/global/workloadIdentityPools/{pool_id}/providers/{provider_id}"
    credential_supplier = EKSCredentialSupplier(region=aws_region)
    
    # Adjust scopes based on your needs
    scopes = ["https://www.googleapis.com/auth/cloud-platform"]
    
    credentials = aws.Credentials(
        audience=audience,
        subject_token_type="urn:ietf:params:aws:token-type:aws4_request",
        token_url="https://sts.googleapis.com/v1/token",
        aws_security_credentials_supplier=credential_supplier,
        scopes=scopes
    )
    
    if service_account:
        credentials = impersonated_credentials.Credentials(
            source_credentials=credentials,
            target_principal=service_account,
            target_scopes=scopes
        )
    
    return credentials
```

### Initialize Session
```python
credentials = get_wif_credentials()
authed_session = AuthorizedSession(credentials)

# Use authed_session for all GCP API calls
response = authed_session.get("https://www.googleapis.com/...")
```

## Key Features

- **No Service Account Keys**: Uses Workload Identity Federation instead of storing GCP credentials
- **Automatic Credential Refresh**: Both AWS and GCP credentials refresh automatically
- **Long-Running Support**: Suitable for long-running applications in EKS
- **Secure**: Leverages EKS pod IAM roles and GCP's federated identity

## Common Scopes

```python
# Google Sheets
["https://www.googleapis.com/auth/spreadsheets"]

# Google Drive (read-only)
["https://www.googleapis.com/auth/drive.readonly"]

# All Google Cloud APIs
["https://www.googleapis.com/auth/cloud-platform"]

# Multiple scopes
["https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive.readonly"]
```

## Troubleshooting

**403 Error: "Request had insufficient authentication scopes"**
- Add the required scope to the `scopes` list

**403 Error: Permission denied on Google Sheet**
- Share the sheet with the GCP service account email

**Authentication fails**
- Verify Workload Identity Pool configuration
- Check IAM role trust policy for EKS service account
- Ensure service account has impersonation permissions
