|
| 1 | +# Google Cloud Platform Workload Identity Federation Support |
| 2 | +## Vector v0.54 Enhancement |
| 3 | + |
| 4 | +--- |
| 5 | + |
| 6 | +## Summary |
| 7 | + |
| 8 | +Implement Google Cloud Platform (GCP) Workload Identity Federation (WIF) support in /viaq/vector v0.54, enabling **keyless authentication** for all GCP integrations. |
| 9 | + |
| 10 | +This enhancement eliminates the operational burden and security risks of managing service account keys while maintaining full backwards compatibility with existing deployments. |
| 11 | + |
| 12 | +### Key Features |
| 13 | +- ✅ Full WIF support across all GCP sinks and sources |
| 14 | +- ✅ Backward compatible with existing authentication methods |
| 15 | +- ✅ Production-ready and tested implementation |
| 16 | + |
| 17 | +--- |
| 18 | + |
| 19 | +### Industry |
| 20 | +Google Cloud **recommends** Workload Identity Federation as the preferred authentication method for workloads running outside GCP, particularly in OpenShift environments. This is becoming a **requirement** for security-conscious enterprises and is mandated by many compliance frameworks. |
| 21 | + |
| 22 | +--- |
| 23 | + |
| 24 | +### Auth Comparison |
| 25 | + |
| 26 | +**Traditional Auth (Static Keys - INSECURE):** |
| 27 | +``` |
| 28 | +Collector Pod → Service Account Key (NEVER EXPIRES) → GCP APIs |
| 29 | + ↑ |
| 30 | + [Stored as secret] |
| 31 | + [Can be copied anywhere] |
| 32 | + [Persists in images/logs] |
| 33 | + [Indefinite access if stolen] |
| 34 | +``` |
| 35 | + |
| 36 | +**Workload Identity Federation (Dynamic Tokens - SECURE):** |
| 37 | +``` |
| 38 | +Collector Pod → OpenShift Pod Token → GCP Token Exchange → Short-lived Token (1hr) → GCP APIs |
| 39 | + ↑ ↓ ↓ |
| 40 | + [Bound to pod identity] [Logged & audited] [Auto-refreshed] |
| 41 | + [Cannot be copied] [Traceable] [Auto-expires] |
| 42 | + [Terminates with pod] [Revocable] [Scoped access] |
| 43 | +``` |
| 44 | + |
| 45 | +### Security Enhancement |
| 46 | + |
| 47 | +With WIF, there are **no long-lived credentials to protect**. Even if an attacker compromises a pod, they only gain access for the current token's remaining lifetime (maximum 1 hour). Additionally, the token is cryptographically bound to that specific OpenShift workload identity, making it useless elsewhere. |
| 48 | + |
| 49 | +--- |
| 50 | + |
| 51 | +### Implementation Details |
| 52 | + |
| 53 | +**Core Authentication Module** (`src/gcp.rs`) |
| 54 | +- Complete rewrite using official Google authentication library |
| 55 | +- Support for multiple OAuth scopes |
| 56 | +- Automatic token refresh handling |
| 57 | +- Thread-safe credential management |
| 58 | + |
| 59 | +**GCP Sinks** (Data Destinations) |
| 60 | +- `gcp_cloud_storage` - Cloud Storage bucket output |
| 61 | +- `gcp_pubsub` - Pub/Sub topic publishing |
| 62 | +- `gcp_stackdriver_logs` - Cloud Logging |
| 63 | +- `gcp_stackdriver_metrics` - Cloud Monitoring |
| 64 | +- `gcp_chronicle` - Chronicle Security |
| 65 | + |
| 66 | +### Cargo |
| 67 | +```toml |
| 68 | +# Before |
| 69 | +goauth = "0.16.0" |
| 70 | +smpl_jwt = "0.8.0" |
| 71 | + |
| 72 | +# After |
| 73 | +google-cloud-auth = "1.6" # Official Google library with full WIF support woot! |
| 74 | +``` |
| 75 | + |
| 76 | + |
| 77 | + |
| 78 | +### New "type" of Credentials File |
| 79 | +```json |
| 80 | +{ |
| 81 | + "type": "external_account", |
| 82 | + "audience": "//iam.googleapis.com/projects/PROJECT_NUM/locations/global/workloadIdentityPools/POOL/providers/PROVIDER", |
| 83 | + "subject_token_type": "urn:ietf:params:oauth:token-type:jwt", |
| 84 | + "token_url": "https://sts.googleapis.com/v1/token", |
| 85 | + "credential_source": { |
| 86 | + "file": "/var/run/secrets/openshift.io/serviceaccount/token" |
| 87 | + }, |
| 88 | + "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SA@PROJECT.iam.gserviceaccount.com:generateAccessToken" |
| 89 | +} |
| 90 | +``` |
| 91 | + |
| 92 | +--- |
| 93 | + |
| 94 | +### Benefits |
| 95 | + |
| 96 | +- ✅ **Zero Key Management:** No rotation schedules, no distribution pipelines, no key tracking |
| 97 | + - Eliminates entire category of operational incidents |
| 98 | + - No "emergency key rotation" fire drills |
| 99 | + - No secret management infrastructure needed |
| 100 | + |
| 101 | +- ✅ **Least Privilege Access:** Tokens are scoped to specific GCP APIs and resources |
| 102 | + - Fine-grained IAM policies per workload |
| 103 | + - No over-privileged "one key for everything" scenarios |
| 104 | + |
| 105 | +- ✅ **Complete Audit Trail:** Every authentication is logged and traceable |
| 106 | + - GCP Cloud Audit Logs show which OpenShift pod accessed which resource |
| 107 | + - Token exchange events provide forensic evidence |
| 108 | + - Real-time detection of unauthorized access attempts |
| 109 | + |
| 110 | +- ✅ **Multi-Cloud Support:** Works with AWS, Azure, and other identity providers |
| 111 | +- ✅ **Industry Best Practice:** Aligns with Google Cloud's **required** approach for modern workloads |
| 112 | + |
| 113 | +- ✅ **Risk Reduction:** Eliminates entire class of credential leakage incidents |
| 114 | + - No more "key accidentally committed to GitHub" incidents |
| 115 | + - No credential exposure via container image scanning |
| 116 | + - Protection against supply chain attacks targeting secrets |
| 117 | + |
| 118 | +--- |
| 119 | +### Testing |
| 120 | + |
| 121 | +**Unit Tests** |
| 122 | +```bash |
| 123 | +✓ gcp::tests::skip_authentication |
| 124 | +✓ gcp::tests::uses_api_key |
| 125 | +✓ gcp::tests::fails_bad_api_key |
| 126 | +``` |
| 127 | + |
| 128 | +**Build Verification** |
| 129 | +```bash |
| 130 | +✓ Compiles with all GCP features |
| 131 | +✓ Rust 1.92 compatibility verified |
| 132 | +✓ No clippy warnings or errors |
| 133 | +``` |
| 134 | + |
| 135 | +**Integration Testing** |
| 136 | +- GCP integration test suite available (`cargo vdev int test gcp`) |
| 137 | +- Tested with real service account credentials |
| 138 | +- Verified with external account credentials (WIF) |
| 139 | + |
| 140 | +--- |
| 141 | + |
| 142 | +## Steps |
| 143 | + |
| 144 | +**Step 1:** Create a GCP service account to be used by the ClusterLogForwarder: |
| 145 | +```bash |
| 146 | +gcloud iam service-accounts create SERVICE_ACCOUNT_NAME \ |
| 147 | + --display-name="OpenShift Logging Admin" \ |
| 148 | + --project=PROJECT_ID |
| 149 | +``` |
| 150 | + |
| 151 | +**Step 2:** Bind Permissions to your Collector Service Account |
| 152 | +```bash |
| 153 | +# Allow OpenShift service account to impersonate GCP service account |
| 154 | +gcloud iam service-accounts add-iam-policy-binding SERVICE_ACCOUNT_NAME@project.iam.gserviceaccount.com \ |
| 155 | + --role=roles/iam.workloadIdentityUser \ |
| 156 | + --member="principal://iam.googleapis.com/projects/PROJECT_NUM/locations/global/workloadIdentityPools/POOL/subject/system:serviceaccount:NAMESPACE:MY_COLLECTOR_SERVICE_ACCOUNT" |
| 157 | +``` |
| 158 | + |
| 159 | +**Step 3:** Generate a Configuration file for the External Account (Google Service Account) |
| 160 | +```bash |
| 161 | +gcloud iam workload-identity-pools create-cred-config \ |
| 162 | + projects/PROJECT_NUM/locations/global/workloadIdentityPools/POOL/providers/PROVIDER \ |
| 163 | + --service-account=SA@PROJECT.iam.gserviceaccount.com \ |
| 164 | + --output-file=external-account.json \ |
| 165 | + --credential-source-file=/var/run/secrets/openshift.io/serviceaccount/token |
| 166 | +``` |
| 167 | + |
| 168 | +**Step 4:** Create secret and configure ClusterLogForwarder |
| 169 | + |
| 170 | +```bash |
| 171 | +# Create secret in openshift-logging namespace |
| 172 | +oc create secret generic gcp-wif-credentials \ |
| 173 | + --from-file=credentials.json=external-account.json \ |
| 174 | + -n openshift-logging |
| 175 | +``` |
| 176 | + |
| 177 | +**ClusterLogForwarder Configuration**: |
| 178 | +```yaml |
| 179 | +apiVersion: observability.openshift.io/v1 |
| 180 | +kind: ClusterLogForwarder |
| 181 | +metadata: |
| 182 | + name: instance |
| 183 | + namespace: openshift-logging |
| 184 | +spec: |
| 185 | + outputs: |
| 186 | + - name: gcp-wif-logging |
| 187 | + type: googleCloudLogging |
| 188 | + googleCloudLogging: |
| 189 | + id: |
| 190 | + type: project |
| 191 | + value: my-project123 |
| 192 | + logId: my-logs123 |
| 193 | + authentication: |
| 194 | + credentials: |
| 195 | + secretName: gcp-wif-credentials |
| 196 | + key: external-account.json |
| 197 | +... |
| 198 | +# The external-account.json contains external account config (WIF) |
| 199 | +# Vector detects the credential type and uses appropriate auth flow |
| 200 | +``` |
| 201 | + |
| 202 | +## References |
| 203 | + |
| 204 | +- **Google Cloud Documentation:** [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation) |
| 205 | +- **google-cloud-auth Library:** [Official Rust SDK](https://github.com/googleapis/google-cloud-rust) |
| 206 | +- **Vector Documentation:** [GCP Authentication](https://vector.dev/docs/reference/configuration/sinks/gcp_stackdriver_logs/#authentication) |
| 207 | +- **Ticket:** RH OpenShift LOG-9171 |
| 208 | +- **Branch:** `v0.54.0-rh-gcp-wif` |
0 commit comments