-
Notifications
You must be signed in to change notification settings - Fork 131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Failed to get schema due to backend authentication #128
Comments
@garry-harthill-cko Generally the language server was designed to not require any access to credentials and other configuration that is usually provided out of bound for the exact reason that passing the right ENV variables or configuration down to Terraform is difficult from UX perspective. The only terraform commands it runs are the following:
and each execution of either of these is also visible from the log (when you enable logging), e.g.
Obtaining the schema does require the workspace to be initialized, but I'm aware that the extension also has Do you mind sharing more details about the problem you're running into? Ideally a snippet of a log like the above? |
Thanks for the quick reply. I'm seeing this in the logs quite soon after starting vscode:
Then while editing references to a missing schema file are displayed:
The workspace is initialised and all terraform actions work without errors on the command line. Maybe I installed the extension incorrectly? I cloned into extensions directory and ran |
Thank you for these useful additional details @garry-harthill-cko ! I will try to reproduce this 🔜 , but if it's a bug it would be more likely in the language server or Terraform itself, than the extension as it's the server that executes Terraform in this context. For that reason I'm going to transfer it over. |
One more question - what Terraform version do you use for this configuration? |
Also could you please try to run the following (in the mentioned workspace):
with and without your auth wrapper? |
Without the auth wrapper I get the error I described before:
With the auth wrapper it appears to work and returns a very large json document:
|
Can this schema document be downloaded separately and placed in a directory manually for use by the extension? |
Thank you 🙏 It appears that You may be able to override the path to Terraform in the meantime via the following VSCode configuration ( {
"terraform.languageServer.args": [
"serve",
"-tf-exec=/auth/wrapper terraform"
]
} We could also make this a more 1st-class settings in the VSCode UI in the future.
Not really and I don't think we'd want to support such workflow, because getting the UX right around updating it would be very tricky. Ideally the user shouldn't even need to know that there's such thing as machine-readable schema in most cases (in the happy path). |
Actually the custom path flag isn't support yet, but will be in the upcoming LS version: |
I built the master branch of terraform-ls. The I have managed to get it kind of working by calling another wrapper shell script which in turn exec's terraform with the correct environment. Not ideal. |
You're right - it's not ideal. Ideally obtaining schema shouldn't require state at all (and hence shouldn't require auth) IMO, but we can't really fix this in Terraform core retrospectively (in past versions), so we will need to have a decent solution before this is addressed in core.
Good catch! I'm not too excited about flags which expect string with spaces (or any kind of arrays), but it is a solution and think we could use something like We can also prioritize the UI config option for setting the Terraform path in VSCode and try to construct (Unrelated to your use case) There may be users which don't use wrappers like the one you mentioned, but set variables manually. I'm not sure there's any decent way we can support that, because passing environment variables between whatever process launches the IDE, the IDE, plugin system and Maybe we just discourage this is as a bad practice and make folks approach it either via wrappers, or by making I mean even if you do store variables locally, then the sensitive ones should really be stored in something like |
I misspoke, this is due to the shared auth package they use: https://github.com/hashicorp/aws-sdk-go-base |
Instead of taking additional arguments you could probably just write/call a shell script as the "executable" in the near term while we investigate. |
I think we are going to need to significantly relax env propagation and related functionality due to this backend authentication issue. See #138 |
I think all we need to propagate in this case is really just terraform-ls/internal/terraform/exec/exec.go Lines 24 to 32 in b6cda0d
Then Terraform can find I would not go as far as propagating everything. It has some really bad UX implications stemming from the fact that most people launch their IDEs context/environment-less (via icon from a desktop, menu bar etc.). Even if they don't, they will need to change the environment variables when switching between workspaces, presumably without closing the IDE. So passing through variables which are usually passed to all applications (like |
Just to clarify though the above is a solution for #138 but not so much for this issue (#128). That said I think that integrating |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@radeksimko I'm just seeing this now cross linked from the other issue. I had assumed as well that What exactly is it doing with the state - some type of schema merge? Since terraform |
Generally a combination of config and state is needed to pick the providers before any I'm unsure what other use cases
So yes - I think that would be probably the ideal longer-term solution, but it still raises the question of 0.12 and any earlier 0.13 releases which may not have this feature - and these versions will be around for a while, so we're hoping to find some solutions for these too, without having to backport any patches. |
terraform providers schema -jsonがバックエンド認証を要求するが rootモジュールごとにAWSアカウントが異なり読み込む環境変数が違う。 hashicorp/terraform-ls#128 terraformコマンドの実行パスは-tf-execでカスタマイズできるので、 以下のようなラッパーコマンドを用意しておき、direnv経由で実行する。 ``` DIRENV_LOG_FORMAT="" direnv exec . terraform "$@" ``` 現時点ではシングルバイナリである必要があり、 bash -c でワンライナーでは書けないようだ。 また、$HOMEや~も解釈してくれないのでフルパスで指定する必要がある。
terraform providers schema -jsonがバックエンド認証を要求するが rootモジュールごとにAWSアカウントが異なり読み込む環境変数が違う。 hashicorp/terraform-ls#128 terraformコマンドの実行パスは-tf-execでカスタマイズできるので、 以下のようなラッパーコマンドを用意しておき、direnv経由で実行する。 ``` DIRENV_LOG_FORMAT="" direnv exec . terraform "$@" ``` 現時点ではシングルバイナリである必要があり、 bash -c でワンライナーでは書けないようだ。 また、$HOMEや~も解釈してくれないのでフルパスで指定する必要がある。
I'm going to add a bit of complexity to this I think .. In our config we use aws-vault (as mentioned above) together with A simple wrapper script will not suffice here .. because I need to pass different config names to aws-vault based on if this is in a sandbox or a production sub-folder .. perhaps something that is able to be set on a parent folder to specify the wrapper differently or something .. Our folder structure looks like this:
|
@piotrb Is there a reason your custom scripting can't just take these different config names as environment variables, instead of flags and leverage direnv there, since direnv already solves the problem of environment differences between folders? |
direnv solves the environment issue on the shell, sure .. but the new ENV only activates when you enter the various subfolders .. so if the language server can execute stuff as a full shell, or support direnv in some way (or some other way to set env on a per folder basis) .. then this could work, a wrapper can be made easily that just changes based on the env maybe what wasn't clear is that my 3 example root folders above are all inside one repo, so I often open it as a single project, so the LS needs to know to switch envs if its looking at a root below the different environment roots .. |
I suppose it might be possible to make a wrapper that executes direnv on its own .. then executes terraform wrapped in aws-vault .. the question is .. are the changes discussed here around being able to specify a wrapper already available? |
@piotrb There is currently no integration with direnv but we are considering integration of Also there is no "interpolation" of direnv exec $PWD terraform $@ The idea is though that you would be able to do the above, or pass any other complex wrapper straight, once mattn/go-shellwords#39 is resolved. |
ok I'm the right track now .. but having one more issue now .. the wrapper requires some manually entered credentials like keychain password and OTP code .. these come as popups which is fine .. the issue is that it seems like the language server is concurrently invoked a LOT of times .. (I guess once per root) .. is there a way to make it reduce the concurrency or something? if you launch them all at once .. they all ask for password .. if you launch them in serial the first one will ask for password only .. |
@piotrb That is a valid point OTP is generally a challenge in Terraform at this point for various reasons unfortunately - it is a topic we have discussed across teams a few times, but haven't come up with a decent solution yet (read as there's no API for providers/backends for this kind of stuff). However I have had some success using Terraform with auth tools which work in such a way that they pre-generate tokens somewhere in a known location (such as AWS STS tokens in |
I think the ideal solution for this will really be just not requiring state for getting the schemas, and therefore not requiring auth. Technically the LSP does have methods for prompting user for input, but (a) not arbitrary input, just multiple choices, and (b) even if we were to somehow connect that to the shell executor it would probably be very fragile. We also plan to explore some ways of obtaining the schema directly from plugin binaries via gRPC, which would sidestep this problem entirely both short term and long-term, but no work was done on that yet. |
tools like aws-vault do a great job of caching the credentials like you're mentioning above .. |
well or just not requiring authentication .. its a definitely a bit silly my editor language server needing to do authenticated calls to terraform ... it shouldn't need to do that and its a potential security risk |
I'm not sure I fully understand the problem here actually. 🤔 Why do concurrent calls cause a problem, if the auth is already cached for all of them? Is the cache not able to handle concurrent access? My assumption above was that the authentication is done prior to the launch of language server, because as mentioned complex authentication requiring user input as part of the launch is not really an option anyway. |
You can't guarantee that the credentials are going to be current .. especially in scenarios were you are using high security setups (aws keys + OTP + assume role) (which we are) .. so this stuff can usually be cached only for ~1h .. aws-vault manages that and generally does a great job of a complex situation The issue is that the first call after a bit of being idle will require to (at least) unlock the system keyring once again to retrieve the cached credentials (so this will pop up one authentication prompt) .. and then if the OTP is expired it will re-authenticate that too .. So .. the first call will unlock the keychain and possibly ask for OTP .. subsequent calls have a window of time while the keychain is still open and can do stuff without any prompts .. Of course of you parallelize the calls .. each call is actually the first .. and EVERY ONE OF THEM will pop up a keychain unlock prompt .. its a bit of a mess ;) |
Right, my point is why don't you make the first call outside of the language server, before it even launches to avoid all this? Assuming that the IDE, and therefore language server is launched by the same user, then the keychain should remain open for them, if I'm not mistaken? As for parallelisation control - I wouldn't be opposed to making configurable as part of #186 |
Its not trivial to always make that request before its needed again and it would seriously hamper any ease at which I can just jump in and edit the files .. having module detection run doesn't provide enough benefit in order to add a whole, kind of random step to "just editing a file" .. so its easier to just let it fail in the background and make the edits needed. If it can't be automated in the tool (ie vscode/terraform-ls) its not worth the extra hassle. |
Yikes, this issue is causing me and my org quite a headache. We pull in our AWS creds via vault (in a wrapper) and those paths differ between projects. This makes the solution suggested earlier not work in our use-case. |
Hi @radeksimko @garry-harthill-cko , my organization is trying to leverage the vscode-terraform extension which leverages terraform-ls. At the moment, we are not making providers locally available nor do we have a private registry for users to get them from. I won't go into the specifics of why things are like this, but currently at best we have the output from I'd like to leverage terraform-ls/internal/schemas/preload_schemas.go Lines 10 to 13 in c4ea46f
Thanks in advance . |
I believe the language server is reading the remote state. Remote state requires authentication.
I have a more elaborate method of authenticating against AWS which is a wrapper that rotates keys and sets environment variables, etc.
https://github.com/99designs/aws-vault
It would be a good feature if we would wrap the language servers execution in this program. Maybe a "terraform-ls.command" option so we can define the full terraform-ls command to be executed. eg:
/usr/local/bin/aws-vault exec myProfile -- terraform-ls
The text was updated successfully, but these errors were encountered: