Beg Report: ED25519 SSH Private Keys human-readable value differs from json value

Options
brchar
brchar
Community Member

in troubleshooting with the ansible community, we have discovered that ED25519 SSH Keys generated by 1Password have an incorrect value in the private key value field when using "--format json" flag. however "--format human-readable" returns the correct key.

the ansible community.general.onepassword lookup plugin relies on the json output to parse values. We need the top level value field in the Json Response from op cli to match that of the ssh_formats['openssh']['value'] field on the json response.

for example:
{
"id": "private_key",
"type": "SSHKEY",
"label": "private key",
"value": "-----BEGIN PRIVATE KEY-----\r\nreally_short_invalid_ssh_key==\r\n-----END PRIVATE KEY-----\r\n",
"reference": "op://SSH Keys/my_test_key/private key",
"ssh_formats": {
"openssh": {
"reference": "op://SSH Keys/my_test_key/private key?ssh-format=openssh",
"value": "-----BEGIN OPENSSH PRIVATE KEY-----\r\nmy_valid_ssh_key\r\n-----END OPENSSH PRIVATE KEY-----\r\n"
}
}
}

BEGIN/END PRIVATE KEY are for RSA Keys only, but ED25519 use the BEGIN/END OPENSSH PRIVATE KEY

The corresponding Public Keys will only work with the value currently stored in ssh_formats['openssh']['value'] and will fail to authenticate using the Key in value field.

We need this fixed!


1Password Version: cli 2.21.0
Extension Version: Not Provided
OS Version: Windows 10/Debian 12
Browser: Not Provided

Comments

  • andi.t_1P
    edited November 2023
    Options

    @brchar . We are currently supporting 2 private key formats: PKCS8 and OpenSSH. The value field in the JSON output will show the original (internal) format of the private key, which is PKCS8 in most cases (The only exception is when you import a private key that already has OpenSSH format). However, you can always reliably get the OpenSSH format by looking into ssh_formats['openssh']['value'].

    The initial considerations of why we picked this output design, was to not break the scripts of people who were already relying on the value field returning the PKCS8 format of their key.

  • brchar
    brchar
    Community Member
    edited November 2023
    Options

    I understand your reasoning. However I believe that both ed25519 and pkcs8 keys generated by 1password should put the selected format as the normal value field, and then perhaps both ssh formats be listed under the ssh_formats key.

    Ssh clients that I have tested cannot use the pkcs8 private key if the target is using an ed25519 public key. And now it makes a lot more work to move to the newer standard of ed25519 since pkcs8 rsa key standards are considered legacy now.

    The current methodology makes using ed25519 keys difficult in automation tools such as ansible.

  • rmartinsjr
    rmartinsjr
    Community Member
    Options

    Hi @andi.t_1P

    I've just spent a lot of hours trying to figure out why my Ansible playbook was not using the right SSH key (and failing) when I came across this bug report.

    Now I understand that the lookup plugin "community.general.onepassword" was retrieving the PKCS8 while OP cli was showing the right SSH format. Sadly there's no consistency between the two and adding an insult to injury, there's no way to point out which format the Ansible lookup plugin should use.

    I agree with @brchar, not only it makes ed25519 adoption difficult by tools such as Ansible, but it is a completely different behavior triggered by the key type! And guess what I had to do to have it working without committing more hours? I "downgraded" the ED25519 key to RSA!

    Here are some key points that 1Password team should address:

    • Consistency: the Ansible plugin states that it's a wrapper around OP cli, but it shows PKCS8 while OP cli shows OPENSSH format. Either both return PKCS8 or OPENSSH format.
    • Compatibility: Ansible lookup plugin should return the OPENSSH format for ED25519, as it is the case for RSA keys.
    • Keep the Ansible plugin up to date! It looks like the plugin is "unaware" of this change AND there is no way to retrieve different formats.
  • brchar
    brchar
    Community Member
    Options

    Ansible plug-in uses op cli. However it uses the value field from the json format of the output. I think op cli choses the field to return from in text output based on the key type.

  • rmartinsjr
    rmartinsjr
    Community Member
    Options

    Exactly! That's why I'm asking for consistency, or at least having the option to select the format (PKCS8 or OPENSSH) in the Ansible lookup plugin.

    Here is a playbook that shows this behavior (replace "item_id" with the ID of some SSH Key in 1Password):

    ---
    
    - hosts: localhost
      tasks:
        - command: op item get item_id --field 'private key' --reveal
          register: op_cli
        - debug:
            var: op_cli.stdout
        - debug:
            msg: "{{ lookup('community.general.onepassword', 'item_id', field='private key') }}"
    
  • brchar
    brchar
    Community Member
    edited December 2023
    Options

    @rmartinsjr and @andi.t_1P

    it's not the ansible module that has the issue though. it is the opcli itself.

    the ansible modules rely on the json output format from opcli and in the json output format private_key seems to only contain the PKSC8 Key while the Ed25519 Key is stored in the convoluted ssh_formats.openssh.value field. this seems to break standardization for the Newer Ed25519 keys since now we have to re-write any tools/scripts to adopt 2 different standards. especially since 1Password is suggesting the Ed25519 Keys as a default now.

    I think it would be better to adopt storing the key that was selected at generation in the private_key field, while also providing both key formats in the ssh_formats section.

    I am trying to use Ed25519 Keys generated by 1Password. so one would expect that the private key would be that format of the key which was generated not always PKCS8

  • brchar
    brchar
    Community Member
    edited December 2023
    Options

    This is the command being used by ansible:

    op item get $key_name --vault=$vault_name --fields=$field_list --reveal --format=json

    so in my case

    op item get 'My Test Key' --vault='SSH Keys' --fields=private_key --reveal --format=json