Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package terragrunt for openSUSE:Factory 
checked in at 2022-05-14 22:57:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/terragrunt (Old)
 and      /work/SRC/openSUSE:Factory/.terragrunt.new.1538 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "terragrunt"

Sat May 14 22:57:04 2022 rev:3 rq:977230 version:0.37.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/terragrunt/terragrunt.changes    2022-05-05 
23:08:20.821703624 +0200
+++ /work/SRC/openSUSE:Factory/.terragrunt.new.1538/terragrunt.changes  
2022-05-14 22:58:50.931492344 +0200
@@ -1,0 +2,24 @@
+Sat May 14 08:25:49 UTC 2022 - ka...@b1-systems.de
+
+- Update to version 0.37.1:
+  * Update remote state docs to recommend generate first (#2106)
+
+-------------------------------------------------------------------
+Sat May 14 08:20:02 UTC 2022 - ka...@b1-systems.de
+
+- Update to version 0.37.0:
+  * fix config remote state s3 and update if needs (#2063)
+
+-------------------------------------------------------------------
+Fri May 13 19:58:52 UTC 2022 - ka...@b1-systems.de
+
+- Update to version 0.36.12:
+  * Allow v0.36 to define disable_bucket_update to make it easier to 
transition to v0.37 (#2105)
+
+-------------------------------------------------------------------
+Fri May 13 19:40:56 UTC 2022 - ka...@b1-systems.de
+
+- Update to version 0.36.11:
+  * Bump github.com/hashicorp/go-getter from 1.5.7 to 1.5.11 (#2095)
+
+-------------------------------------------------------------------

Old:
----
  terragrunt-0.36.10.tar.gz

New:
----
  terragrunt-0.37.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ terragrunt.spec ++++++
--- /var/tmp/diff_new_pack.1snwnn/_old  2022-05-14 22:58:51.527493089 +0200
+++ /var/tmp/diff_new_pack.1snwnn/_new  2022-05-14 22:58:51.531493094 +0200
@@ -19,7 +19,7 @@
 %define __arch_install_post export NO_BRP_STRIP_DEBUG=true
 
 Name:           terragrunt
-Version:        0.36.10
+Version:        0.37.1
 Release:        0
 Summary:        Thin wrapper for Terraform for working with multiple Terraform 
modules
 License:        MIT

++++++ _service ++++++
--- /var/tmp/diff_new_pack.1snwnn/_old  2022-05-14 22:58:51.563493134 +0200
+++ /var/tmp/diff_new_pack.1snwnn/_new  2022-05-14 22:58:51.567493139 +0200
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/gruntwork-io/terragrunt</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v0.36.10</param>
+    <param name="revision">v0.37.1</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="changesgenerate">enable</param>
     <param name="versionrewrite-pattern">v(.*)</param>
@@ -16,7 +16,7 @@
     <param name="compression">gz</param>
   </service>
   <service name="go_modules" mode="disabled">
-    <param name="archive">terragrunt-0.36.10.tar.gz</param>
+    <param name="archive">terragrunt-0.37.1.tar.gz</param>
   </service>
 </services>
 

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.1snwnn/_old  2022-05-14 22:58:51.587493164 +0200
+++ /var/tmp/diff_new_pack.1snwnn/_new  2022-05-14 22:58:51.591493169 +0200
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param 
name="url">https://github.com/gruntwork-io/terragrunt</param>
-              <param 
name="changesrevision">19291801f3c436fd88c144a56506cfe952e33d4e</param></service></servicedata>
+              <param 
name="changesrevision">f9f76373bb387b78b8198a90cb42cd4b73786efd</param></service></servicedata>
 (No newline at EOF)
 

++++++ terragrunt-0.36.10.tar.gz -> terragrunt-0.37.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/terragrunt-0.36.10/aws_helper/policy.go 
new/terragrunt-0.37.1/aws_helper/policy.go
--- old/terragrunt-0.36.10/aws_helper/policy.go 1970-01-01 01:00:00.000000000 
+0100
+++ new/terragrunt-0.37.1/aws_helper/policy.go  2022-05-13 16:04:48.000000000 
+0200
@@ -0,0 +1,37 @@
+package aws_helper
+
+import "encoding/json"
+
+// A representation of the polciy for AWS
+type Policy struct {
+       Version   string      `json:"Version"`
+       Statement []Statement `json:"Statement"`
+}
+
+type Statement struct {
+       Sid       string                  `json:"Sid"`
+       Effect    string                  `json:"Effect"`
+       Principal interface{}             `json:"Principal"`
+       Action    string                  `json:"Action"`
+       Resource  []string                `json:"Resource"`
+       Condition *map[string]interface{} `json:"Condition,omitempty"`
+}
+
+func UnmarshalPolicy(policy string) (Policy, error) {
+       var p Policy
+       err := json.Unmarshal([]byte(policy), &p)
+       if err != nil {
+               return p, err
+       }
+
+       return p, nil
+}
+
+func MarshalPolicy(policy Policy) ([]byte, error) {
+       policyJson, err := json.Marshal(policy)
+       if err != nil {
+               return nil, err
+       }
+
+       return policyJson, nil
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/terragrunt-0.36.10/docs/_docs/02_features/keep-your-remote-state-configuration-dry.md
 
new/terragrunt-0.37.1/docs/_docs/02_features/keep-your-remote-state-configuration-dry.md
--- 
old/terragrunt-0.36.10/docs/_docs/02_features/keep-your-remote-state-configuration-dry.md
   2022-05-04 09:33:29.000000000 +0200
+++ 
new/terragrunt-0.37.1/docs/_docs/02_features/keep-your-remote-state-configuration-dry.md
    2022-05-13 16:04:48.000000000 +0200
@@ -16,10 +16,9 @@
 
   - [Filling in remote state settings with 
Terragrunt](#filling-in-remote-state-settings-with-terragrunt)
 
-  - [Using the generate property to generate terraform code for managing 
remote 
state](#using-the-generate-property-to-generate-terraform-code-for-managing-remote-state)
-
   - [Create remote state and locking resources 
automatically](#create-remote-state-and-locking-resources-automatically)
 
+
 ### Motivation
 
 Terraform supports [remote state 
storage](https://www.terraform.io/docs/state/remote.html) via a variety of 
[backends](https://www.terraform.io/docs/backends) that you normally configure 
in your `.tf` files as follows:
@@ -49,14 +48,7 @@
 
 To use remote state with each of these modules, you would have to copy/paste 
the exact same `backend` configuration into each of the `main.tf` files. The 
only thing that would differ between the configurations would be the `key` 
parameter: e.g., the `key` for `mysql/main.tf` might be 
`mysql/terraform.tfstate` and the `key` for `frontend-app/main.tf` might be 
`frontend-app/terraform.tfstate`.
 
-To keep your remote state configuration DRY, you can use Terragrunt. You still 
have to specify the `backend` you want to use in each module, but instead of 
copying and pasting the configuration settings over and over again into each 
`main.tf` file, you can leave them blank (this is known as [partial 
configuration](https://www.terraform.io/docs/backends/config.html#partial-configuration)):
-
-``` hcl
-terraform {
-  # The configuration for this backend will be filled in by Terragrunt
-  backend "s3" {}
-}
-```
+To keep your remote state configuration DRY, you can use Terragrunt.
 
 ### Filling in remote state settings with Terragrunt
 
@@ -76,12 +68,15 @@
         ????????? main.tf
         ????????? terragrunt.hcl
 
-In your **root** `terragrunt.hcl` file, you can define your entire remote 
state configuration just once in a `remote_state` block (which supports all the 
same [backend types](https://www.terraform.io/docs/backends/types/index.html) 
as Terraform), as follows:
+In your **root** `terragrunt.hcl` file, you can define your entire remote 
state configuration just once in a `generate` block, to generate a `backend.tf` 
file that includes the backend configuration:
 
-``` hcl
-remote_state {
-  backend = "s3"
-  config = {
+```hcl
+generate "backend" {
+  path      = "backend.tf"
+  if_exists = "overwrite_terragrunt"
+  contents = <<EOF
+terraform {
+  backend "s3" {
     bucket         = "my-terraform-state"
     key            = "${path_relative_to_include()}/terraform.tfstate"
     region         = "us-east-1"
@@ -89,9 +84,17 @@
     dynamodb_table = "my-lock-table"
   }
 }
+EOF
+}
 ```
 
-In each of the **child** `terragrunt.hcl` files, such as 
`mysql/terragrunt.hcl`, you can tell Terragrunt to automatically include all 
the settings from the root `terragrunt.hcl` file as follows:
+This instructs Terragrunt to create the file `backend.tf` in the working 
directory (where Terragrunt calls `terraform`)
+before it calls any of the Terraform commands, including `init`. This allows 
you to inject this backend configuration
+in all the modules that includes the root file and have `terragrunt` properly 
initialize the backend configuration with
+interpolated values.
+
+To inherit this configuration, in each of the **child** `terragrunt.hcl` 
files, such as `mysql/terragrunt.hcl`, you can
+tell Terragrunt to automatically include all the settings from the root 
`terragrunt.hcl` file as follows:
 
 ``` hcl
 include "root" {
@@ -99,9 +102,9 @@
 }
 ```
 
-The `include` block tells Terragrunt to use the exact same Terragrunt 
configuration from the `terragrunt.hcl` file specified via the `path` 
parameter. It behaves exactly as if you had copy/pasted the Terraform 
configuration from the included file `remote_state` configuration into 
`mysql/terragrunt.hcl`, but this approach is much easier to maintain\!
+The `include` block tells Terragrunt to use the exact same Terragrunt 
configuration from the `terragrunt.hcl` file specified via the `path` 
parameter. It behaves exactly as if you had copy/pasted the Terraform 
configuration from the included file `generate` configuration into 
`mysql/terragrunt.hcl`, but this approach is much easier to maintain\!
 
-The next time you run `terragrunt`, it will automatically configure all the 
settings in the `remote_state.config` block, if they aren???t configured 
already, by calling [terraform 
init](https://www.terraform.io/docs/commands/init.html).
+The next time you run `terragrunt`, it will automatically configure all the 
settings for the backend, if they aren???t configured already, by calling 
[terraform init](https://www.terraform.io/docs/commands/init.html).
 
 The `terragrunt.hcl` files above use two Terragrunt built-in functions:
 
@@ -111,47 +114,69 @@
 
 See [the Built-in Functions 
docs]({{site.baseurl}}/docs/reference/built-in-functions/#built-in-functions) 
for more info.
 
-Check out the 
[terragrunt-infrastructure-modules-example](https://github.com/gruntwork-io/terragrunt-infrastructure-modules-example)
 and 
[terragrunt-infrastructure-live-example](https://github.com/gruntwork-io/terragrunt-infrastructure-live-example)
 repos for fully-working sample code that demonstrates how to use Terragrunt to 
manage remote state.
-
-### Rules for merging parent and child configurations
 
-The child `.hcl` file???s `terraform` settings will be merged into the parent 
file???s `terraform` settings as follows:
+### Create remote state and locking resources automatically
 
-  - If an `extra_arguments` block in the child has the same name as an 
`extra_arguments` block in the parent, then the child???s block will override 
the parent???s.
+The `generate` block is useful for allowing you to setup the remote state 
backend configuration in a DRY manner, but
+this introduces a bootstrapping problem: how do you create and manage the 
underlying storage resources for the remote
+state? For example, when using the [s3 
backend](https://www.terraform.io/language/settings/backends/s3), Terraform
+expects the S3 bucket to already exist for it to upload the state objects.
+
+Ideally you can manage the S3 bucket using Terraform, but what about the state 
object for the module managing the S3
+bucket? How do you create the S3 bucket, before you run `terraform`, if you 
need to run `terraform` to create the
+bucket?
+
+To handle this, Terragrunt supports a different block for managing the backend 
configuration: the [remote_state
+block](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#remote_state).
+
+> **NOTE**
+>
+> `remote_state` is an alternative way of managing the Terraform backend 
compared to `generate`. You can not use both
+> methods at the same time to manage the remote state configuration. When 
implementing `remote_state`, be sure to remove
+> the corresponding `generate` block for managing the backend.
+
+The following backends are currently supported by `remote_state`:
+
+- [s3 backend](https://www.terraform.io/language/settings/backends/s3)
+- [gcs backend](https://www.terraform.io/language/settings/backends/gcs)
+
+For all other backends, the `remote_state` block operates in the same manner 
as `generate`. However, we may add
+support for additional backends to `remote_state` blocks, which may disrupt 
your environment. If you do not want support
+for automated management of remote state resources, we recommend sticking to 
`generate` blocks to configure the backend.
 
-      - Specifying an empty `extra_arguments` block in a child with the same 
name will effectively remove the parent???s block.
+When you run `terragrunt` with a `remote_state` configuration, it will 
automatically create the following resources if they don???t already exist:
 
-  - If an `extra_arguments` block in the child has a different name than 
`extra_arguments` blocks in the parent, then both the parent and child???s 
`extra_arguments` will be effective.
+  - **S3 bucket**: If you are using the [S3 
backend](https://www.terraform.io/docs/backends/types/s3.html) for remote state 
storage and the `bucket` you specify in `remote_state.config` doesn???t already 
exist, Terragrunt will create it automatically, with 
[versioning](https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html), 
[server-side 
encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html),
 and [access 
logging](https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerLogs.html) 
enabled.
 
-      - The child???s `extra_arguments` will be placed *after* the parent???s 
`extra_arguments` on the terraform command line.
+    In addition, you can let terragrunt tag the bucket with custom tags that 
you specify in `remote_state.config.s3_bucket_tags`.
 
-      - Therefore, if a child???s and parent???s `extra_arguments` include 
`.tfvars` files with the same variable defined, the value from the `.tfvars` 
file from the child???s `extra_arguments` will be used by terraform.
+  - **DynamoDB table**: If you are using the [S3 
backend](https://www.terraform.io/docs/backends/types/s3.html) for remote state 
storage and you specify a `dynamodb_table` (a [DynamoDB table used for 
locking](https://www.terraform.io/docs/backends/types/s3.html#dynamodb_table)) 
in `remote_state.config`, if that table doesn???t already exist, Terragrunt 
will create it automatically, with [server-side 
encryption](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/EncryptionAtRest.html)
 enabled, including a primary key called `LockID`.
 
-  - If a `before_hook` or `after_hook` block in the child has the same name as 
the hook block in the parent, then the child???s block will override the 
parent???s.
+    You may configure custom endpoint for the AWS DynamoDB API using 
`remote_state.config.dynamodb_endpoint`.
 
-      - Specifying an empty hook block in a child with the same name will 
effectively remove the parent???s block.
+    In addition, you can let terragrunt tag the DynamoDB table with custom 
tags that you specify in `remote_state.config.dynamodb_table_tags`.
 
-  - If a `before_hook` or `after_hook` block in the child has a different name 
than hook blocks in the parent, then both the parent and child???s hook blocks 
will be effective.
+  - **GCS bucket**: If you are using the [GCS 
backend](https://www.terraform.io/docs/backends/types/gcs.html) for remote 
state storage and the `bucket` you specify in `remote_state.config` doesn???t 
already exist, Terragrunt will create it automatically, with 
[versioning](https://cloud.google.com/storage/docs/object-versioning) enabled. 
For this to work correctly you must also specify `project` and `location` keys 
in `remote_state.config`, so Terragrunt knows where to create the bucket. You 
will also need to supply valid credentials using either 
`remote_state.config.credentials` or by setting the 
`GOOGLE_APPLICATION_CREDENTIALS` environment variable. If you want to skip 
creating the bucket entirely, simply set `skip_bucket_creation` to `true` and 
Terragrunt will assume the bucket has already been created. If you don???t 
specify `bucket` in `remote_state` then terragrunt will assume that you will 
pass `bucket` through `-backend-config` in `extra_arguments`.
 
-  - The `source` field in the child will override `source` field in the parent
+    We also strongly recommend you enable [Cloud Audit 
Logs](https://cloud.google.com/storage/docs/access-logs) to audit and track API 
operations performed against the state bucket.
 
-Other settings in the child `.hcl` file override the respective settings in 
the parent.
+    In addition, you can let Terragrunt label the bucket with custom labels 
that you specify in `remote_state.config.gcs_bucket_labels`.
 
+**Note**: If you specify a `profile` key in `remote_state.config`, Terragrunt 
will automatically use this AWS profile when creating the S3 bucket or DynamoDB 
table.
 
-### Using the generate property to generate terraform code for managing remote 
state
+**Note**: You can disable automatic remote state initialization by setting 
`remote_state.disable_init`, this will skip the automatic creation of remote 
state resources and will execute `terraform init` passing the `backend=false` 
option. This can be handy when running commands such as `validate-all` as part 
of a CI process where you do not want to initialize remote state.
 
-While the default way terragrunt manages remote state is through `terraform 
init` with `-backend-config`, you can also
-use the `generate` property to configure terragrunt to generate a `.tf` file 
in the terraform working directory with the
-backend configuration.
+The following example demonstrates using an environment variable to configure 
this option:
 
-The `generate` property is an object that accepts two parameters:
+``` hcl
+remote_state {
+  # ...
 
-- `path`: The path where the generated file should be written. If a relative 
path, it'll be relative to the Terragrunt
-  working dir (where the terraform code lives).
-- `if_exists`: What to do if a file already exists at `path`. Valid values 
are: `overwrite` (overwrite the existing
-  file), `skip` (skip code generation and leave the existing file as-is), 
`error` (exit with an error).
+  disable_init = tobool(get_env("TERRAGRUNT_DISABLE_INIT", "false"))
+}
+```
 
-For example, here is a version of the root `remote_state` configuration with 
the `generate` property:
+Here is an example of using the `remote_state` block to configure the S3 
backend:
 
 ```hcl
 remote_state {
@@ -170,58 +195,30 @@
 }
 ```
 
-With this configuration, `terragrunt` will generate a new file `backend.tf` in 
the working directory before it calls out
-to any `terraform` command with the following contents:
+Like the approach with `generate` blocks, this will generate a `backend.tf` 
file that contains the remote state
+configuration. However, in addition to that, `terragrunt` will also now manage 
the S3 bucket and DynamoDB table for you.
+This means that if the S3 bucket `my-terraform-state` and DynamoDB table 
`my-lock-table` does not exist in your account,
+Terragrunt will automatically create these resources before calling 
`terraform` and configure them based on the
+specified configuration parameters.
+
+Additionally, for **the S3 backend only**, Terragrunt will automatically 
update the S3 resource to match the
+configuration specified in the `remote_state` bucket. For example, if you 
require versioning in the `remote_state`
+block, but the underlying state bucket doesn't have versioning enabled, 
Terragrunt will automatically turn on versioning
+on the bucket to match the configuration.
+
+If you do not want `terragrunt` to automatically apply changes, you can 
configuret the following:
 
 ```hcl
-# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
-terraform {
-  backend "s3" {
-    bucket         = "my-terraform-state"
-    key            = "path/to/child/from/parent/terraform.tfstate"
-    region         = "us-east-1"
-    encrypt        = true
-    dynamodb_table = "my-lock-table"
+remote_state {
+  # ... other args omitted for brevity ...
+  config = {
+    # ... other config omitted for brevity ...
+    disable_bucket_update = true
   }
 }
 ```
 
-Terragrunt will also skip including the `-backend-config` arguments when 
calling `terraform`.
-
-
-### Create remote state and locking resources automatically
-
-When you run `terragrunt` with `remote_state` configuration, it will 
automatically create the following resources if they don???t already exist:
-
-  - **S3 bucket**: If you are using the [S3 
backend](https://www.terraform.io/docs/backends/types/s3.html) for remote state 
storage and the `bucket` you specify in `remote_state.config` doesn???t already 
exist, Terragrunt will create it automatically, with 
[versioning](https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html), 
[server-side 
encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html),
 and [access 
logging](https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerLogs.html) 
enabled.
-
-    In addition, you can let terragrunt tag the bucket with custom tags that 
you specify in `remote_state.config.s3_bucket_tags`.
-
-  - **DynamoDB table**: If you are using the [S3 
backend](https://www.terraform.io/docs/backends/types/s3.html) for remote state 
storage and you specify a `dynamodb_table` (a [DynamoDB table used for 
locking](https://www.terraform.io/docs/backends/types/s3.html#dynamodb_table)) 
in `remote_state.config`, if that table doesn???t already exist, Terragrunt 
will create it automatically, with [server-side 
encryption](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/EncryptionAtRest.html)
 enabled, including a primary key called `LockID`.
-  
-    You may configure custom endpoint for the AWS DynamoDB API using 
`remote_state.config.dynamodb_endpoint`.
-    
-    In addition, you can let terragrunt tag the DynamoDB table with custom 
tags that you specify in `remote_state.config.dynamodb_table_tags`.
-
-  - **GCS bucket**: If you are using the [GCS 
backend](https://www.terraform.io/docs/backends/types/gcs.html) for remote 
state storage and the `bucket` you specify in `remote_state.config` doesn???t 
already exist, Terragrunt will create it automatically, with 
[versioning](https://cloud.google.com/storage/docs/object-versioning) enabled. 
For this to work correctly you must also specify `project` and `location` keys 
in `remote_state.config`, so Terragrunt knows where to create the bucket. You 
will also need to supply valid credentials using either 
`remote_state.config.credentials` or by setting the 
`GOOGLE_APPLICATION_CREDENTIALS` environment variable. If you want to skip 
creating the bucket entirely, simply set `skip_bucket_creation` to `true` and 
Terragrunt will assume the bucket has already been created. If you don???t 
specify `bucket` in `remote_state` then terragrunt will assume that you will 
pass `bucket` through `-backend-config` in `extra_arguments`.
-
-    We also strongly recommend you enable [Cloud Audit 
Logs](https://cloud.google.com/storage/docs/access-logs) to audit and track API 
operations performed against the state bucket.
-
-    In addition, you can let Terragrunt label the bucket with custom labels 
that you specify in `remote_state.config.gcs_bucket_labels`.
-
-**Note**: If you specify a `profile` key in `remote_state.config`, Terragrunt 
will automatically use this AWS profile when creating the S3 bucket or DynamoDB 
table.
-
-**Note**: You can disable automatic remote state initialization by setting 
`remote_state.disable_init`, this will skip the automatic creation of remote 
state resources and will execute `terraform init` passing the `backend=false` 
option. This can be handy when running commands such as `validate-all` as part 
of a CI process where you do not want to initialize remote state.
-
-The following example demonstrates using an environment variable to configure 
this option:
-
-``` hcl
-remote_state {
-  # ...
-
-  disable_init = tobool(get_env("TERRAGRUNT_DISABLE_INIT", "false"))
-}
-```
+Check out the 
[terragrunt-infrastructure-modules-example](https://github.com/gruntwork-io/terragrunt-infrastructure-modules-example)
 and 
[terragrunt-infrastructure-live-example](https://github.com/gruntwork-io/terragrunt-infrastructure-live-example)
 repos for fully-working sample code that demonstrates how to use Terragrunt to 
manage remote state.
 
 ### S3-specific remote state settings
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/terragrunt-0.36.10/docs/_docs/04_reference/config-blocks-and-attributes.md 
new/terragrunt-0.37.1/docs/_docs/04_reference/config-blocks-and-attributes.md
--- 
old/terragrunt-0.36.10/docs/_docs/04_reference/config-blocks-and-attributes.md  
    2022-05-04 09:33:29.000000000 +0200
+++ 
new/terragrunt-0.37.1/docs/_docs/04_reference/config-blocks-and-attributes.md   
    2022-05-13 16:04:48.000000000 +0200
@@ -387,6 +387,7 @@
 - `skip_bucket_accesslogging`: _DEPRECATED_ If provided, will be ignored. A 
log warning will be issued in the console output to notify the user.
 - `skip_bucket_root_access`: When `true`, the S3 bucket that is created will 
not be configured with bucket policies that allow access to the root AWS user.
 - `skip_bucket_enforced_tls`: When `true`, the S3 bucket that is created will 
not be configured with a bucket policy that enforces access to the bucket via a 
TLS connection.
+- `disable_bucket_update`: When `true`, disable update S3 bucket if not equal 
configured in config block 
 - `enable_lock_table_ssencryption`: When `true`, the synchronization lock 
table in DynamoDB used for remote state concurrent access will not be 
configured with server side encryption.
 - `s3_bucket_tags`: A map of key value pairs to associate as tags on the 
created S3 bucket.
 - `dynamodb_table_tags`: A map of key value pairs to associate as tags on the 
created DynamoDB remote state lock table.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/terragrunt-0.36.10/go.mod 
new/terragrunt-0.37.1/go.mod
--- old/terragrunt-0.36.10/go.mod       2022-05-04 09:33:29.000000000 +0200
+++ new/terragrunt-0.37.1/go.mod        2022-05-13 16:04:48.000000000 +0200
@@ -19,7 +19,7 @@
        github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
        github.com/gruntwork-io/terratest v0.32.6
        github.com/hashicorp/go-cleanhttp v0.5.2
-       github.com/hashicorp/go-getter v1.5.7
+       github.com/hashicorp/go-getter v1.5.11
        github.com/hashicorp/go-multierror v1.1.1
        github.com/hashicorp/go-retryablehttp v0.6.7 // indirect
        github.com/hashicorp/go-safetemp v1.0.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/terragrunt-0.36.10/go.sum 
new/terragrunt-0.37.1/go.sum
--- old/terragrunt-0.36.10/go.sum       2022-05-04 09:33:29.000000000 +0200
+++ new/terragrunt-0.37.1/go.sum        2022-05-13 16:04:48.000000000 +0200
@@ -502,8 +502,8 @@
 github.com/hashicorp/go-cleanhttp v0.5.2 
h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
 github.com/hashicorp/go-cleanhttp v0.5.2/go.mod 
h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
 github.com/hashicorp/go-getter v1.5.1/go.mod 
h1:a7z7NPPfNQpJWcn4rSWFtdrSldqLdLPEF3d8nFMsSLM=
-github.com/hashicorp/go-getter v1.5.7 
h1:HBLsom8eGHLxj78ta+/MVSyct8KWG4B4z6lhBA4vJcg=
-github.com/hashicorp/go-getter v1.5.7/go.mod 
h1:BrrV/1clo8cCYu6mxvboYg+KutTiFnXjMEgDD8+i7ZI=
+github.com/hashicorp/go-getter v1.5.11 
h1:wioTuNmaBU3IE9vdFtFMcmZWj0QzLc6DYaP6sNe5onY=
+github.com/hashicorp/go-getter v1.5.11/go.mod 
h1:9i48BP6wpWweI/0/+FBjqLrp9S8XtwUGjiu0QkWHEaY=
 github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod 
h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
 github.com/hashicorp/go-hclog v0.8.0/go.mod 
h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
 github.com/hashicorp/go-hclog v0.9.2/go.mod 
h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
@@ -899,8 +899,6 @@
 go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod 
h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
 go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a 
h1:N7VD+PwpJME2ZfQT8+ejxwA4Ow10IkGbU0MGf94ll8k=
 go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a/go.mod 
h1:YDKUvO0b//78PaaEro6CAPH6NqohCmL2Cwju5XI2HoE=
-go.mozilla.org/sops/v3 v3.7.0 h1:JuurncZrzjzirMNiQLm5WZLPyB5vcWhgre9YAWlTusA=
-go.mozilla.org/sops/v3 v3.7.0/go.mod 
h1:CJzeerUlKPLyVr8FxEGgEmc7LgUq4hwzqGxJqs8b+1c=
 go.mozilla.org/sops/v3 v3.7.2 h1:LNThLKe/pb80eGyAOFiWKP1Znqp1GQO2hqvuQOCmy5o=
 go.mozilla.org/sops/v3 v3.7.2/go.mod 
h1:OUNXNSkIrbr2wq3+RbK8s/ZCG+GaUnh8EY8IhXHI+wc=
 go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/terragrunt-0.36.10/remote/remote_state.go 
new/terragrunt-0.37.1/remote/remote_state.go
--- old/terragrunt-0.36.10/remote/remote_state.go       2022-05-04 
09:33:29.000000000 +0200
+++ new/terragrunt-0.37.1/remote/remote_state.go        2022-05-13 
16:04:48.000000000 +0200
@@ -55,7 +55,7 @@
 // Validate that the remote state is configured correctly
 func (remoteState *RemoteState) Validate() error {
        if remoteState.Backend == "" {
-               return errors.WithStackTrace(RemoteBackendMissing)
+               return errors.WithStackTrace(ErrRemoteBackendMissing)
        }
 
        return nil
@@ -173,7 +173,7 @@
 // Generate the terraform code for configuring remote state backend.
 func (remoteState *RemoteState) GenerateTerraformCode(terragruntOptions 
*options.TerragruntOptions) error {
        if remoteState.Generate == nil {
-               return errors.WithStackTrace(GenerateCalledWithNoGenerateAttr)
+               return 
errors.WithStackTrace(ErrGenerateCalledWithNoGenerateAttr)
        }
 
        // Make sure to strip out terragrunt specific configurations from the 
config.
@@ -205,6 +205,6 @@
 
 // Custom errors
 var (
-       RemoteBackendMissing             = fmt.Errorf("The remote_state.backend 
field cannot be empty")
-       GenerateCalledWithNoGenerateAttr = fmt.Errorf("Generate code routine 
called when no generate attribute is configured.")
+       ErrRemoteBackendMissing             = fmt.Errorf("the 
remote_state.backend field cannot be empty")
+       ErrGenerateCalledWithNoGenerateAttr = fmt.Errorf("generate code routine 
called when no generate attribute is configured")
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/terragrunt-0.36.10/remote/remote_state_gcs.go 
new/terragrunt-0.37.1/remote/remote_state_gcs.go
--- old/terragrunt-0.36.10/remote/remote_state_gcs.go   2022-05-04 
09:33:29.000000000 +0200
+++ new/terragrunt-0.37.1/remote/remote_state_gcs.go    2022-05-13 
16:04:48.000000000 +0200
@@ -289,7 +289,7 @@
                return errors.WithStackTrace(err)
        }
 
-       if attrs.VersioningEnabled == false {
+       if !attrs.VersioningEnabled {
                terragruntOptions.Logger.Warnf("Versioning is not enabled for 
the remote state GCS bucket %s. We recommend enabling versioning so that you 
can roll back to previous versions of your Terraform state in case of error.", 
config.Bucket)
        }
 
@@ -326,7 +326,7 @@
        ctx := context.Background()
        bucket := gcsClient.Bucket(config.remoteStateConfigGCS.Bucket)
 
-       bucketAttrs := *&storage.BucketAttrsToUpdate{}
+       bucketAttrs := storage.BucketAttrsToUpdate{}
 
        for key, value := range config.GCSBucketLabels {
                bucketAttrs.SetLabel(key, value)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/terragrunt-0.36.10/remote/remote_state_s3.go 
new/terragrunt-0.37.1/remote/remote_state_s3.go
--- old/terragrunt-0.36.10/remote/remote_state_s3.go    2022-05-04 
09:33:29.000000000 +0200
+++ new/terragrunt-0.37.1/remote/remote_state_s3.go     2022-05-13 
16:04:48.000000000 +0200
@@ -1,7 +1,6 @@
 package remote
 
 import (
-       "encoding/json"
        "fmt"
        "reflect"
        "strconv"
@@ -23,6 +22,8 @@
 const (
        lockTableDeprecationMessage              = "Remote state configuration 
'lock_table' attribute is deprecated; use 'dynamodb_table' instead."
        DefaultS3BucketAccessLoggingTargetPrefix = "TFStateLogs/"
+       SidRootPolicy                            = "RootAccess"
+       SidEnforcedTLSPolicy                     = "EnforcedTLS"
 )
 
 /*
@@ -40,6 +41,7 @@
        SkipBucketAccessLogging     bool              
`mapstructure:"skip_bucket_accesslogging"`
        SkipBucketRootAccess        bool              
`mapstructure:"skip_bucket_root_access"`
        SkipBucketEnforcedTLS       bool              
`mapstructure:"skip_bucket_enforced_tls"`
+       DisableBucketUpdate         bool              
`mapstructure:"disable_bucket_update"`
        EnableLockTableSSEncryption bool              
`mapstructure:"enable_lock_table_ssencryption"`
        DisableAWSClientChecksums   bool              
`mapstructure:"disable_aws_client_checksums"`
        AccessLoggingBucketName     string            
`mapstructure:"accesslogging_bucket_name"`
@@ -56,6 +58,7 @@
        "skip_bucket_accesslogging",
        "skip_bucket_root_access",
        "skip_bucket_enforced_tls",
+       "disable_bucket_update",
        "enable_lock_table_ssencryption",
        "disable_aws_client_checksums",
        "accesslogging_bucket_name",
@@ -258,8 +261,14 @@
                return err
        }
 
+       if !s3ConfigExtended.DisableBucketUpdate {
+               if err := updateS3BucketIfNecessary(s3Client, s3ConfigExtended, 
terragruntOptions); err != nil {
+                       return err
+               }
+       }
+
        if !s3ConfigExtended.SkipBucketVersioning {
-               if err := checkIfVersioningEnabled(s3Client, &s3Config, 
terragruntOptions); err != nil {
+               if _, err := checkIfVersioningEnabled(s3Client, &s3Config, 
terragruntOptions); err != nil {
                        return err
                }
        }
@@ -381,20 +390,207 @@
        return nil
 }
 
+func updateS3BucketIfNecessary(s3Client *s3.S3, config 
*ExtendedRemoteStateConfigS3, terragruntOptions *options.TerragruntOptions) 
error {
+       if !DoesS3BucketExist(s3Client, &config.remoteStateConfigS3.Bucket) {
+               return errors.WithStackTrace(fmt.Errorf("remote state S3 bucket 
%s does not exist or you don't have permissions to access it", 
config.remoteStateConfigS3.Bucket))
+       }
+
+       needUpdate, bucketUpdatesRequired, err := 
checkIfS3BucketNeedsUpdate(s3Client, config, terragruntOptions)
+       if err != nil {
+               return err
+       }
+
+       if !needUpdate {
+               terragruntOptions.Logger.Debug("S3 bucket is already up to 
date")
+               return nil
+       }
+
+       prompt := fmt.Sprintf("Remote state S3 bucket %s is out of date. Would 
you like Terragrunt to update it?", config.remoteStateConfigS3.Bucket)
+       shouldUpdateBucket, err := shell.PromptUserForYesNo(prompt, 
terragruntOptions)
+       if err != nil {
+               return err
+       }
+
+       if !shouldUpdateBucket {
+               return nil
+       }
+
+       if bucketUpdatesRequired.Versioning {
+               if config.SkipBucketVersioning {
+                       terragruntOptions.Logger.Debugf("Versioning is disabled 
for the remote state S3 bucket %s using 'skip_bucket_versioning' config.", 
config.remoteStateConfigS3.Bucket)
+               } else if err := EnableVersioningForS3Bucket(s3Client, 
&config.remoteStateConfigS3, terragruntOptions); err != nil {
+                       return err
+               }
+       }
+
+       if bucketUpdatesRequired.SSEEncryption {
+               if config.SkipBucketSSEncryption {
+                       terragruntOptions.Logger.Debugf("Server-Side Encryption 
is disabled for the remote state AWS S3 bucket %s using 
'skip_bucket_ssencryption' config.", config.remoteStateConfigS3.Bucket)
+               } else if err := EnableSSEForS3BucketWide(s3Client, config, 
terragruntOptions); err != nil {
+                       return err
+               }
+       }
+
+       if bucketUpdatesRequired.RootAccess {
+               if config.SkipBucketRootAccess {
+                       terragruntOptions.Logger.Debugf("Root access is 
disabled for the remote state S3 bucket %s using 'skip_bucket_root_access' 
config.", config.remoteStateConfigS3.Bucket)
+               } else if err := EnableRootAccesstoS3Bucket(s3Client, config, 
terragruntOptions); err != nil {
+                       return err
+               }
+       }
+
+       if bucketUpdatesRequired.EnforcedTLS {
+               if config.SkipBucketEnforcedTLS {
+                       terragruntOptions.Logger.Debugf("Enforced TLS is 
disabled for the remote state AWS S3 bucket %s using 'skip_bucket_enforced_tls' 
config.", config.remoteStateConfigS3.Bucket)
+               } else if err := EnableEnforcedTLSAccesstoS3Bucket(s3Client, 
config, terragruntOptions); err != nil {
+                       return err
+               }
+       }
+
+       if bucketUpdatesRequired.AccessLogging {
+               if config.SkipBucketAccessLogging {
+                       terragruntOptions.Logger.Debugf("Access logging is 
disabled for the remote state AWS S3 bucket %s using 
'skip_bucket_access_logging' config.", config.remoteStateConfigS3.Bucket)
+               } else {
+                       if config.AccessLoggingBucketName != "" {
+                               terragruntOptions.Logger.Debugf("Enabling 
bucket-wide Access Logging on AWS S3 bucket %s - using as TargetBucket %s", 
config.remoteStateConfigS3.Bucket, config.AccessLoggingBucketName)
+
+                               if err := 
CreateLogsS3BucketIfNecessary(s3Client, 
aws.String(config.AccessLoggingBucketName), terragruntOptions); err != nil {
+                                       terragruntOptions.Logger.Errorf("Could 
not create logs bucket %s for AWS S3 bucket %s", 
config.AccessLoggingBucketName, config.remoteStateConfigS3.Bucket)
+                                       return err
+                               }
+
+                               if err := 
EnablePublicAccessBlockingForS3Bucket(s3Client, config.AccessLoggingBucketName, 
terragruntOptions); err != nil {
+                                       return err
+                               }
+
+                               if err := 
EnableAccessLoggingForS3BucketWide(s3Client, &config.remoteStateConfigS3, 
terragruntOptions, config.AccessLoggingBucketName, 
config.AccessLoggingTargetPrefix); err != nil {
+                                       return err
+                               }
+                       } else {
+                               terragruntOptions.Logger.Debugf("Access Logging 
is disabled for the remote state AWS S3 bucket %s", 
config.remoteStateConfigS3.Bucket)
+                       }
+               }
+       }
+
+       if bucketUpdatesRequired.PublicAccess {
+               if err := EnablePublicAccessBlockingForS3Bucket(s3Client, 
config.remoteStateConfigS3.Bucket, terragruntOptions); err != nil {
+                       return err
+               }
+       }
+
+       return nil
+}
+
+type S3BucketUpdatesRequired struct {
+       Versioning    bool
+       SSEEncryption bool
+       RootAccess    bool
+       EnforcedTLS   bool
+       AccessLogging bool
+       PublicAccess  bool
+}
+
+func checkIfS3BucketNeedsUpdate(s3Client *s3.S3, config 
*ExtendedRemoteStateConfigS3, terragruntOptions *options.TerragruntOptions) 
(bool, S3BucketUpdatesRequired, error) {
+       var needUpdate []string
+       var configBucket S3BucketUpdatesRequired
+
+       if !config.SkipBucketVersioning {
+               enabled, err := checkIfVersioningEnabled(s3Client, 
&config.remoteStateConfigS3, terragruntOptions)
+               if err != nil {
+                       return false, configBucket, err
+               }
+
+               if !enabled {
+                       configBucket.Versioning = true
+                       needUpdate = append(needUpdate, "Bucket Versioning")
+               }
+       }
+
+       if !config.SkipBucketSSEncryption {
+               enabled, err := checkIfSSEForS3Enabled(s3Client, 
&config.remoteStateConfigS3, terragruntOptions)
+               if err != nil {
+                       return false, configBucket, err
+               }
+
+               if !enabled {
+                       configBucket.SSEEncryption = true
+                       needUpdate = append(needUpdate, "Bucket Server-Side 
Encryption")
+               }
+       }
+
+       if !config.SkipBucketRootAccess {
+               enabled, err := checkIfBucketRootAccess(s3Client, 
&config.remoteStateConfigS3, terragruntOptions)
+               if err != nil {
+                       return false, configBucket, err
+               }
+
+               if !enabled {
+                       configBucket.RootAccess = true
+                       needUpdate = append(needUpdate, "Bucket Root Access")
+               }
+       }
+
+       if !config.SkipBucketEnforcedTLS {
+               enabled, err := checkIfBucketEnforcedTLS(s3Client, 
&config.remoteStateConfigS3, terragruntOptions)
+               if err != nil {
+                       return false, configBucket, err
+               }
+
+               if !enabled {
+                       configBucket.EnforcedTLS = true
+                       needUpdate = append(needUpdate, "Bucket Enforced TLS")
+               }
+       }
+
+       if !config.SkipBucketAccessLogging && config.AccessLoggingBucketName != 
"" {
+               enabled, err := checkIfAccessLoggingForS3Enabled(s3Client, 
&config.remoteStateConfigS3, terragruntOptions)
+               if err != nil {
+                       return false, configBucket, err
+               }
+
+               if !enabled {
+                       configBucket.AccessLogging = true
+                       needUpdate = append(needUpdate, "Bucket Access Logging")
+               }
+       }
+
+       enabled, err := checkIfS3PublicAccessBlockingEnabled(s3Client, 
&config.remoteStateConfigS3, terragruntOptions)
+       if err != nil {
+               return false, configBucket, err
+       }
+       if !enabled {
+               configBucket.PublicAccess = true
+               needUpdate = append(needUpdate, "Bucket Public Access Blocking")
+       }
+
+       // show update message if any of the above configs are not set
+       if len(needUpdate) > 0 {
+               terragruntOptions.Logger.Warnf("The remote state S3 bucket %s 
needs to be updated:", config.remoteStateConfigS3.Bucket)
+               for _, update := range needUpdate {
+                       terragruntOptions.Logger.Warnf("  - %s", update)
+               }
+
+               return true, configBucket, nil
+       }
+
+       return false, configBucket, nil
+}
+
 // Check if versioning is enabled for the S3 bucket specified in the given 
config and warn the user if it is not
-func checkIfVersioningEnabled(s3Client *s3.S3, config *RemoteStateConfigS3, 
terragruntOptions *options.TerragruntOptions) error {
+func checkIfVersioningEnabled(s3Client *s3.S3, config *RemoteStateConfigS3, 
terragruntOptions *options.TerragruntOptions) (bool, error) {
        out, err := 
s3Client.GetBucketVersioning(&s3.GetBucketVersioningInput{Bucket: 
aws.String(config.Bucket)})
        if err != nil {
-               return errors.WithStackTrace(err)
+               return false, errors.WithStackTrace(err)
        }
 
        // NOTE: There must be a bug in the AWS SDK since out == nil when 
versioning is not enabled. In the future,
        // check the AWS SDK for updates to see if we can remove "out == nil 
||".
        if out == nil || out.Status == nil || *out.Status != 
s3.BucketVersioningStatusEnabled {
                terragruntOptions.Logger.Warnf("Versioning is not enabled for 
the remote state S3 bucket %s. We recommend enabling versioning so that you can 
roll back to previous versions of your Terraform state in case of error.", 
config.Bucket)
+               return false, nil
        }
 
-       return nil
+       return true, nil
 }
 
 // Create the given S3 bucket and enable versioning for it
@@ -442,7 +638,7 @@
 
        if config.SkipBucketSSEncryption {
                terragruntOptions.Logger.Debugf("Server-Side Encryption is 
disabled for the remote state AWS S3 bucket %s using 'skip_bucket_ssencryption' 
config.", config.remoteStateConfigS3.Bucket)
-       } else if err := EnableSSEForS3BucketWide(s3Client, 
&config.remoteStateConfigS3, terragruntOptions); err != nil {
+       } else if err := EnableSSEForS3BucketWide(s3Client, config, 
terragruntOptions); err != nil {
                return err
        }
 
@@ -502,7 +698,9 @@
        putBucketTaggingInput := s3.PutBucketTaggingInput{
                Bucket: aws.String(config.remoteStateConfigS3.Bucket),
                Tagging: &s3.Tagging{
-                       TagSet: tagsConverted}}
+                       TagSet: tagsConverted,
+               },
+       }
 
        _, err := s3Client.PutBucketTagging(&putBucketTaggingInput)
        if err != nil {
@@ -578,19 +776,43 @@
                return errors.WithStackTrace(err)
        }
 
-       rootS3Policy := map[string]interface{}{
-               "Version": "2012-10-17",
-               "Statement": []map[string]interface{}{
+       var policyInBucket aws_helper.Policy
+       policyOutput, err := s3Client.GetBucketPolicy(&s3.GetBucketPolicyInput{
+               Bucket: aws.String(bucket),
+       })
+       // If there's no policy, we need to create one
+       if err != nil {
+               terragruntOptions.Logger.Debugf("Policy not exists for bucket 
%s", bucket)
+       }
+
+       if policyOutput.Policy != nil {
+               terragruntOptions.Logger.Debugf("Policy already exists for 
bucket %s", bucket)
+               policyInBucket, err = 
aws_helper.UnmarshalPolicy(*policyOutput.Policy)
+               if err != nil {
+                       return errors.WithStackTrace(err)
+               }
+       }
+
+       for _, statement := range policyInBucket.Statement {
+               if statement.Sid == SidRootPolicy {
+                       terragruntOptions.Logger.Debugf("Policy for RootAccess 
already exists for bucket %s", bucket)
+                       return nil
+               }
+       }
+
+       rootS3Policy := aws_helper.Policy{
+               Version: "2012-10-17",
+               Statement: []aws_helper.Statement{
                        {
-                               "Sid":    "RootAccess",
-                               "Effect": "Allow",
-                               "Action": "s3:*",
-                               "Resource": []string{
+                               Sid:    SidRootPolicy,
+                               Effect: "Allow",
+                               Action: "s3:*",
+                               Resource: []string{
                                        "arn:" + partition + ":s3:::" + bucket,
                                        "arn:" + partition + ":s3:::" + bucket 
+ "/*",
                                },
-                               "Principal": map[string][]string{
-                                       "AWS": []string{
+                               Principal: map[string][]string{
+                                       "AWS": {
                                                "arn:" + partition + ":iam::" + 
accountID + ":root",
                                        },
                                },
@@ -598,7 +820,9 @@
                },
        }
 
-       policy, err := json.Marshal(rootS3Policy)
+       // Append the root s3 policy to the existing policy in the bucket
+       rootS3Policy.Statement = append(rootS3Policy.Statement, 
policyInBucket.Statement...)
+       policy, err := aws_helper.MarshalPolicy(rootS3Policy)
        if err != nil {
                return errors.WithStackTrace(err)
        }
@@ -615,6 +839,39 @@
        return nil
 }
 
+// Helper function to check if the root access policy is enabled for the bucket
+func checkIfBucketRootAccess(s3Client *s3.S3, config *RemoteStateConfigS3, 
terragruntOptions *options.TerragruntOptions) (bool, error) {
+       terragruntOptions.Logger.Debugf("Checking if bucket %s is have root 
access", config.Bucket)
+
+       policyOutput, err := s3Client.GetBucketPolicy(&s3.GetBucketPolicyInput{
+               Bucket: aws.String(config.Bucket),
+       })
+       if err != nil {
+               terragruntOptions.Logger.Debugf("Could not get policy for 
bucket %s", config.Bucket)
+               return false, nil
+       }
+
+       // If the bucket has no policy, it is not enforced
+       if policyOutput == nil {
+               return true, nil
+       }
+
+       policyInBucket, err := aws_helper.UnmarshalPolicy(*policyOutput.Policy)
+       if err != nil {
+               return false, errors.WithStackTrace(err)
+       }
+
+       for _, statement := range policyInBucket.Statement {
+               if statement.Sid == SidRootPolicy {
+                       terragruntOptions.Logger.Debugf("Policy for RootAccess 
already exists for bucket %s", config.Bucket)
+                       return true, nil
+               }
+       }
+
+       terragruntOptions.Logger.Debugf("Root access to bucket %s is not 
enabled", config.Bucket)
+       return false, nil
+}
+
 // Add a policy to enforce TLS based access to the bucket
 func EnableEnforcedTLSAccesstoS3Bucket(s3Client *s3.S3, config 
*ExtendedRemoteStateConfigS3, terragruntOptions *options.TerragruntOptions) 
error {
        bucket := config.remoteStateConfigS3.Bucket
@@ -625,28 +882,54 @@
                return errors.WithStackTrace(err)
        }
 
-       tlsS3Policy := map[string]interface{}{
-               "Version": "2012-10-17",
-               "Statement": []map[string]interface{}{
+       var policyInBucket aws_helper.Policy
+       policyOutput, err := s3Client.GetBucketPolicy(&s3.GetBucketPolicyInput{
+               Bucket: aws.String(bucket),
+       })
+       // If there's no policy, we need to create one
+       if err != nil {
+               terragruntOptions.Logger.Debugf("Policy not exists for bucket 
%s", bucket)
+       }
+
+       if policyOutput.Policy != nil {
+               terragruntOptions.Logger.Debugf("Policy already exists for 
bucket %s", bucket)
+               policyInBucket, err = 
aws_helper.UnmarshalPolicy(*policyOutput.Policy)
+               if err != nil {
+                       return errors.WithStackTrace(err)
+               }
+       }
+
+       for _, statement := range policyInBucket.Statement {
+               if statement.Sid == SidEnforcedTLSPolicy {
+                       terragruntOptions.Logger.Debugf("Policy for EnforceTLS 
already exists for bucket %s", bucket)
+                       return nil
+               }
+       }
+
+       tlsS3Policy := aws_helper.Policy{
+               Version: "2012-10-17",
+               Statement: []aws_helper.Statement{
                        {
-                               "Sid":    "AllowTLSRequestsOnly",
-                               "Action": "s3:*",
-                               "Effect": "Deny",
-                               "Resource": []string{
+                               Sid:       SidEnforcedTLSPolicy,
+                               Effect:    "Deny",
+                               Action:    "s3:*",
+                               Principal: "*",
+                               Resource: []string{
                                        "arn:" + partition + ":s3:::" + bucket,
                                        "arn:" + partition + ":s3:::" + bucket 
+ "/*",
                                },
-                               "Condition": map[string]interface{}{
+                               Condition: &map[string]interface{}{
                                        "Bool": map[string]interface{}{
                                                "aws:SecureTransport": "false",
                                        },
                                },
-                               "Principal": "*",
                        },
                },
        }
 
-       policy, err := json.Marshal(tlsS3Policy)
+       // Append the root s3 policy to the existing policy in the bucket
+       tlsS3Policy.Statement = append(tlsS3Policy.Statement, 
policyInBucket.Statement...)
+       policy, err := aws_helper.MarshalPolicy(tlsS3Policy)
        if err != nil {
                return errors.WithStackTrace(err)
        }
@@ -663,6 +946,47 @@
        return nil
 }
 
+// Helper function to check if the enforced TLS policy is enabled for the 
bucket
+func checkIfBucketEnforcedTLS(s3Client *s3.S3, config *RemoteStateConfigS3, 
terragruntOptions *options.TerragruntOptions) (bool, error) {
+       terragruntOptions.Logger.Debugf("Checking if bucket %s is enforced with 
TLS", config.Bucket)
+
+       policyOutput, err := s3Client.GetBucketPolicy(&s3.GetBucketPolicyInput{
+               Bucket: aws.String(config.Bucket),
+       })
+       if err != nil {
+               // S3 API error codes:
+               // 
http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
+               if aerr, ok := err.(awserr.Error); ok {
+                       // Enforced TLS policy if is not found bucket policy
+                       if aerr.Code() == "NoSuchBucketPolicy" {
+                               terragruntOptions.Logger.Debugf("Could not get 
policy for bucket %s", config.Bucket)
+                               return false, nil
+                       }
+               }
+
+               return false, errors.WithStackTrace(err)
+       }
+
+       if policyOutput.Policy == nil {
+               return true, nil
+       }
+
+       policyInBucket, err := aws_helper.UnmarshalPolicy(*policyOutput.Policy)
+       if err != nil {
+               return false, errors.WithStackTrace(err)
+       }
+
+       for _, statement := range policyInBucket.Statement {
+               if statement.Sid == SidEnforcedTLSPolicy {
+                       terragruntOptions.Logger.Debugf("Policy for EnforcedTLS 
already exists for bucket %s", config.Bucket)
+                       return true, nil
+               }
+       }
+
+       terragruntOptions.Logger.Debugf("Bucket %s is not enforced with TLS 
Policy", config.Bucket)
+       return false, nil
+}
+
 // Enable versioning for the S3 bucket specified in the given config
 func EnableVersioningForS3Bucket(s3Client *s3.S3, config *RemoteStateConfigS3, 
terragruntOptions *options.TerragruntOptions) error {
        terragruntOptions.Logger.Debugf("Enabling versioning on S3 bucket %s", 
config.Bucket)
@@ -681,24 +1005,64 @@
 }
 
 // Enable bucket-wide Server-Side Encryption for the AWS S3 bucket specified 
in the given config
-func EnableSSEForS3BucketWide(s3Client *s3.S3, config *RemoteStateConfigS3, 
terragruntOptions *options.TerragruntOptions) error {
-       terragruntOptions.Logger.Debugf("Enabling bucket-wide SSE on AWS S3 
bucket %s", config.Bucket)
+func EnableSSEForS3BucketWide(s3Client *s3.S3, config 
*ExtendedRemoteStateConfigS3, terragruntOptions *options.TerragruntOptions) 
error {
+       terragruntOptions.Logger.Debugf("Enabling bucket-wide SSE on AWS S3 
bucket %s", config.remoteStateConfigS3.Bucket)
+
        // Encrypt with KMS by default
-       defEnc := &s3.ServerSideEncryptionByDefault{SSEAlgorithm: 
aws.String(s3.ServerSideEncryptionAwsKms)}
+       accountID, err := 
aws_helper.GetAWSAccountID(config.GetAwsSessionConfig(), terragruntOptions)
+       if err != nil {
+               return errors.WithStackTrace(err)
+       }
+
+       kmsKeyID := fmt.Sprintf("arn:aws:kms:%s:%s:alias/aws/s3", 
config.remoteStateConfigS3.Region, accountID)
+       defEnc := &s3.ServerSideEncryptionByDefault{
+               SSEAlgorithm:   aws.String(s3.ServerSideEncryptionAwsKms),
+               KMSMasterKeyID: aws.String(kmsKeyID),
+       }
+
        rule := 
&s3.ServerSideEncryptionRule{ApplyServerSideEncryptionByDefault: defEnc}
        rules := []*s3.ServerSideEncryptionRule{rule}
        serverConfig := &s3.ServerSideEncryptionConfiguration{Rules: rules}
-       input := &s3.PutBucketEncryptionInput{Bucket: 
aws.String(config.Bucket), ServerSideEncryptionConfiguration: serverConfig}
+       input := &s3.PutBucketEncryptionInput{Bucket: 
aws.String(config.remoteStateConfigS3.Bucket), 
ServerSideEncryptionConfiguration: serverConfig}
 
-       _, err := s3Client.PutBucketEncryption(input)
+       _, err = s3Client.PutBucketEncryption(input)
        if err != nil {
                return errors.WithStackTrace(err)
        }
 
-       terragruntOptions.Logger.Debugf("Enabled bucket-wide SSE on AWS S3 
bucket %s", config.Bucket)
+       terragruntOptions.Logger.Debugf("Enabled bucket-wide SSE on AWS S3 
bucket %s", config.remoteStateConfigS3.Bucket)
        return nil
 }
 
+func checkIfSSEForS3Enabled(s3Client *s3.S3, config *RemoteStateConfigS3, 
terragruntOptions *options.TerragruntOptions) (bool, error) {
+       terragruntOptions.Logger.Debugf("Checking if SSE is enabled for AWS S3 
bucket %s", config.Bucket)
+
+       input := &s3.GetBucketEncryptionInput{Bucket: aws.String(config.Bucket)}
+       output, err := s3Client.GetBucketEncryption(input)
+       if err != nil {
+               terragruntOptions.Logger.Debugf("Error checking if SSE is 
enabled for AWS S3 bucket %s: %s", config.Bucket, err.Error())
+               return false, nil
+       }
+
+       if output.ServerSideEncryptionConfiguration == nil {
+               return false, nil
+       }
+
+       for _, rule := range output.ServerSideEncryptionConfiguration.Rules {
+               if rule.ApplyServerSideEncryptionByDefault != nil {
+                       if rule.ApplyServerSideEncryptionByDefault.SSEAlgorithm 
!= nil {
+                               if 
*rule.ApplyServerSideEncryptionByDefault.SSEAlgorithm == 
s3.ServerSideEncryptionAwsKms {
+                                       return true, nil
+                               }
+
+                               return false, nil
+                       }
+               }
+       }
+
+       return false, nil
+}
+
 // Enable bucket-wide Access Logging for the AWS S3 bucket specified in the 
given config
 func EnableAccessLoggingForS3BucketWide(s3Client *s3.S3, config 
*RemoteStateConfigS3, terragruntOptions *options.TerragruntOptions, logsBucket 
string, logsBucketPrefix string) error {
        if err := configureBucketAccessLoggingAcl(s3Client, 
aws.String(logsBucket), terragruntOptions); err != nil {
@@ -725,6 +1089,23 @@
        return nil
 }
 
+func checkIfAccessLoggingForS3Enabled(s3Client *s3.S3, config 
*RemoteStateConfigS3, terragruntOptions *options.TerragruntOptions) (bool, 
error) {
+       terragruntOptions.Logger.Debugf("Checking if Access Logging is enabled 
for AWS S3 bucket %s", config.Bucket)
+
+       input := &s3.GetBucketLoggingInput{Bucket: aws.String(config.Bucket)}
+       output, err := s3Client.GetBucketLogging(input)
+       if err != nil {
+               terragruntOptions.Logger.Debugf("Error checking if Access 
Logging is enabled for AWS S3 bucket %s: %s", config.Bucket, err.Error())
+               return false, nil
+       }
+
+       if output.LoggingEnabled == nil {
+               return false, nil
+       }
+
+       return true, nil
+}
+
 // Block all public access policies on the bucket and objects. These settings 
ensure that a misconfiguration of the
 // bucket or objects will not accidentally enable public access to those 
items. See
 // 
https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html
 for more information.
@@ -750,6 +1131,43 @@
        return nil
 }
 
+func checkIfS3PublicAccessBlockingEnabled(s3Client *s3.S3, config 
*RemoteStateConfigS3, terragruntOptions *options.TerragruntOptions) (bool, 
error) {
+       terragruntOptions.Logger.Debugf("Checking if S3 bucket %s is configured 
to block public access", config.Bucket)
+       output, err := 
s3Client.GetPublicAccessBlock(&s3.GetPublicAccessBlockInput{
+               Bucket: aws.String(config.Bucket),
+       })
+       if err != nil {
+               if aerr, ok := err.(awserr.Error); ok {
+                       // Enforced block public access if is not found bucket 
policy
+                       if aerr.Code() == 
"NoSuchPublicAccessBlockConfiguration" {
+                               terragruntOptions.Logger.Debugf("Could not get 
public access block for bucket %s", config.Bucket)
+                               return false, nil
+                       }
+               }
+
+               return false, errors.WithStackTrace(err)
+       }
+
+       if output.PublicAccessBlockConfiguration == nil {
+               return false, nil
+       }
+
+       if !*output.PublicAccessBlockConfiguration.BlockPublicAcls {
+               return false, nil
+       }
+       if !*output.PublicAccessBlockConfiguration.BlockPublicPolicy {
+               return false, nil
+       }
+       if !*output.PublicAccessBlockConfiguration.IgnorePublicAcls {
+               return false, nil
+       }
+       if !*output.PublicAccessBlockConfiguration.RestrictPublicBuckets {
+               return false, nil
+       }
+
+       return true, nil
+}
+
 // To enable access logging in an S3 bucket, you must grant WRITE and READ_ACP 
permissions to the Log Delivery
 // Group. For more info, see:
 // 
https://docs.aws.amazon.com/AmazonS3/latest/dev/enable-logging-programming.html
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/terragrunt-0.36.10/remote/remote_state_s3_test.go 
new/terragrunt-0.37.1/remote/remote_state_s3_test.go
--- old/terragrunt-0.36.10/remote/remote_state_s3_test.go       2022-05-04 
09:33:29.000000000 +0200
+++ new/terragrunt-0.37.1/remote/remote_state_s3_test.go        2022-05-13 
16:04:48.000000000 +0200
@@ -276,6 +276,7 @@
                                "skip_bucket_ssencryption":       false,
                                "skip_bucket_root_access":        false,
                                "skip_bucket_enforced_tls":       false,
+                               "disable_bucket_update":          true,
                                "enable_lock_table_ssencryption": true,
                                "disable_aws_client_checksums":   false,
                                "accesslogging_bucket_name":      "test",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/terragrunt-0.36.10/remote/remote_state_test.go 
new/terragrunt-0.37.1/remote/remote_state_test.go
--- old/terragrunt-0.36.10/remote/remote_state_test.go  2022-05-04 
09:33:29.000000000 +0200
+++ new/terragrunt-0.37.1/remote/remote_state_test.go   2022-05-13 
16:04:48.000000000 +0200
@@ -109,8 +109,8 @@
        t.Parallel()
 
        remoteStates := []RemoteState{
-               RemoteState{Backend: "s3"},
-               RemoteState{Backend: "gcs"},
+               {Backend: "s3"},
+               {Backend: "gcs"},
        }
 
        for _, state := range remoteStates {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/terragrunt-0.36.10/remote/terraform_state_file_test.go 
new/terragrunt-0.37.1/remote/terraform_state_file_test.go
--- old/terragrunt-0.36.10/remote/terraform_state_file_test.go  2022-05-04 
09:33:29.000000000 +0200
+++ new/terragrunt-0.37.1/remote/terraform_state_file_test.go   2022-05-13 
16:04:48.000000000 +0200
@@ -33,7 +33,7 @@
                Serial:  0,
                Backend: nil,
                Modules: []TerraformStateModule{
-                       TerraformStateModule{
+                       {
                                Path:      []string{"root"},
                                Outputs:   map[string]interface{}{},
                                Resources: map[string]interface{}{},
@@ -90,7 +90,7 @@
                        },
                },
                Modules: []TerraformStateModule{
-                       TerraformStateModule{
+                       {
                                Path:      []string{"root"},
                                Outputs:   map[string]interface{}{},
                                Resources: map[string]interface{}{},
@@ -220,7 +220,7 @@
                        },
                },
                Modules: []TerraformStateModule{
-                       TerraformStateModule{
+                       {
                                Path: []string{"root"},
                                Outputs: map[string]interface{}{
                                        "key1": "value1",
@@ -229,7 +229,7 @@
                                },
                                Resources: map[string]interface{}{},
                        },
-                       TerraformStateModule{
+                       {
                                Path: []string{"root", 
"module_with_outputs_no_resources"},
                                Outputs: map[string]interface{}{
                                        "key1": "",
@@ -237,7 +237,7 @@
                                },
                                Resources: map[string]interface{}{},
                        },
-                       TerraformStateModule{
+                       {
                                Path:    []string{"root", 
"module_with_resources_no_outputs"},
                                Outputs: map[string]interface{}{},
                                Resources: map[string]interface{}{
@@ -277,7 +277,7 @@
                                        },
                                },
                        },
-                       TerraformStateModule{
+                       {
                                Path:      []string{"root", "module_level_1", 
"module_level_2"},
                                Outputs:   map[string]interface{}{},
                                Resources: map[string]interface{}{},

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/terragrunt/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.terragrunt.new.1538/vendor.tar.gz differ: char 5, 
line 1

Reply via email to