diff --git a/.changes/unreleased/FEATURES-20230209-110755.yaml b/.changes/unreleased/FEATURES-20230209-110755.yaml new file mode 100644 index 00000000..dd785ea9 --- /dev/null +++ b/.changes/unreleased/FEATURES-20230209-110755.yaml @@ -0,0 +1,6 @@ +kind: FEATURES +body: 'resource/local_file: added support for `MD5`, `SHA1`, `SHA256`, and `SHA512` + checksum outputs.' +time: 2023-02-09T11:07:55.67622-05:00 +custom: + Issue: "142" diff --git a/.changes/unreleased/FEATURES-20230209-110940.yaml b/.changes/unreleased/FEATURES-20230209-110940.yaml new file mode 100644 index 00000000..26bf9278 --- /dev/null +++ b/.changes/unreleased/FEATURES-20230209-110940.yaml @@ -0,0 +1,6 @@ +kind: FEATURES +body: 'resource/local_sensitive_file: added support for `MD5`, `SHA1`, `SHA256`, and + `SHA512` checksum outputs.' +time: 2023-02-09T11:09:40.757015-05:00 +custom: + Issue: "142" diff --git a/.changes/unreleased/FEATURES-20230209-111044.yaml b/.changes/unreleased/FEATURES-20230209-111044.yaml new file mode 100644 index 00000000..b199192a --- /dev/null +++ b/.changes/unreleased/FEATURES-20230209-111044.yaml @@ -0,0 +1,6 @@ +kind: FEATURES +body: 'data-source/local_file: added support for `MD5`, `SHA1`, `SHA256`, and `SHA512` + checksum outputs.' +time: 2023-02-09T11:10:44.260895-05:00 +custom: + Issue: "142" diff --git a/.changes/unreleased/FEATURES-20230209-111108.yaml b/.changes/unreleased/FEATURES-20230209-111108.yaml new file mode 100644 index 00000000..8ca8a6ce --- /dev/null +++ b/.changes/unreleased/FEATURES-20230209-111108.yaml @@ -0,0 +1,6 @@ +kind: FEATURES +body: 'data-source/local_sensitive-file: added support for `MD5`, `SHA1`, `SHA256`, + and `SHA512` checksum outputs.' +time: 2023-02-09T11:11:08.992066-05:00 +custom: + Issue: "142" diff --git a/docs/data-sources/file.md b/docs/data-sources/file.md index bf43ca5a..ce9a064e 100644 --- a/docs/data-sources/file.md +++ b/docs/data-sources/file.md @@ -35,4 +35,10 @@ resource "aws_s3_object" "shared_zip" { - `content` (String) Raw content of the file that was read, as UTF-8 encoded string. Files that do not contain UTF-8 text will have invalid UTF-8 sequences in `content` replaced with the Unicode replacement character. - `content_base64` (String) Base64 encoded version of the file content (use this when dealing with binary data). -- `id` (String) The hexadecimal encoding of the checksum of the file content. \ No newline at end of file +- `content_base64sha256` (String) Base64 encoded SHA256 checksum of file content. +- `content_base64sha512` (String) Base64 encoded SHA512 checksum of file content. +- `content_md5` (String) MD5 checksum of file content. +- `content_sha1` (String) SHA1 checksum of file content. +- `content_sha256` (String) SHA256 checksum of file content. +- `content_sha512` (String) SHA512 checksum of file content. +- `id` (String) The hexadecimal encoding of the SHA1 checksum of the file content. \ No newline at end of file diff --git a/docs/data-sources/sensitive_file.md b/docs/data-sources/sensitive_file.md index a727606a..83da4be7 100644 --- a/docs/data-sources/sensitive_file.md +++ b/docs/data-sources/sensitive_file.md @@ -38,4 +38,10 @@ resource "aws_s3_object" "shared_zip" { - `content` (String, Sensitive) Raw content of the file that was read, as UTF-8 encoded string. Files that do not contain UTF-8 text will have invalid UTF-8 sequences in `content` replaced with the Unicode replacement character. - `content_base64` (String, Sensitive) Base64 encoded version of the file content (use this when dealing with binary data). -- `id` (String) The hexadecimal encoding of the checksum of the file content \ No newline at end of file +- `content_base64sha256` (String) Base64 encoded SHA256 checksum of file content. +- `content_base64sha512` (String) Base64 encoded SHA512 checksum of file content. +- `content_md5` (String) MD5 checksum of file content. +- `content_sha1` (String) SHA1 checksum of file content. +- `content_sha256` (String) SHA256 checksum of file content. +- `content_sha512` (String) SHA512 checksum of file content. +- `id` (String) The hexadecimal encoding of the SHA1 checksum of the file content. \ No newline at end of file diff --git a/docs/resources/file.md b/docs/resources/file.md index d9094f46..c7a340a4 100644 --- a/docs/resources/file.md +++ b/docs/resources/file.md @@ -67,4 +67,10 @@ resource "local_file" "foo" { ### Read-Only -- `id` (String) The hexadecimal encoding of the checksum of the file content \ No newline at end of file +- `content_base64sha256` (String) Base64 encoded SHA256 checksum of file content. +- `content_base64sha512` (String) Base64 encoded SHA512 checksum of file content. +- `content_md5` (String) MD5 checksum of file content. +- `content_sha1` (String) SHA1 checksum of file content. +- `content_sha256` (String) SHA256 checksum of file content. +- `content_sha512` (String) SHA512 checksum of file content. +- `id` (String) The hexadecimal encoding of the SHA1 checksum of the file content. \ No newline at end of file diff --git a/docs/resources/sensitive_file.md b/docs/resources/sensitive_file.md index 1f19a57f..8f211dfe 100644 --- a/docs/resources/sensitive_file.md +++ b/docs/resources/sensitive_file.md @@ -61,4 +61,10 @@ resource "local_sensitive_file" "foo" { ### Read-Only -- `id` (String) The hexadecimal encoding of the checksum of the file content \ No newline at end of file +- `content_base64sha256` (String) Base64 encoded SHA256 checksum of file content. +- `content_base64sha512` (String) Base64 encoded SHA512 checksum of file content. +- `content_md5` (String) MD5 checksum of file content. +- `content_sha1` (String) SHA1 checksum of file content. +- `content_sha256` (String) SHA256 checksum of file content. +- `content_sha512` (String) SHA512 checksum of file content. +- `id` (String) The hexadecimal encoding of the SHA1 checksum of the file content. \ No newline at end of file diff --git a/internal/provider/data_source_local_file.go b/internal/provider/data_source_local_file.go index de24e2f4..1c4db19c 100644 --- a/internal/provider/data_source_local_file.go +++ b/internal/provider/data_source_local_file.go @@ -2,9 +2,7 @@ package provider import ( "context" - "crypto/sha1" "encoding/base64" - "encoding/hex" "fmt" "os" @@ -41,7 +39,31 @@ func (n *localFileDataSource) Schema(ctx context.Context, req datasource.SchemaR Computed: true, }, "id": schema.StringAttribute{ - Description: "The hexadecimal encoding of the checksum of the file content.", + Description: "The hexadecimal encoding of the SHA1 checksum of the file content.", + Computed: true, + }, + "content_md5": schema.StringAttribute{ + Description: "MD5 checksum of file content.", + Computed: true, + }, + "content_sha1": schema.StringAttribute{ + Description: "SHA1 checksum of file content.", + Computed: true, + }, + "content_sha256": schema.StringAttribute{ + Description: "SHA256 checksum of file content.", + Computed: true, + }, + "content_base64sha256": schema.StringAttribute{ + Description: "Base64 encoded SHA256 checksum of file content.", + Computed: true, + }, + "content_sha512": schema.StringAttribute{ + Description: "SHA512 checksum of file content.", + Computed: true, + }, + "content_base64sha512": schema.StringAttribute{ + Description: "Base64 encoded SHA512 checksum of file content.", Computed: true, }, }, @@ -75,22 +97,34 @@ func (n *localFileDataSource) Read(ctx context.Context, req datasource.ReadReque return } - //calculate the checksum of file content - checksum := sha1.Sum(content) + //calculate the checksums of file content + checksums := genFileChecksums(content) state := localFileDataSourceModelV0{ - Filename: config.Filename, - Content: types.StringValue(string(content)), - ContentBase64: types.StringValue(base64.StdEncoding.EncodeToString(content)), - ID: types.StringValue(hex.EncodeToString(checksum[:])), + Filename: config.Filename, + Content: types.StringValue(string(content)), + ContentBase64: types.StringValue(base64.StdEncoding.EncodeToString(content)), + ID: types.StringValue(checksums.sha1Hex), + ContentMd5: types.StringValue(checksums.md5Hex), + ContentSha1: types.StringValue(checksums.sha1Hex), + ContentSha256: types.StringValue(checksums.sha256Hex), + ContentBase64sha256: types.StringValue(checksums.sha256Base64), + ContentSha512: types.StringValue(checksums.sha512Hex), + ContentBase64sha512: types.StringValue(checksums.sha512Base64), } diags = resp.State.Set(ctx, state) resp.Diagnostics.Append(diags...) } type localFileDataSourceModelV0 struct { - Filename types.String `tfsdk:"filename"` - Content types.String `tfsdk:"content"` - ContentBase64 types.String `tfsdk:"content_base64"` - ID types.String `tfsdk:"id"` + Filename types.String `tfsdk:"filename"` + Content types.String `tfsdk:"content"` + ContentBase64 types.String `tfsdk:"content_base64"` + ID types.String `tfsdk:"id"` + ContentMd5 types.String `tfsdk:"content_md5"` + ContentSha1 types.String `tfsdk:"content_sha1"` + ContentSha256 types.String `tfsdk:"content_sha256"` + ContentBase64sha256 types.String `tfsdk:"content_base64sha256"` + ContentSha512 types.String `tfsdk:"content_sha512"` + ContentBase64sha512 types.String `tfsdk:"content_base64sha512"` } diff --git a/internal/provider/data_source_local_file_test.go b/internal/provider/data_source_local_file_test.go index 756f8793..322b5e3e 100644 --- a/internal/provider/data_source_local_file_test.go +++ b/internal/provider/data_source_local_file_test.go @@ -9,6 +9,7 @@ import ( func TestLocalFileDataSource(t *testing.T) { content := "This is some content" + checkSums := genFileChecksums([]byte(content)) config := ` data "local_file" "file" { @@ -24,6 +25,12 @@ func TestLocalFileDataSource(t *testing.T) { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("data.local_file.file", "content", content), resource.TestCheckResourceAttr("data.local_file.file", "content_base64", base64.StdEncoding.EncodeToString([]byte(content))), + resource.TestCheckResourceAttr("data.local_file.file", "content_md5", checkSums.md5Hex), + resource.TestCheckResourceAttr("data.local_file.file", "content_sha1", checkSums.sha1Hex), + resource.TestCheckResourceAttr("data.local_file.file", "content_sha256", checkSums.sha256Hex), + resource.TestCheckResourceAttr("data.local_file.file", "content_base64sha256", checkSums.sha256Base64), + resource.TestCheckResourceAttr("data.local_file.file", "content_sha512", checkSums.sha512Hex), + resource.TestCheckResourceAttr("data.local_file.file", "content_base64sha512", checkSums.sha512Base64), ), }, }, diff --git a/internal/provider/data_source_local_sensitive_file.go b/internal/provider/data_source_local_sensitive_file.go index 12927d0f..cb2f5d92 100644 --- a/internal/provider/data_source_local_sensitive_file.go +++ b/internal/provider/data_source_local_sensitive_file.go @@ -45,7 +45,31 @@ func (n *localSensitiveFileDataSource) Schema(ctx context.Context, req datasourc Computed: true, }, "id": schema.StringAttribute{ - Description: "The hexadecimal encoding of the checksum of the file content", + Description: "The hexadecimal encoding of the SHA1 checksum of the file content.", + Computed: true, + }, + "content_md5": schema.StringAttribute{ + Description: "MD5 checksum of file content.", + Computed: true, + }, + "content_sha1": schema.StringAttribute{ + Description: "SHA1 checksum of file content.", + Computed: true, + }, + "content_sha256": schema.StringAttribute{ + Description: "SHA256 checksum of file content.", + Computed: true, + }, + "content_base64sha256": schema.StringAttribute{ + Description: "Base64 encoded SHA256 checksum of file content.", + Computed: true, + }, + "content_sha512": schema.StringAttribute{ + Description: "SHA512 checksum of file content.", + Computed: true, + }, + "content_base64sha512": schema.StringAttribute{ + Description: "Base64 encoded SHA512 checksum of file content.", Computed: true, }, }, diff --git a/internal/provider/data_source_local_sensitive_file_test.go b/internal/provider/data_source_local_sensitive_file_test.go index 58780e9a..5517a141 100644 --- a/internal/provider/data_source_local_sensitive_file_test.go +++ b/internal/provider/data_source_local_sensitive_file_test.go @@ -11,6 +11,7 @@ import ( func TestLocalFileSensitiveDataSource(t *testing.T) { testFileContent := "This is some content" + checkSums := genFileChecksums([]byte(testFileContent)) config := ` data "local_sensitive_file" "file" { @@ -26,6 +27,12 @@ func TestLocalFileSensitiveDataSource(t *testing.T) { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("data.local_sensitive_file.file", "content", testFileContent), resource.TestCheckResourceAttr("data.local_sensitive_file.file", "content_base64", base64.StdEncoding.EncodeToString([]byte(testFileContent))), + resource.TestCheckResourceAttr("data.local_sensitive_file.file", "content_md5", checkSums.md5Hex), + resource.TestCheckResourceAttr("data.local_sensitive_file.file", "content_sha1", checkSums.sha1Hex), + resource.TestCheckResourceAttr("data.local_sensitive_file.file", "content_sha256", checkSums.sha256Hex), + resource.TestCheckResourceAttr("data.local_sensitive_file.file", "content_base64sha256", checkSums.sha256Base64), + resource.TestCheckResourceAttr("data.local_sensitive_file.file", "content_sha512", checkSums.sha512Hex), + resource.TestCheckResourceAttr("data.local_sensitive_file.file", "content_base64sha512", checkSums.sha512Base64), ), }, }, diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 3339a592..a89319cb 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -2,6 +2,12 @@ package provider import ( "context" + "crypto/md5" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "encoding/base64" + "encoding/hex" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/provider" @@ -44,3 +50,32 @@ func (p *localProvider) Resources(ctx context.Context) []func() resource.Resourc func (p *localProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) { resp.Schema = schema.Schema{} } + +type fileChecksums struct { + md5Hex string + sha1Hex string + sha256Hex string + sha256Base64 string + sha512Hex string + sha512Base64 string +} + +func genFileChecksums(data []byte) fileChecksums { + var checksums fileChecksums + + md5Sum := md5.Sum(data) + checksums.md5Hex = hex.EncodeToString(md5Sum[:]) + + sha1Sum := sha1.Sum(data) + checksums.sha1Hex = hex.EncodeToString(sha1Sum[:]) + + sha256Sum := sha256.Sum256(data) + checksums.sha256Hex = hex.EncodeToString(sha256Sum[:]) + checksums.sha256Base64 = base64.StdEncoding.EncodeToString(sha256Sum[:]) + + sha512Sum := sha512.Sum512(data) + checksums.sha512Hex = hex.EncodeToString(sha512Sum[:]) + checksums.sha512Base64 = base64.StdEncoding.EncodeToString(sha512Sum[:]) + + return checksums +} diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index 44c4e4b2..9517c5f0 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -42,8 +42,15 @@ func checkFileCreation(resourceName, path string) resource.TestCheckFunc { if err != nil { return fmt.Errorf("Error occurred while reading file at path: %s\n, error: %s\n", path, err) } + checkSums := genFileChecksums(resultContent) resource.TestCheckResourceAttr(resourceName, "content", string(resultContent)) + resource.TestCheckResourceAttr(resourceName, "content_md5", checkSums.md5Hex) + resource.TestCheckResourceAttr(resourceName, "content_sha1", checkSums.sha1Hex) + resource.TestCheckResourceAttr(resourceName, "content_sha256", checkSums.sha256Hex) + resource.TestCheckResourceAttr(resourceName, "content_base64sha256", checkSums.sha256Base64) + resource.TestCheckResourceAttr(resourceName, "content_sha512", checkSums.sha512Hex) + resource.TestCheckResourceAttr(resourceName, "content_base64sha512", checkSums.sha512Base64) return nil } diff --git a/internal/provider/resource_local_file.go b/internal/provider/resource_local_file.go index 03553b1d..88aaf909 100644 --- a/internal/provider/resource_local_file.go +++ b/internal/provider/resource_local_file.go @@ -116,7 +116,7 @@ func (n *localFileResource) Schema(ctx context.Context, req resource.SchemaReque }, }, "id": schema.StringAttribute{ - Description: "The hexadecimal encoding of the checksum of the file content", + Description: "The hexadecimal encoding of the SHA1 checksum of the file content.", Computed: true, }, "sensitive_content": schema.StringAttribute{ @@ -139,6 +139,30 @@ func (n *localFileResource) Schema(ctx context.Context, req resource.SchemaReque path.MatchRoot("source")), }, }, + "content_md5": schema.StringAttribute{ + Description: "MD5 checksum of file content.", + Computed: true, + }, + "content_sha1": schema.StringAttribute{ + Description: "SHA1 checksum of file content.", + Computed: true, + }, + "content_sha256": schema.StringAttribute{ + Description: "SHA256 checksum of file content.", + Computed: true, + }, + "content_base64sha256": schema.StringAttribute{ + Description: "Base64 encoded SHA256 checksum of file content.", + Computed: true, + }, + "content_sha512": schema.StringAttribute{ + Description: "SHA512 checksum of file content.", + Computed: true, + }, + "content_base64sha512": schema.StringAttribute{ + Description: "Base64 encoded SHA512 checksum of file content.", + Computed: true, + }, }, } } @@ -196,9 +220,15 @@ func (n *localFileResource) Create(ctx context.Context, req resource.CreateReque return } - checksum := sha1.Sum(content) + checksums := genFileChecksums(content) + plan.ContentMd5 = types.StringValue(checksums.md5Hex) + plan.ContentSha1 = types.StringValue(checksums.sha1Hex) + plan.ContentSha256 = types.StringValue(checksums.sha256Hex) + plan.ContentBase64sha256 = types.StringValue(checksums.sha256Base64) + plan.ContentSha512 = types.StringValue(checksums.sha512Hex) + plan.ContentBase64sha512 = types.StringValue(checksums.sha512Base64) - plan.ID = types.StringValue(hex.EncodeToString(checksum[:])) + plan.ID = types.StringValue(checksums.sha1Hex) diags = resp.State.Set(ctx, &plan) resp.Diagnostics.Append(diags...) } @@ -283,4 +313,10 @@ type localFileResourceModelV0 struct { DirectoryPermission types.String `tfsdk:"directory_permission"` ID types.String `tfsdk:"id"` SensitiveContent types.String `tfsdk:"sensitive_content"` + ContentMd5 types.String `tfsdk:"content_md5"` + ContentSha1 types.String `tfsdk:"content_sha1"` + ContentSha256 types.String `tfsdk:"content_sha256"` + ContentBase64sha256 types.String `tfsdk:"content_base64sha256"` + ContentSha512 types.String `tfsdk:"content_sha512"` + ContentBase64sha512 types.String `tfsdk:"content_base64sha512"` } diff --git a/internal/provider/resource_local_sensitive_file.go b/internal/provider/resource_local_sensitive_file.go index 8ed77e1b..99270920 100644 --- a/internal/provider/resource_local_sensitive_file.go +++ b/internal/provider/resource_local_sensitive_file.go @@ -115,7 +115,31 @@ func (n *localSensitiveFileResource) Schema(ctx context.Context, req resource.Sc }, }, "id": schema.StringAttribute{ - Description: "The hexadecimal encoding of the checksum of the file content", + Description: "The hexadecimal encoding of the SHA1 checksum of the file content.", + Computed: true, + }, + "content_md5": schema.StringAttribute{ + Description: "MD5 checksum of file content.", + Computed: true, + }, + "content_sha1": schema.StringAttribute{ + Description: "SHA1 checksum of file content.", + Computed: true, + }, + "content_sha256": schema.StringAttribute{ + Description: "SHA256 checksum of file content.", + Computed: true, + }, + "content_base64sha256": schema.StringAttribute{ + Description: "Base64 encoded SHA256 checksum of file content.", + Computed: true, + }, + "content_sha512": schema.StringAttribute{ + Description: "SHA512 checksum of file content.", + Computed: true, + }, + "content_base64sha512": schema.StringAttribute{ + Description: "Base64 encoded SHA512 checksum of file content.", Computed: true, }, }, @@ -176,9 +200,15 @@ func (n *localSensitiveFileResource) Create(ctx context.Context, req resource.Cr return } - checksum := sha1.Sum(content) + checksums := genFileChecksums(content) + plan.ContentMd5 = types.StringValue(checksums.md5Hex) + plan.ContentSha1 = types.StringValue(checksums.sha1Hex) + plan.ContentSha256 = types.StringValue(checksums.sha256Hex) + plan.ContentBase64sha256 = types.StringValue(checksums.sha256Base64) + plan.ContentSha512 = types.StringValue(checksums.sha512Hex) + plan.ContentBase64sha512 = types.StringValue(checksums.sha512Base64) - plan.ID = types.StringValue(hex.EncodeToString(checksum[:])) + plan.ID = types.StringValue(checksums.sha1Hex) diags = resp.State.Set(ctx, &plan) resp.Diagnostics.Append(diags...) } @@ -259,4 +289,10 @@ type localSensitiveFileResourceModelV0 struct { FilePermission types.String `tfsdk:"file_permission"` DirectoryPermission types.String `tfsdk:"directory_permission"` ID types.String `tfsdk:"id"` + ContentMd5 types.String `tfsdk:"content_md5"` + ContentSha1 types.String `tfsdk:"content_sha1"` + ContentSha256 types.String `tfsdk:"content_sha256"` + ContentBase64sha256 types.String `tfsdk:"content_base64sha256"` + ContentSha512 types.String `tfsdk:"content_sha512"` + ContentBase64sha512 types.String `tfsdk:"content_base64sha512"` }