That response is an HTTP redirect telling you to repeat your request at a different URL, specified in the
curl doesn’t automatically follow redirects, so to practice with that command you’ll need to run
curl again with the new URL to see what the new request returns:
$ curl -i https://registry.terraform.io/v1/modules/terraform-google-modules/vm/google/7.8.0/download
cache-control: public, max-age=604800, stale-if-error=31536000
last-modified: Thu, 23 Jun 2022 03:01:32 GMT
strict-transport-security: max-age=31536000; includeSubDomains; preload
via: 1.1 varnish, 1.1 varnish
date: Mon, 12 Sep 2022 18:39:04 GMT
x-served-by: cache-iad-kjyo7100141-IAD, cache-pdx12328-PDX
x-cache: HIT, HIT
x-cache-hits: 1, 1
vary: Accept-Encoding, X-Terraform-Version
The Download Source Code for a Specific Module Version operation (which is what we called here) is defined to return a
204 No Content response with a header
X-Terraform-Get describing the real download location.
That matches the response above, and the
X-Terraform-Get header contains the following string:
The challenge at this point is that this is a raw module source string and there is not a well-defined specification for how to interpret these. Instead, the specification is just whatever Terraform CLI itself does. This is why I described using
terraform init -from-module=... to download the module instead; that command knows how to understand the above string and retrieve the module source code using Git.
$ terraform init -backend=false -from-module=git::https://github.com/terraform-google-modules/terraform-google-vm?ref=v7.8.0
Copying configuration from "git::https://github.com/terraform-google-modules/terraform-google-vm?ref=v7.8.0"...
Terraform initialized in an empty directory!
The directory has no Terraform configuration files. You may begin working
with Terraform immediately by creating Terraform configuration files.
This particular module package is interesting because the root directory doesn’t contain a Terraform module, and so Terraform treated it as an empty directory. It isn’t really fully empty, but from Terraform’s perspective it doesn’t include any
.tf files and so there’s nothing in that directory that Terraform itself knows how to read.
However, despite this weird error message there are still files in the current working directory afterwards:
autogen autogen_modules.json build CHANGELOG.md
CONTRIBUTING.md docs examples LICENSE Makefile
modules README.md test
modules subdirectory in particular contains what the Terraform Registry web UI describes as “sub-modules”, which are also Terraform modules you can analyze.
(Note: I used
-backend=false on the
terraform init command above to prevent any backend initialization. It’s not valid for a shared Terraform module to include a backend configuration, but this particular command is asking Terraform to treat a shared module as if it were a root module and so a malicious module package could potentially include a backend configuration that Terraform would then try to initialize, potentially sending any ambient credentials on your system to an attacker-provided location. Disabling the backend initialization prevents that from happening.)
If you are willing to support only the official public Terraform Registry then there is an easier path in retrieving “Latest Version for a Specific Module Provider” in the public-registry-specific API:
In this response you should see for the main module (which doesn’t exist in this package) and for each submodule the JSON properties
outputs, which will directly describe which input variables the module expects and which output values it produces.
The registry doesn’t currently expose exactly which provider configurations the module expects, so you’d need to infer that separately somehow today. For example, you could in principle assume that because the last part of the module’s address is “google”, representing Google Cloud Platform, that the module will need a default (unaliased) configuration for the
hashicorp/google provider. It’s possible that a module might require additional (aliased) provider configurations too; that currently is not exposed in the API, so you’d need to do direct analysis to learn that.