Skip to content

Commit 672b916

Browse files
committed
Add support for openssh comments when generating a private key
1 parent b59972d commit 672b916

File tree

8 files changed

+61
-2
lines changed

8 files changed

+61
-2
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: ENHANCEMENTS
2+
body: 'resource/tls_private_key: add openssh_comment attribute
3+
data-source/tls_public_key: add openssh_comment attribute'
4+
time: 2023-08-03T09:42:41.390232535Z
5+
custom:
6+
Issue: "395"

docs/data-sources/public_key.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ data "tls_public_key" "private_key_openssh-example" {
4343

4444
- `algorithm` (String) The name of the algorithm used by the given private key. Possible values are: `RSA`, `ECDSA`, `ED25519`.
4545
- `id` (String) Unique identifier for this data source: hexadecimal representation of the SHA1 checksum of the data source.
46+
- `openssh_comment` (String) The OpenSSH comment.
4647
- `public_key_fingerprint_md5` (String) The fingerprint of the public key data in OpenSSH MD5 hash format, e.g. `aa:bb:cc:...`. Only available if the selected private key format is compatible, as per the rules for `public_key_openssh` and [ECDSA P224 limitations](../../docs#limitations).
4748
- `public_key_fingerprint_sha256` (String) The fingerprint of the public key data in OpenSSH SHA256 hash format, e.g. `SHA256:...`. Only available if the selected private key format is compatible, as per the rules for `public_key_openssh` and [ECDSA P224 limitations](../../docs#limitations).
4849
- `public_key_openssh` (String) The public key, in [OpenSSH PEM (RFC 4716)](https://datatracker.ietf.org/doc/html/rfc4716) format. This is also known as ['Authorized Keys'](https://www.ssh.com/academy/ssh/authorized_keys/openssh#format-of-the-authorized-keys-file) format. This is not populated for `ECDSA` with curve `P224`, as it is [not supported](../../docs#limitations). **NOTE**: the [underlying](https://pkg.go.dev/encoding/pem#Encode) [libraries](https://pkg.go.dev/golang.org/x/crypto/ssh#MarshalAuthorizedKey) that generate this value append a `\n` at the end of the PEM. In case this disrupts your use case, we recommend using [`trimspace()`](https://www.terraform.io/language/functions/trimspace).

docs/resources/private_key.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ resource "tls_private_key" "ed25519-example" {
5353
### Optional
5454

5555
- `ecdsa_curve` (String) When `algorithm` is `ECDSA`, the name of the elliptic curve to use. Currently-supported values are: `P224`, `P256`, `P384`, `P521`. (default: `P224`).
56+
- `openssh_comment` (String) Comment to add to the OpenSSH key (default: `""`).
5657
- `rsa_bits` (Number) When `algorithm` is `RSA`, the size of the generated RSA key, in bits (default: `2048`).
5758

5859
### Read-Only

internal/provider/common_key.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"crypto/x509"
1515
"encoding/pem"
1616
"fmt"
17+
"strings"
1718

1819
"github.com/hashicorp/terraform-plugin-framework/diag"
1920
"github.com/hashicorp/terraform-plugin-framework/path"
@@ -201,6 +202,15 @@ func setPublicKeyAttributes(ctx context.Context, s *tfsdk.State, prvKey crypto.P
201202
sshPubKeyBytes := ssh.MarshalAuthorizedKey(sshPubKey)
202203

203204
pubKeySSH = string(sshPubKeyBytes)
205+
206+
// Manually add the comment as MarshalAuthorizedKeys ignores it: https://github.com/golang/go/issues/46870
207+
var comment *string
208+
diags.Append(s.GetAttribute(ctx, path.Root("openssh_comment"), &comment)...)
209+
210+
if comment != nil {
211+
pubKeySSH = fmt.Sprintf("%s %s\n", strings.TrimSuffix(pubKeySSH, "\n"), *comment)
212+
}
213+
204214
pubKeySSHFingerprintMD5 = ssh.FingerprintLegacyMD5(sshPubKey)
205215
pubKeySSHFingerprintSHA256 = ssh.FingerprintSHA256(sshPubKey)
206216
}

internal/provider/data_source_public_key.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ func (d *publicKeyDataSource) Schema(ctx context.Context, req datasource.SchemaR
6969
Description: "The name of the algorithm used by the given private key. " +
7070
fmt.Sprintf("Possible values are: `%s`. ", strings.Join(supportedAlgorithmsStr(), "`, `")),
7171
},
72+
"openssh_comment": schema.StringAttribute{
73+
Computed: true,
74+
Description: "The OpenSSH comment.",
75+
},
7276
"public_key_pem": schema.StringAttribute{
7377
Computed: true,
7478
Description: "The public key, in [PEM (RFC 1421)](https://datatracker.ietf.org/doc/html/rfc1421) format. " +

internal/provider/models.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ type certificateSubjectModel struct {
6565

6666
type privateKeyResourceModel struct {
6767
Algorithm types.String `tfsdk:"algorithm"`
68+
OpenSSHComment types.String `tfsdk:"openssh_comment"`
6869
RSABits types.Int64 `tfsdk:"rsa_bits"`
6970
ECDSACurve types.String `tfsdk:"ecdsa_curve"`
7071
PrivateKeyPem types.String `tfsdk:"private_key_pem"`

internal/provider/resource_private_key.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ func (r *privateKeyResource) Schema(_ context.Context, req resource.SchemaReques
6161
},
6262

6363
// Optional attributes
64+
"openssh_comment": schema.StringAttribute{
65+
Optional: true,
66+
PlanModifiers: []planmodifier.String{
67+
stringplanmodifier.RequiresReplace(),
68+
},
69+
MarkdownDescription: "Comment to add to the OpenSSH key (default: `\"\"`).",
70+
},
6471
"rsa_bits": schema.Int64Attribute{
6572
Optional: true,
6673
Computed: true,
@@ -159,6 +166,10 @@ func privateKeyResourceSchemaV1() schema.Schema {
159166
},
160167

161168
// Optional attributes
169+
"openssh_comment": schema.StringAttribute{
170+
Optional: true,
171+
MarkdownDescription: "Comment to add to the OpenSSH key (default: `\"\"`).",
172+
},
162173
"rsa_bits": schema.Int64Attribute{
163174
Optional: true,
164175
Computed: true,
@@ -318,12 +329,11 @@ func (r *privateKeyResource) Create(ctx context.Context, req resource.CreateRequ
318329
tflog.Debug(ctx, "Marshalling private key to OpenSSH PEM (if supported)")
319330
newState.PrivateKeyOpenSSH = types.StringValue("")
320331
if prvKeySupportsOpenSSHMarshalling(prvKey) {
321-
openSSHKeyPemBlock, err := openssh.MarshalPrivateKey(prvKey, "")
332+
openSSHKeyPemBlock, err := openssh.MarshalPrivateKey(prvKey, newState.OpenSSHComment.ValueString())
322333
if err != nil {
323334
res.Diagnostics.AddError("Unable to marshal private key into OpenSSH format", err.Error())
324335
return
325336
}
326-
327337
newState.PrivateKeyOpenSSH = types.StringValue(string(pem.EncodeToMemory(openSSHKeyPemBlock)))
328338
}
329339

internal/provider/resource_private_key_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,3 +401,29 @@ func TestAccPrivateKeyED25519_UpgradeFromVersion3_4_0(t *testing.T) {
401401
},
402402
})
403403
}
404+
405+
func TestOpenSSHComment(t *testing.T) {
406+
r.UnitTest(t, r.TestCase{
407+
ProtoV5ProviderFactories: protoV5ProviderFactories(),
408+
Steps: []r.TestStep{
409+
{
410+
Config: `
411+
resource "tls_private_key" "test" {
412+
algorithm = "ED25519"
413+
openssh_comment = "test@test"
414+
}
415+
`,
416+
Check: r.ComposeAggregateTestCheckFunc(
417+
tu.TestCheckPEMFormat("tls_private_key.test", "private_key_pem", PreamblePrivateKeyPKCS8.String()),
418+
tu.TestCheckPEMFormat("tls_private_key.test", "public_key_pem", PreamblePublicKey.String()),
419+
tu.TestCheckPEMFormat("tls_private_key.test", "private_key_openssh", PreamblePrivateKeyOpenSSH.String()),
420+
tu.TestCheckPEMFormat("tls_private_key.test", "private_key_pem_pkcs8", PreamblePrivateKeyPKCS8.String()),
421+
r.TestMatchResourceAttr("tls_private_key.test", "public_key_openssh", regexp.MustCompile(`^ssh-ed25519 `)),
422+
r.TestMatchResourceAttr("tls_private_key.test", "public_key_openssh", regexp.MustCompile(` test@test\n$`)),
423+
r.TestMatchResourceAttr("tls_private_key.test", "public_key_fingerprint_md5", regexp.MustCompile(`^([abcdef\d]{2}:){15}[abcdef\d]{2}`)),
424+
r.TestMatchResourceAttr("tls_private_key.test", "public_key_fingerprint_sha256", regexp.MustCompile(`^SHA256:`)),
425+
),
426+
},
427+
},
428+
})
429+
}

0 commit comments

Comments
 (0)