Skip to content

Commit c32ea71

Browse files
committed
r/private_key: Add private_key_openssh attribute
This commit adds private_key_openssh attribute, which always contains private key in format, which is compatible with OpenSSH. This allows to produce ED25519 private key in OpenSSL compatible format in private_key_pem attribute and OpenSSH-compatible format in this new attribute. Other key types are the same in private_key_pem and private_key_openssh, as OpenSSH can read them. In the future, this could be changed to produce all private keys OpenSSH native format. Refs #26 Signed-off-by: Mateusz Gozdek <[email protected]>
1 parent f295a2d commit c32ea71

File tree

3 files changed

+39
-6
lines changed

3 files changed

+39
-6
lines changed

tls/resource_private_key.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ func resourcePrivateKey() *schema.Resource {
9393
Sensitive: true,
9494
},
9595

96+
"private_key_openssh": {
97+
Type: schema.TypeString,
98+
Computed: true,
99+
Sensitive: true,
100+
},
101+
96102
"public_key_pem": {
97103
Type: schema.TypeString,
98104
Computed: true,
@@ -125,6 +131,7 @@ func CreatePrivateKey(d *schema.ResourceData, meta interface{}) error {
125131
}
126132

127133
var keyPemBlock *pem.Block
134+
var openSSHKeyPemBlock *pem.Block
128135
switch k := key.(type) {
129136
case *rsa.PrivateKey:
130137
keyPemBlock = &pem.Block{
@@ -141,16 +148,29 @@ func CreatePrivateKey(d *schema.ResourceData, meta interface{}) error {
141148
Bytes: keyBytes,
142149
}
143150
case *ed25519.PrivateKey:
151+
keyBytes, err := x509.MarshalPKCS8PrivateKey(*k)
152+
if err != nil {
153+
return fmt.Errorf("error encoding key to PEM: %s", err)
154+
}
155+
144156
keyPemBlock = &pem.Block{
157+
Type: "PRIVATE KEY",
158+
Bytes: keyBytes,
159+
}
160+
openSSHKeyPemBlock = &pem.Block{
145161
Type: "OPENSSH PRIVATE KEY",
146162
Bytes: marshalED25519PrivateKey(*k),
147163
}
148164
default:
149165
return fmt.Errorf("unsupported private key type")
150166
}
151-
keyPem := string(pem.EncodeToMemory(keyPemBlock))
167+
d.Set("private_key_pem", string(pem.EncodeToMemory(keyPemBlock)))
168+
169+
if openSSHKeyPemBlock == nil {
170+
openSSHKeyPemBlock = keyPemBlock
171+
}
152172

153-
d.Set("private_key_pem", keyPem)
173+
d.Set("private_key_openssh", string(pem.EncodeToMemory(openSSHKeyPemBlock)))
154174

155175
return readPublicKey(d, key)
156176
}

tls/resource_private_key_test.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,9 @@ func TestPrivateKeyED25519(t *testing.T) {
235235
output "private_key_pem" {
236236
value = "${tls_private_key.test.private_key_pem}"
237237
}
238+
output "private_key_openssh" {
239+
value = "${tls_private_key.test.private_key_openssh}"
240+
}
238241
output "public_key_pem" {
239242
value = "${tls_private_key.test.public_key_pem}"
240243
}
@@ -252,8 +255,18 @@ func TestPrivateKeyED25519(t *testing.T) {
252255
return fmt.Errorf("output for \"private_key_pem\" is not a string")
253256
}
254257

255-
if !strings.HasPrefix(gotPrivate, "-----BEGIN OPENSSH PRIVATE KEY----") {
256-
return fmt.Errorf("private key is missing RSA key PEM preamble")
258+
if !strings.HasPrefix(gotPrivate, "-----BEGIN PRIVATE KEY----") {
259+
return fmt.Errorf("private key is missing ED25519 key PEM preamble")
260+
}
261+
262+
gotPrivateOpenSSHUntyped := s.RootModule().Outputs["private_key_openssh"].Value
263+
gotPrivateOpenSSH, ok := gotPrivateOpenSSHUntyped.(string)
264+
if !ok {
265+
return fmt.Errorf("output for \"private_key_openssh\" is not a string")
266+
}
267+
268+
if !strings.HasPrefix(gotPrivateOpenSSH, "-----BEGIN OPENSSH PRIVATE KEY----") {
269+
return fmt.Errorf("private key is missing OPENSSH key PEM preamble")
257270
}
258271

259272
gotPublicUntyped := s.RootModule().Outputs["public_key_pem"].Value

website/docs/r/private_key.html.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ default.
4949
The following attributes are exported:
5050

5151
* `algorithm` - The algorithm that was selected for the key.
52-
* `private_key_pem` - The private key data in PEM format. For "ED25519" keys,
53-
the key is in OpenSSH-compatible format.
52+
* `private_key_pem` - The private key data in PEM format.
53+
* `private_key_openssh` - The private key data in OpenSSH-compatible format.
5454
* `public_key_pem` - The public key data in PEM format.
5555
* `public_key_openssh` - The public key data in OpenSSH `authorized_keys`
5656
format, if the selected private key format is compatible. All RSA and ED25519

0 commit comments

Comments
 (0)