GoogleCloudPlatform / cloud-sql-proxy

A utility for connecting securely to your Cloud SQL instances
Apache License 2.0
1.28k stars 349 forks source link

Support Workload Identity Federation #1096

Closed j0hnsmith closed 2 years ago

j0hnsmith commented 2 years ago

Feature Description

I tried using this in a github action that uses WIF to run as a service account, I got an auth error. I then used export_default_credentials and it worked (no other changes).

Additional Context

As suggested in https://github.com/GoogleCloudPlatform/cloudsql-proxy/issues/1006#issuecomment-985001107, I'm 99% sure that if you update the deps that provide the auth functionality to this tool to the latest version, auth via WIF will work.

enocom commented 2 years ago

Thanks for the request @j0hnsmith. I'd like to see this work more smoothly now that WIF is being used more frequently. I'll look into what the technical issue is and report back.

enocom commented 2 years ago

So here's what I did. Adding all the steps in case others want to try the same.

  1. Created a pool:
gcloud iam workload-identity-pools create "my-pool" \
  --location="global" \
  --display-name="Demo pool"
  1. Created an OIDC provider for GitHub:
gcloud iam workload-identity-pools providers create-oidc "my-provider" \
  --location="global" \
  --workload-identity-pool="my-pool" \
  --display-name="Demo provider" \
  --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.aud=assertion.aud,attribute.repository=assertion.repository" \
  --issuer-uri="https://token.actions.githubusercontent.com"
  1. Added an IAM binding to allow the pool to assume the SA identity:
# EDIT: This command is wrong. See below for the right command.
gcloud iam service-accounts \
    add-iam-policy-binding "workload-identity@<project-id>.iam.gserviceaccount.com" \
    --role="roles/iam.workloadIdentityUser" \
    --member="principalSet://iam.googleapis.com/projects/<project-number>/locations/global/workloadIdentityPools/my-pool/attribute.repository/<github-org>/<github-repo>"

And then here's my action.

name: check
on: [push]

jobs:
  check:
    name: "check wif"
    runs-on: "ubuntu-latest"
    permissions:
      contents: 'read'
      id-token: 'write'
    steps:
    - uses: 'actions/checkout@v2'
    - id: 'auth'
      name: 'Authenticate to Google Cloud'
      uses: 'google-github-actions/auth@v0.4.0'
      with:
        workload_identity_provider: 'projects/<project-number>/locations/global/workloadIdentityPools/my-pool/providers/my-provider'
        service_account: 'workload-identity@<project-id>.iam.gserviceaccount.com'

    - name: 'Set up Cloud SDK'
      uses: 'google-github-actions/setup-gcloud@v0'

    - name: 'Use gcloud CLI'
      run: 'gcloud info'

    - name: "print env"
      run: "env | sort"

   - name: start proxy                                                                                                        
      run: |                                                                                                                   
        wget "https://storage.googleapis.com/cloudsql-proxy/v1.28.1/cloud_sql_proxy.linux.amd64" -O cloud_sql_proxy            
        chmod +x ./cloud_sql_proxy                                                                                             
        ./cloud_sql_proxy -instances=<project-id>:us-central1:<instance-name>=tcp:5432 &                                       
        echo $! > pid.file                                                                                                     
        sleep 60                                                                                                               
        kill $(cat pid.file)

From the output, I can see that GOOGLE_APPLICATION_CREDENTIALS is correctly populated and that it works (gcloud info reports correctly). Further, the proxy will use a provided 1) credentials file, 2) token, and then 3) try to use GOOGLE_APPLICATION_CREDENTIALS (source).

The proxy then fails with this error:

2022/02/09 21:21:24 current FDs rlimit set to 65536, wanted limit is 8500. Nothing to do here.
2022/02/09 21:21:24 using credential file for authentication; path="/home/runner/work/_temp/8a2ab4ef9b265c5ad0042ac8"
2022/02/09 21:21:25 errors parsing config:
    Get "https://sqladmin.googleapis.com/sql/v1beta4/projects/<project>/instances/us-central1~<instance-name>/connectSettings?alt=json&prettyPrint=false": oauth2/google: status code 403: {
  "error": {
    "code": 403,
    "message": "The caller does not have permission",
    "status": "PERMISSION_DENIED"
  }
}

This looks like an OAuth2 scope problem, as the proxy is picking up the correct GOOGLE_APPLICATION_CREDENTIALS.

EDIT:

I had a mismatch between the attributes and the IAM binding. A working binding is:

gcloud iam service-accounts \
    add-iam-policy-binding "workload-identity@<project-id>.iam.gserviceaccount.com" \
    --role="roles/iam.workloadIdentityUser" \
    --member="principalSet://iam.googleapis.com/projects/<project-number>/locations/global/workloadIdentityPools/my-pool/attribute.repository/<github-org>/<github-repo>"

But the best way to configure WIF is to just use the Terraform module and avoid all these headaches.

enocom commented 2 years ago

This seems useful: https://github.com/google-github-actions/auth/blob/main/docs/TROUBLESHOOTING.md.

In short, I think the proxy already supports WIF, but I haven't been able to prove it myself given how hard it is to set up WIF correctly.

enocom commented 2 years ago

So after some more investigation, I found I had a mismatch between the attributes I was mapping from the OIDC token and the associated principalSet in the IAM binding with my service account. See above for details.

In short, because the proxy already supports application default credentials, it does work with WIF. You're likely having a problem with your WIF configuration. I'm going to close this, but if you'd like to share the error you're seeing, I can provide some pointers about what worked for me.

j0hnsmith commented 2 years ago

@enocom I appreciate the lengths you went to in order to reproduce. I tried again with a simplified action based on yours and it worked. I apologise for wasting your time.

enocom commented 2 years ago

Glad to hear it. WIF is hard.