fix(runner): propagate public hostname to kubernetes job pods for TF_TOKEN auth - #948
fix(runner): propagate public hostname to kubernetes job pods for TF_TOKEN auth#948olemathias wants to merge 1 commit into
Conversation
|
@olemathias Thanks for the bug report and PR. I think the heart of the issue is that there a hostname set in I don't believe this issue is unique to the kubernetes executor. Any scenario in which there is a mis-match between those two settings will result in the error you're seeing. That can occur, say, in In your case, and as you've noticed, I'm not sure about your fix. I need to think some more on the ramifications. The Have you considered setting |
|
Thanks for the quick review! I did consider setting What if instead of replacing the |
Why would you have runs both inside and "outside of OTF"? But in any case, on second thoughts I'm not sure this would be a viable approach because the service probably doesn't expose the endpoint as https and terraform assumes it is https.
Yes I think this a more valid approach. Please update your PR accordingly. |
…TOKEN auth When using the kubernetes executor, the otf-job pod connects to otfd via an internal Kubernetes service URL (e.g. http://otf.default:8080/), causing the TF_TOKEN_* credential env var to be keyed on the internal hostname. Terraform's data.terraform_remote_state uses the public-facing OTF hostname to look up credentials, so authentication fails.
81d4b5e to
4adfc3b
Compare
|
@leg100 PR updated with the changes |
| credentialEnvs := func(opts OperationOptions) []string { | ||
| var envs []string | ||
| envs = append(envs, internal.CredentialEnv(opts.Client.Hostname(), opts.JobToken)) | ||
| if opts.CredentialHostname != "" && opts.CredentialHostname != opts.Client.Hostname() { | ||
| envs = append(envs, internal.CredentialEnv(opts.CredentialHostname, opts.JobToken)) | ||
| } | ||
| return envs | ||
| } |
There was a problem hiding this comment.
What's the purpose of this test if the code under test is merely re-implemented within the test?!
Fixes #947
Problem
When using the Kubernetes executor, OpenTofu fails to read remote state via
data.terraform_remote_statewith the remote backend. The runner's authentication token doesn't appear to be propagated to the pod/job that executes the plan.Root cause:
otf-jobconnects to otfd via the internal Kubernetes service URL (e.g.http://otf.default:8080/).DoOperationderives theTF_TOKEN_*credential env var name from the API client's hostname, so it setsTF_TOKEN_otf_default_8080=<token>.But Terraform's
data.terraform_remote_statecan connect using the public-facing OTF hostname (e.g.otf.example.com) and looks forTF_TOKEN_otf_example_com, which is never set.Fix
Pass the public OTF hostname to job pods as
OTF_HOSTNAME.otf-jobreads it and supplies it asCredentialHostnameinOperationOptions.DoOperationnow sets credential env vars for both hostnames when they differ — one forClient.Hostname()(the internal service URL) and one forCredentialHostname(the public-facing hostname). This ensures Terraform can authenticate regardless of which hostname appears in the remote backend config.The daemon propagates the hostname automatically, so no additional configuration is needed beyond having the public hostname set in otfd.
Testing
Added unit tests covering:
DoOperationsets only one credential env var whenCredentialHostnameis empty or matchesClient.Hostname()DoOperationsets two credential env vars whenCredentialHostnamediffers fromClient.Hostname()SpawnOperationpasses the correct value in theOTF_HOSTNAMEpod env varNote
I am not an experienced Go developer. Claude Code was used to help identify and implement this fix. That said, the fix has been verified on a real OTF deployment and is working.
Happy to make any changes if the approach needs adjusting.