Skip to content
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

Forces replacement #7

Merged
merged 4 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 41 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,41 @@
# tfreveal

[![Test Status](https://github.com/breml/tfreveal/workflows/Main/badge.svg)](https://github.com/breml/tfreveal/actions?query=workflow%3AMain)
[![Go Report Card](https://goreportcard.com/badge/github.com/breml/tfreveal)](https://goreportcard.com/report/github.com/breml/tfreveal) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

tfreveal is an open-source tool designed to enhance the visibility of Terraform
plan files by displaying all differences in resources and outputs, including
sensitive values. Unlike Terraform, which hides sensitive data, tfreveal reveals
these values to ensure complete transparency in your infrastructure changes.

## Motivation

Terraform does mask sensitive values in the output (e.g. from `terraform plan`)
in order to protect them from being revealed to 3rd parties.
in order to protect them from being revealed to unauthorized 3rd parties.

Sometimes it is neccessary to see the exact changes, Terraform will perform to the
infrastructure including all the changes to sensitive values. So far, Terraform
does not provide a feature to forcefully unmask the sensitive values in the
But sometimes it is neccessary to see the exact changes, Terraform will perform
to the infrastructure including all the changes to sensitive values. In
particular, if one observes drift between the Terraform state and the actual
state of the infrastructure, this becomes inevitable. So far, Terraform does not
provide a feature to forcefully unmask the sensitive values in the
[concise diff plan outputs](https://www.hashicorp.com/blog/terraform-0-14-adds-a-new-concise-diff-format-to-terraform-plans).

The general advice given by the Terraform maintainers is to use the JSON output
in such cases. While the JSON output does provide all the necessary information,
it is not perticularely easy to read for humans and to spot small differences.
It gets even more complicated, if the sensitive values contain larger JSON
encoded values.
It gets even more complicated, if the changes are contained in larger JSON
encoded values, that are marked as sensitive.

There exists instructions using for example `jq`, but the process stays manual,
cumbersome and error prone.

`tfreveal` is here to fix this and provide an easy way to show the concise diff
plan outputs with all sensitive values revealed.

## Installation

Download the latest release from the [releases page](https://github.com/breml/tfreveal/releases).

## Usage

The plan file generated from Terraform can be directly piped to `tfreveal`:
Expand All @@ -36,6 +53,24 @@ $ terraform show -json plan.out > plan.json
$ tfreveal plan.json
```

## Development

The task to update the test data and the golden files is provided in the
`Taskfile.yml` and can be executed by running `task gen-all`. This requires the
`task` tool to be installed. Please refer to the
[official documentation](https://taskfile.dev/installation/).

Additionally the `terraform` command needs to be present in the `PATH`. Follow
the [official installation instructions](https://developer.hashicorp.com/terraform/install).

## Author

Copyright 2024 by Lucas Bremgartner ([breml](https://github.com/breml))

## License

[MIT License](LICENSE)

## Trademarks

All other trademarks referenced herein are the property of their respective owners.
30 changes: 30 additions & 0 deletions format.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,42 @@ func (a *App) diff(change *tfjson.Change) string {
panic(err)
}

replacePaths := make([]string, 0, len(change.ReplacePaths))
for _, replacePath := range change.ReplacePaths {
rp := replacePath.([]any)
var path string
for _, pathSegment := range rp {
path += "/" + fmt.Sprint(pathSegment)
}
replacePaths = append(replacePaths, path)
}

buf := &strings.Builder{}
formatter := jsondiffprinter.NewTerraformFormatter(buf,
jsondiffprinter.WithIndentation(" "),
jsondiffprinter.WithHideUnchanged(true),
jsondiffprinter.WithJSONinJSONCompare(compare),
jsondiffprinter.WithColor(!a.noColor),
jsondiffprinter.WithPatchSeriesPostProcess(func(diff jsondiffprinter.Patch) jsondiffprinter.Patch {
colorize := colorstring.Colorize{
Colors: colorstring.DefaultColors,
Disable: a.noColor,
}

outerLoop:
for _, path := range replacePaths {
for i := range diff {
if diff[i].Path.String() == path {
if diff[i].Metadata == nil {
diff[i].Metadata = make(map[string]string, 0)
}
diff[i].Metadata["note"] = colorize.Color(" [light_red]# forces replacement[reset]")
continue outerLoop
}
}
}
return diff
}),
)
err = formatter.Format(change.Before, patch)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/breml/tfreveal
go 1.22.3

require (
github.com/breml/jsondiffprinter v0.0.7
github.com/breml/jsondiffprinter v0.0.8
github.com/ghetzel/go-stockutil v1.11.4
github.com/hashicorp/terraform-json v0.22.1
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/breml/jsondiffprinter v0.0.7 h1:R2DMEYnyn6p7Y+u8tYiGYxiuETgO6qmG0uGHyWKviaQ=
github.com/breml/jsondiffprinter v0.0.7/go.mod h1:XuyU5sGP+XDNFHnhuyOT67mRBUUHtJ8OmjztxNuXgL8=
github.com/breml/jsondiffprinter v0.0.8 h1:+FE3r92haHtqDSfjq1l8JRAKmEARVEeajD4Ud0YqVGQ=
github.com/breml/jsondiffprinter v0.0.8/go.mod h1:XuyU5sGP+XDNFHnhuyOT67mRBUUHtJ8OmjztxNuXgL8=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
Expand Down
1 change: 0 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ Resource actions are indicated with the following symbols:
[red]-[reset]/[green]+[reset] destroy and then create replacement
[green]+[reset]/[red]-[reset] create replacement and then destroy
`)
_ = executionPlanLegend

cliapp := &cli.App{
Name: "tfreveal",
Expand Down
6 changes: 3 additions & 3 deletions testdata/advanced/output.golden
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,22 @@ Changes to Resources:
- string_removed = "removed"
# (4 unchanged attribute hidden)
}
)
) # forces replacement
~ content_base64sha256 = "nIMhVlzPvgCIzeahBGJ/jEJLuCBuwIqx78vltuKjcyw=" -> "(known after apply)"
~ content_base64sha512 = "WDetH1vI/Yy0tu49ZCyW/WySxstlQc3+T7vX0Ei0UaLvLKsd884Djd3raxFJS66NMgFZc1bpSxPKKDXmgz9drA==" -> "(known after apply)"
~ content_md5 = "6f61fcba1ffd2b366fe358450f93b952" -> "(known after apply)"
~ content_sha1 = "4dfb08a62fbd3d8737cd6a11c2360df3953dda51" -> "(known after apply)"
~ content_sha256 = "9c8321565ccfbe0088cde6a104627f8c424bb8206ec08ab1efcbe5b6e2a3732c" -> "(known after apply)"
~ content_sha512 = "5837ad1f5bc8fd8cb4b6ee3d642c96fd6c92c6cb6541cdfe4fbbd7d048b451a2ef2cab1df3ce038dddeb6b11494bae8d3201597356e94b13ca2835e6833f5dac" -> "(known after apply)"
~ file_permission = "0777" -> "0660"
~ file_permission = "0777" -> "0660" # forces replacement
~ id = "4dfb08a62fbd3d8737cd6a11c2360df3953dda51" -> "(known after apply)"
# (5 unchanged attribute hidden)
}

# null_resource.cluster must be replaced
-/+ null_resource.cluster = {
~ id = "7713440656663291188" -> "(known after apply)"
triggers = {
triggers = { # forces replacement
~ secret = "secure" -> "still secure"
}
}
Expand Down
2 changes: 1 addition & 1 deletion testdata/resource_replace/output.golden
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Changes to Resources:
# null_resource.cluster must be replaced
-/+ null_resource.cluster = {
~ id = "5350362168280616586" -> "(known after apply)"
triggers = {
triggers = { # forces replacement
~ secret = "secure" -> "very very secure"
}
}
Expand Down
2 changes: 1 addition & 1 deletion testdata/sensitive/output.golden
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Changes to Resources:
# null_resource.sensitive must be replaced
-/+ null_resource.sensitive = {
~ id = "4190156157480914441" -> "(known after apply)"
triggers = {
triggers = { # forces replacement
~ secret = "some secret value" -> "new secret value"
}
}
Expand Down