feat(provider): Add Google IAP authentication support#456
feat(provider): Add Google IAP authentication support#456Aaron ("AJ") Steers (aaronsteers) wants to merge 8 commits into
Conversation
This adds support for authenticating with Airbyte instances hosted behind
Google Cloud Identity-Aware Proxy (IAP).
New provider attributes:
- google_iap_service_account_key: Google Service Account JSON key (content or file path)
- google_iap_client_id: OAuth2 Client ID configured for IAP
Features:
- Automatic IAP token generation using Service Account credentials
- Token caching with automatic refresh before expiration
- Transparent header injection for all API requests
Usage:
```hcl
provider "airbyte" {
server_url = "https://your-airbyte.example.com/api/v1"
google_iap_service_account_key = file("path/to/service-account.json")
google_iap_client_id = "123456789-abc.apps.googleusercontent.com"
}
```
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…s set When bearer_auth is configured, BasicAuth with empty credentials was incorrectly overwriting the Authorization header. This caused "Invalid IAP credentials: empty token" errors. Now BasicAuth is only initialized when: 1. bearerAuth is not set, AND 2. username or password is provided Fixes #198 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: AJ Steers <aj@airbyte.io>
Rework the IAP authentication integration to survive Speakeasy code regeneration: - Add scripts/patch_iap_auth.py: patches provider.go and utils.go after generation to add IAP schema attrs, model fields, and transport config - Keep google_iap.go as a standalone non-generated file (token manager) - Update poe_tasks.toml to run the IAP patch in post-generate pipeline - Normalize field alignment to match Speakeasy's generated style The bearer_auth overwrite fix (issue #198) is now handled correctly by the current generated code (BasicAuth is only set when credentials are provided), so no additional patch is needed for that. Closes #207 Closes #198 Co-Authored-By: AJ Steers <aj@airbyte.io>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Thanks for opening this pull request!Your contribution is appreciated. Here are some helpful tips and resources. 💡 Show Tips and TricksTerraform Example Commands
Pre-Release Commands
Pre-releases are published to the Terraform Registry but are not the default version. See CONTRIBUTING.md — Pre-Release Process for details. 📚 Show Repo GuidanceAbout This RepositoryThis repository uses Speakeasy to generate the Terraform provider from the Airbyte OpenAPI specification. The CI will automatically build the provider, validate code generation, and run acceptance tests across Terraform versions 1.0-1.4. Note: This is a generated codebase. Direct modifications to generated files are not accepted - changes must be made to the upstream OpenAPI spec. |
|
Generated Code Drift Detected The committed code does not match what the generation pipeline produces. This usually means a generated file was edited by hand or the generation pipeline needs to be re-run. To fix: Comment To debug locally: Download the generated artifacts and diff them against your committed code: gh run download 26859015259 --name generated_provider_code --dir /tmp/generated_from_ci
diff -rq internal/provider/ /tmp/generated_from_ci/provider/
diff -rq --exclude=.gitattributes --exclude=.gitignore internal/sdk/ /tmp/generated_from_ci/sdk/See CONTRIBUTING.md — Debugging Generation Drift Failures for the full procedure. Diff summary |
Co-Authored-By: AJ Steers <aj@airbyte.io>
E2E Test ResultsBuilt the provider binary from this PR branch and ran a full Terraform lifecycle against Airbyte Cloud sandbox workspace ( Test Results — All Passed
What This Proves
Not Tested (Out of Scope)
|
…butes
Refactors the IAP schema from flat top-level attributes
(google_iap_service_account_key, google_iap_client_id) to a nested
SingleNestedAttribute block:
provider "airbyte" {
google_iap {
service_account_key = file("sa-key.json")
client_id = "xxxx.apps.googleusercontent.com"
}
}
Benefits:
- Follows Terraform conventions (AWS assume_role, Google batching, etc.)
- Atomic validation: both fields required when block is set
- Clean namespace: stack-specific config grouped visually
- Extensible: adding fields later doesn't pollute top-level
GoogleIAPModel struct lives in google_iap.go (non-generated).
Patch script updated for SingleNestedAttribute + nested extraction.
Co-Authored-By: AJ Steers <aj@airbyte.io>
There was a problem hiding this comment.
Pull request overview
Adds Google IAP (Identity-Aware Proxy) authentication to the Airbyte Terraform provider by introducing an IAP token manager, wiring it into the provider HTTP transport, and ensuring the changes survive Speakeasy regeneration via a post-generate patch script. It also addresses the previously reported bearer_auth overwrite scenario by only enabling BasicAuth when credentials are non-empty.
Changes:
- Add
google_iap { service_account_key, client_id }provider config and wire it into the HTTP transport to injectAuthorization: Bearer <iap_token>. - Introduce
IAPTokenManagerfor JWT creation, token exchange, caching, and refresh. - Add an idempotent post-generation patch script and hook it into
post-generate, plus update provider docs.
Reviewed changes
Copilot reviewed 4 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/patch_iap_auth.py | Adds post-generation patching to inject IAP schema/model/transport; needs fixes to avoid generating mis-indented Go code and to inject fail-fast behavior on token errors. |
| poe_tasks.toml | Hooks the IAP patch script into post-generate. |
| internal/provider/utils.go | Adds IAP transport options + token injection; currently has formatting issues and should fail-fast when token retrieval fails. |
| internal/provider/provider.go | Adds google_iap schema + passes nested config into transport opts. |
| internal/provider/google_iap.go | Implements JWT signing + OAuth token exchange + caching for IAP ID tokens; defines the nested schema model. |
| docs/index.md | Documents the new google_iap nested provider block. |
Files not reviewed (2)
- internal/provider/provider.go: Language not supported
- internal/provider/utils.go: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…oundTrip - Move IAP manager initialization from NewProviderHTTPTransport into Configure, where resp.Diagnostics can report errors to users - Replace silent log-and-continue in RoundTrip with fail-fast error return (fmt.Errorf) so IAP token failures produce clear messages - Simplify ProviderHTTPTransportOpts: single IAPManager field instead of two raw strings; NewProviderHTTPTransport just assigns it - Fix indentation in patch script output - Update patch script to generate the corrected code on regeneration Addresses review feedback from Devin Review and Copilot. Co-Authored-By: AJ Steers <aj@airbyte.io>
|
/pre-release version=v1.3.0-rc.1 |
|
|
|
/pre-release version=v1.3.0-rc.1
|
|
|
/pre-release version=v1.3.0-rc1
|
|
Pre-release Status
The output of this PR is available for testing as
v1.3.0-rc1:https://registry.terraform.io/providers/airbytehq/airbyte/1.3.0-rc1
We greatly appreciate any feedback. Please share any feedback here in the PR comments below. Thank you. 🙏
Summary
Adds Google IAP (Identity-Aware Proxy) authentication support and fixes bearer_auth being overwritten by empty BasicAuth credentials. Closes #207, closes #198.
Built from community PR #222 by Shimoikura (@y-ikura) to preserve contributor credit, then reworked for durability using a post-generation patch script (per repo conventions).
Schema — IAP config uses a nested
SingleNestedAttributeblock following Terraform conventions (like AWSassume_role {}, Googlebatching {}):Both inner fields are
Requiredwhen the block is set — atomic validation, no partial config possible.Architecture:
internal/provider/google_iap.go— standalone IAP token manager: JWT/RS256 signing, token caching withsync.RWMutex+singleflightdedup, 55-min cache / 60s refresh buffer. Also definesGoogleIAPModelstruct for the nested schema.scripts/patch_iap_auth.py— post-generation patch that injects IAP schema, model field (*GoogleIAPModel), and transport wiring intoprovider.go/utils.goafter Speakeasy regeneration. Idempotent.poe_tasks.toml— hooks the patch intopost-generate.Transport layer —
RoundTripinjectsAuthorization: Bearer <iap_token>before every request when IAP is configured, overriding any existing auth header. Token refresh is transparent and thread-safe.E2E tested — full terraform lifecycle (plan → apply → drift-check → destroy) against Airbyte Cloud sandbox confirms normal operation is unaffected when IAP is not configured.
Link to Devin session: https://app.devin.ai/sessions/9c254508bc6144058ceee8a24a441fa0
Requested by: Aaron ("AJ") Steers (@aaronsteers)