From f1c7ffa14a0c473fd46f2fece8343ed975593d22 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 12 Apr 2023 21:13:23 +0100 Subject: [PATCH] Prevent hash error `bcrypt.ErrPasswordTooLong` for passwords > 72 bytes in length (#397) * Truncating passwords that are longer than 72 bytes (#396) * Adding changelog entry (#396) * Updating changelog entry and docs (#396) * Updating changelog entry (#396) * updated comment msg --- .../unreleased/BUG FIXES-20230412-132501.yaml | 6 ++++ docs/resources/password.md | 2 +- internal/provider/resource_password.go | 36 +++++++++++++------ internal/provider/resource_password_test.go | 4 +-- 4 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 .changes/unreleased/BUG FIXES-20230412-132501.yaml diff --git a/.changes/unreleased/BUG FIXES-20230412-132501.yaml b/.changes/unreleased/BUG FIXES-20230412-132501.yaml new file mode 100644 index 00000000..a7067e52 --- /dev/null +++ b/.changes/unreleased/BUG FIXES-20230412-132501.yaml @@ -0,0 +1,6 @@ +kind: BUG FIXES +body: 'resource/random_password: Prevent error with `bcrypt` by truncating the bytes + that are hashed to a maximum length of 72' +time: 2023-04-12T13:25:01.113462+01:00 +custom: + Issue: "397" diff --git a/docs/resources/password.md b/docs/resources/password.md index 22bd8a16..afc96201 100644 --- a/docs/resources/password.md +++ b/docs/resources/password.md @@ -53,7 +53,7 @@ resource "aws_db_instance" "example" { ### Read-Only -- `bcrypt_hash` (String, Sensitive) A bcrypt hash of the generated random string. +- `bcrypt_hash` (String, Sensitive) A bcrypt hash of the generated random string. **NOTE**: If the generated random string is greater than 72 bytes in length, `bcrypt_hash` will contain a hash of the first 72 bytes. - `id` (String) A static value used internally by Terraform, this should not be referenced in configurations. - `result` (String, Sensitive) The generated random string. diff --git a/internal/provider/resource_password.go b/internal/provider/resource_password.go index d426d8a3..c1dd20b1 100644 --- a/internal/provider/resource_password.go +++ b/internal/provider/resource_password.go @@ -535,8 +535,18 @@ func upgradePasswordStateV2toV3(ctx context.Context, req resource.UpgradeStateRe resp.Diagnostics.Append(resp.State.Set(ctx, passwordDataV3)...) } +// generateHash truncates strings that are longer than 72 bytes in +// order to avoid the error returned from bcrypt.GenerateFromPassword +// in versions v0.5.0 and above: https://pkg.go.dev/golang.org/x/crypto@v0.8.0/bcrypt#GenerateFromPassword func generateHash(toHash string) (string, error) { - hash, err := bcrypt.GenerateFromPassword([]byte(toHash), bcrypt.DefaultCost) + bytesHash := []byte(toHash) + bytesToHash := bytesHash + + if len(bytesHash) > 72 { + bytesToHash = bytesHash[:72] + } + + hash, err := bcrypt.GenerateFromPassword(bytesToHash, bcrypt.DefaultCost) return string(hash), err } @@ -693,9 +703,11 @@ func passwordSchemaV3() schema.Schema { }, "bcrypt_hash": schema.StringAttribute{ - Description: "A bcrypt hash of the generated random string.", - Computed: true, - Sensitive: true, + Description: "A bcrypt hash of the generated random string. " + + "**NOTE**: If the generated random string is greater than 72 bytes in length, " + + "`bcrypt_hash` will contain a hash of the first 72 bytes.", + Computed: true, + Sensitive: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.UseStateForUnknown(), }, @@ -805,9 +817,11 @@ func passwordSchemaV2() schema.Schema { }, "bcrypt_hash": schema.StringAttribute{ - Description: "A bcrypt hash of the generated random string.", - Computed: true, - Sensitive: true, + Description: "A bcrypt hash of the generated random string. " + + "**NOTE**: If the generated random string is greater than 72 bytes in length, " + + "`bcrypt_hash` will contain a hash of the first 72 bytes.", + Computed: true, + Sensitive: true, }, "id": schema.StringAttribute{ @@ -903,9 +917,11 @@ func passwordSchemaV1() schema.Schema { }, "bcrypt_hash": schema.StringAttribute{ - Description: "A bcrypt hash of the generated random string.", - Computed: true, - Sensitive: true, + Description: "A bcrypt hash of the generated random string. " + + "**NOTE**: If the generated random string is greater than 72 bytes in length, " + + "`bcrypt_hash` will contain a hash of the first 72 bytes.", + Computed: true, + Sensitive: true, }, "id": schema.StringAttribute{ diff --git a/internal/provider/resource_password_test.go b/internal/provider/resource_password_test.go index 9ff7fb93..05ffecb3 100644 --- a/internal/provider/resource_password_test.go +++ b/internal/provider/resource_password_test.go @@ -28,7 +28,7 @@ func TestGenerateHash(t *testing.T) { }{ "defaults": { input: random.StringParams{ - Length: 32, // Required + Length: 73, // Required Lower: true, Numeric: true, Special: true, @@ -111,7 +111,7 @@ func TestAccResourcePassword_BcryptHash(t *testing.T) { Steps: []resource.TestStep{ { Config: `resource "random_password" "test" { - length = 12 + length = 73 }`, Check: resource.ComposeTestCheckFunc( testExtractResourceAttr("random_password.test", "bcrypt_hash", &bcryptHash),