Repository: gruntwork-io/terragrunt (language: go)

Issue:
Add access_token support for the GCS remote state backend config
Hi!

Currently it does not seem to be possible to forward an access token to the GCS remote state backend:

```
remote_state {
  backend = "gcs"
  config = {
    # access_token = local.google_access_token # this doesn't work
    credentials = local.google_credentials # this works
    ...
  }
}
```

I see that credentials were added as a response to https://github.com/gruntwork-io/terragrunt/issues/780 but I think the support for access_token is still missing (it is supported by the Google provider otherwise, see https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#access_token).

Adding support for the access token would be awesome because then anyone would be able to provision with the gcloud credentials with this trick:

```
locals {
  google_access_token = run_cmd(
    "--terragrunt-quiet", "gcloud", "auth", "print-access-token",
    "--configuration", local.organization_id,
  )
}
```

Note that `credentials` isn't documented at the moment (see https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#remote_state, `gcs` backend section), it would be potentially great to document these too.


Discussion / hints:

Fix patch:
diff --git a/docs/_docs/04_reference/config-blocks-and-attributes.md b/docs/_docs/04_reference/config-blocks-and-attributes.md
index a4b3c3e9a6..7306998a35 100644
--- a/docs/_docs/04_reference/config-blocks-and-attributes.md
+++ b/docs/_docs/04_reference/config-blocks-and-attributes.md
@@ -410,7 +410,8 @@ For the `gcs` backend, the following additional properties are supported in the
 - `project`: The GCP project where the bucket will be created.
 - `location`: The GCP location where the bucket will be created.
 - `gcs_bucket_labels`: A map of key value pairs to associate as labels on the created GCS bucket.
-
+- `credentials`: Local path to Google Cloud Platform account credentials in JSON format.
+- `access_token`: A temporary [OAuth 2.0 access token] obtained from the Google Authorization server.
 Example with S3:
 
 ```hcl
diff --git a/remote/remote_state_gcs.go b/remote/remote_state_gcs.go
index fa2dff6bc8..fea740940b 100644
--- a/remote/remote_state_gcs.go
+++ b/remote/remote_state_gcs.go
@@ -52,6 +52,7 @@ var terragruntGCSOnlyConfigs = []string{
 type RemoteStateConfigGCS struct {
 	Bucket        string `mapstructure:"bucket"`
 	Credentials   string `mapstructure:"credentials"`
+	AccessToken   string `mapstructure:"access_token"`
 	Prefix        string `mapstructure:"prefix"`
 	Path          string `mapstructure:"path"`
 	EncryptionKey string `mapstructure:"encryption_key"`
@@ -426,6 +427,11 @@ func CreateGCSClient(gcsConfigRemote RemoteStateConfigGCS) (*storage.Client, err
 
 	if gcsConfigRemote.Credentials != "" {
 		opts = append(opts, option.WithCredentialsFile(gcsConfigRemote.Credentials))
+	} else if gcsConfigRemote.AccessToken != "" {
+		tokenSource := oauth2.StaticTokenSource(&oauth2.Token{
+			AccessToken: gcsConfigRemote.AccessToken,
+		})
+		opts = append(opts, option.WithTokenSource(tokenSource))
 	} else if oauthAccessToken := os.Getenv("GOOGLE_OAUTH_ACCESS_TOKEN"); oauthAccessToken != "" {
 		tokenSource := oauth2.StaticTokenSource(&oauth2.Token{
 			AccessToken: oauthAccessToken,


Test patch:
diff --git a/remote/remote_state_test.go b/remote/remote_state_test.go
index d27d664f96..c3787593f5 100644
--- a/remote/remote_state_test.go
+++ b/remote/remote_state_test.go
@@ -67,13 +67,14 @@ func TestToTerraformInitArgsForGCS(t *testing.T) {
 
 			"skip_bucket_versioning": true,
 
-			"credentials": "my-file",
+			"credentials":  "my-file",
+			"access_token": "xxxxxxxx",
 		},
 	}
 	args := remoteState.ToTerraformInitArgs()
 
 	// must not contain project, location gcs_bucket_labels or skip_bucket_versioning
-	assertTerraformInitArgsEqual(t, args, "-backend-config=bucket=my-bucket -backend-config=prefix=terraform.tfstate -backend-config=credentials=my-file")
+	assertTerraformInitArgsEqual(t, args, "-backend-config=bucket=my-bucket -backend-config=prefix=terraform.tfstate -backend-config=credentials=my-file -backend-config=access_token=xxxxxxxx")
 }
 
 func TestToTerraformInitArgsUnknownBackend(t *testing.T) {