Skip to content

Commit cdaaa5d

Browse files
committed
LOG-9171: Add GCP WIF support
1 parent b2e58e8 commit cdaaa5d

10 files changed

Lines changed: 827 additions & 270 deletions

File tree

Cargo.lock

Lines changed: 473 additions & 79 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,10 @@ prost = { workspace = true, optional = true }
331331
prost-reflect = { workspace = true, optional = true }
332332
prost-types = { workspace = true, optional = true }
333333

334-
# GCP
335-
goauth = { version = "0.16.0", optional = true }
336-
smpl_jwt = { version = "0.8.0", default-features = false, optional = true }
334+
# GCP - using official googleapis/google-cloud-rust authentication library
335+
# Supports service accounts, external accounts (workload identity), and ADC
336+
# Version 1.6 required for full external account support
337+
google-cloud-auth = { version = "1.6", optional = true }
337338

338339
# AMQP
339340
lapin = { version = "2.5.3", default-features = false, features = ["native-tls"], optional = true }
@@ -640,7 +641,7 @@ aws-core = [
640641
# Anything that requires Protocol Buffers.
641642
protobuf-build = ["dep:tonic-build", "dep:prost-build"]
642643

643-
gcp = ["dep:base64", "dep:goauth", "dep:smpl_jwt"]
644+
gcp = ["dep:base64", "dep:google-cloud-auth"]
644645

645646
# Enrichment Tables
646647
enrichment-tables = ["enrichment-tables-geoip", "enrichment-tables-mmdb", "enrichment-tables-memory"]
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
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

Comments
 (0)