Skip to content

lang/funcs: Add support for OpenSSH RSA key format#25112

Merged
alisdair merged 1 commit intomasterfrom
alisdair/support-openssh-rsa-key-encoding
Jun 3, 2020
Merged

lang/funcs: Add support for OpenSSH RSA key format#25112
alisdair merged 1 commit intomasterfrom
alisdair/support-openssh-rsa-key-encoding

Conversation

@alisdair
Copy link
Copy Markdown
Contributor

@alisdair alisdair commented Jun 2, 2020

Keys generated by recent versions of OpenSSH use a new OpenSSH PEM format which is incompatible with the x509 package. We can work around this by using the ParseRawPrivateKey from x/crypto/ssh and type asserting that we get the expected RSA key type back.

The new OpenSSH private key fixture was generated by re-encoding the existing private key fixture using this command on macOS:

$ ssh-keygen -p -N "" -f id_rsa_terraform
Your identification has been saved with the new passphrase.

Fixes #24970.

@alisdair alisdair requested a review from a team June 2, 2020 18:05
@codecov
Copy link
Copy Markdown

codecov bot commented Jun 2, 2020

Codecov Report

Merging #25112 into master will increase coverage by 0.00%.
The diff coverage is 75.00%.

Impacted Files Coverage Δ
lang/funcs/crypto.go 92.06% <75.00%> (+1.89%) ⬆️
terraform/evaluate.go 53.15% <0.00%> (-0.46%) ⬇️
states/statefile/version4.go 56.16% <0.00%> (-0.29%) ⬇️

rawKey, err := ssh.ParseRawPrivateKey([]byte(key))
if err != nil {
return cty.UnknownVal(cty.String), err
return cty.UnknownVal(cty.String), fmt.Errorf("failed to parse key: %s", err)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the Errorf text needed here? Just wondering if we're going to get errors like failed to parse key: fail to parse SSH key

Copy link
Copy Markdown
Contributor

@apparentlymart apparentlymart Jun 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had kinda hoped that the encoding/asn1 package would produce machine-readable error values that we could use to present something more appropriate for the Terraform end-user audience, 'cause from what I see in #24970 these messages seem pretty poor, but sadly it looks like StructuralError and SyntaxError are both just wrappers around opaque strings formatted in the internals of the parser. 😖

With that said, I reviewed the parser code and it looks like this "tags don't match" error is a particularly ugly example but most of them are reasonable messages that suffer only from a total lack of useful context, like "base 128 integer too large". So the two forms this should end up producing are:

  • failed to parse key: asn1: structure error: tags don't match (16 vs {class:1 tag:15 length:112 isCompound:true}) {optional:false explicit:false application:false private:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false} pkcs1PrivateKey @2.
  • failed to parse key: asn1: syntax error: invalid boolean

I think the only way we could marginally improve these with the information we have is to recognize when the error type is either asn1.SyntaxError or asn1.StructuralError and generate a different prefix (replacing asn1: syntax error:) that is more in line with our usual writing style, like:

  • invalid ASN1 data in the given private key: invalid boolean
  • invalid ASN1 data in the given private key: tags don't match (16 vs {class:1 tag:15 length:112 isCompound:true}) {optional:false explicit:false application:false private:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false} pkcs1PrivateKey @2.

(the second one isn't going to be nice whatever we do to it, of course...)

A further embellishment, though very much not necessary, would be to use function.NewArgErrorf to associate this error explicitly with the second argument (argument index 1), and then HCL should indicate that argument's experession in particular as being the problematic part of the configuration.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestions!

I think it is important to process these errors rather than just pass them through, because the crypto errors are pretty obscure. Adding even basic error annotations was the first step to debugging this.

I've made the suggested changes and I think it's a big improvement:

velara:24970 $ tf apply -var-file=trunc.tfvars

Error: Invalid function argument

  on example.tf line 13, in output "password_decrypted":
  13:   value=rsadecrypt(var.password_data, file("${path.module}/${var.rsa_private_key_file}") )
    |----------------
    | path.module is "."
    | var.rsa_private_key_file is "id_rsa_trunc"

Invalid value for "privatekey" parameter: invalid ASN1 data in the given
private key: data truncated.

Previously this function only supported the x509 RSA private key format.
More recent versions of OpenSSH default to generating a new PEM key
format, which this commit now supports using the x/crypto/ssh package.

Also improve the returned error messages for various invalid ciphertext
or invalid private key errors.
@alisdair alisdair force-pushed the alisdair/support-openssh-rsa-key-encoding branch from 91a2722 to a4f5e04 Compare June 3, 2020 14:50
@alisdair alisdair merged commit c921c85 into master Jun 3, 2020
@alisdair alisdair deleted the alisdair/support-openssh-rsa-key-encoding branch June 3, 2020 15:52
@ghost
Copy link
Copy Markdown

ghost commented Jul 4, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@ghost ghost locked and limited conversation to collaborators Jul 4, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rsadecrypt fails using recent ssh-keygen DSA keys

3 participants