mirror of https://github.com/ansible/ansible.git
openssl_privatekey: add ECC support (#49416)
* Add cryptography backend for openssl_privatekey. * Adding ECC support. No support for X25519 and X449, since they don't support serialization. * Improve finterprint calculation to work with Python 3. * Add fingerprint check. * Fix typo. * Use separate curve option for elliptic curves, and use type 'ECC'. * Using curve names as defined in IANA registry. * Bump minimal supported cryptography version. Older versions might work as well, but I couldn't test them. * Improve documentation.pull/50080/head
parent
6d952e4124
commit
92ef500185
@ -0,0 +1,144 @@
|
||||
---
|
||||
- name: Generate privatekey1 - standard
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey1.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: Generate privatekey2 - size 2048
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey2.pem'
|
||||
size: 2048
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: Generate privatekey3 - type DSA
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey3.pem'
|
||||
type: DSA
|
||||
size: 3072
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: Generate privatekey4 - standard
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey4.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: Delete privatekey4 - standard
|
||||
openssl_privatekey:
|
||||
state: absent
|
||||
path: '{{ output_dir }}/privatekey4.pem'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: Generate privatekey5 - standard - with passphrase
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey5.pem'
|
||||
passphrase: ansible
|
||||
cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- name: Generate privatekey5 - standard - idempotence
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey5.pem'
|
||||
passphrase: ansible
|
||||
cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: privatekey5_idempotence
|
||||
|
||||
- name: Generate privatekey6 - standard - with non-ASCII passphrase
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey6.pem'
|
||||
passphrase: ànsïblé
|
||||
cipher: "{{ 'aes256' if select_crypto_backend == 'pyopenssl' else 'auto' }}"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
|
||||
- set_fact:
|
||||
ecc_types: []
|
||||
when: select_crypto_backend == 'pyopenssl'
|
||||
- set_fact:
|
||||
ecc_types:
|
||||
# - curve: X448
|
||||
# min_cryptography_version: "2.5"
|
||||
# - curve: X25519
|
||||
# min_cryptography_version: "2.0"
|
||||
- curve: secp384r1
|
||||
openssl_name: secp384r1
|
||||
min_cryptography_version: "0.5"
|
||||
- curve: secp521r1
|
||||
openssl_name: secp521r1
|
||||
min_cryptography_version: "0.5"
|
||||
- curve: secp224r1
|
||||
openssl_name: secp224r1
|
||||
min_cryptography_version: "0.5"
|
||||
- curve: secp192r1
|
||||
openssl_name: prime192v1
|
||||
min_cryptography_version: "0.5"
|
||||
- curve: secp256k1
|
||||
openssl_name: secp256k1
|
||||
min_cryptography_version: "0.9"
|
||||
- curve: brainpoolP256r1
|
||||
openssl_name: brainpoolP256r1
|
||||
min_cryptography_version: "2.2"
|
||||
- curve: brainpoolP384r1
|
||||
openssl_name: brainpoolP384r1
|
||||
min_cryptography_version: "2.2"
|
||||
- curve: brainpoolP512r1
|
||||
openssl_name: brainpoolP512r1
|
||||
min_cryptography_version: "2.2"
|
||||
- curve: sect571k1
|
||||
openssl_name: sect571k1
|
||||
min_cryptography_version: "0.5"
|
||||
- curve: sect409k1
|
||||
openssl_name: sect409k1
|
||||
min_cryptography_version: "0.5"
|
||||
- curve: sect283k1
|
||||
openssl_name: sect283k1
|
||||
min_cryptography_version: "0.5"
|
||||
- curve: sect233k1
|
||||
openssl_name: sect233k1
|
||||
min_cryptography_version: "0.5"
|
||||
- curve: sect163k1
|
||||
openssl_name: sect163k1
|
||||
min_cryptography_version: "0.5"
|
||||
- curve: sect571r1
|
||||
openssl_name: sect571r1
|
||||
min_cryptography_version: "0.5"
|
||||
- curve: sect409r1
|
||||
openssl_name: sect409r1
|
||||
min_cryptography_version: "0.5"
|
||||
- curve: sect283r1
|
||||
openssl_name: sect283r1
|
||||
min_cryptography_version: "0.5"
|
||||
- curve: sect233r1
|
||||
openssl_name: sect233r1
|
||||
min_cryptography_version: "0.5"
|
||||
- curve: sect163r2
|
||||
openssl_name: sect163r2
|
||||
min_cryptography_version: "0.5"
|
||||
when: select_crypto_backend == 'cryptography'
|
||||
|
||||
- name: Test ECC key generation
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey-{{ item.curve }}.pem'
|
||||
type: ECC
|
||||
curve: "{{ item.curve }}"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: |
|
||||
cryptography_version.stdout is version(item.min_cryptography_version, '>=') and
|
||||
item.openssl_name in openssl_ecc_list
|
||||
loop: "{{ ecc_types }}"
|
||||
loop_control:
|
||||
label: "{{ item.curve }}"
|
||||
register: privatekey_ecc_generate
|
||||
|
||||
- name: Test ECC key generation (idempotency)
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey-{{ item.curve }}.pem'
|
||||
type: ECC
|
||||
curve: "{{ item.curve }}"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: |
|
||||
cryptography_version.stdout is version(item.min_cryptography_version, '>=') and
|
||||
item.openssl_name in openssl_ecc_list
|
||||
loop: "{{ ecc_types }}"
|
||||
loop_control:
|
||||
label: "{{ item.curve }}"
|
||||
register: privatekey_ecc_idempotency
|
@ -1,43 +1,95 @@
|
||||
- name: Generate privatekey1 - standard
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey1.pem'
|
||||
|
||||
- name: Generate privatekey2 - size 2048
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey2.pem'
|
||||
size: 2048
|
||||
|
||||
- name: Generate privatekey3 - type DSA
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey3.pem'
|
||||
type: DSA
|
||||
|
||||
- name: Generate privatekey4 - standard
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey4.pem'
|
||||
|
||||
- name: Delete privatekey4 - standard
|
||||
openssl_privatekey:
|
||||
---
|
||||
- name: Find out which elliptic curves are supported by installed OpenSSL
|
||||
command: openssl ecparam -list_curves
|
||||
register: openssl_ecc
|
||||
|
||||
- name: Compile list of elliptic curves supported by OpenSSL
|
||||
set_fact:
|
||||
openssl_ecc_list: |
|
||||
{{
|
||||
openssl_ecc.stdout_lines
|
||||
| map('regex_search', '^ *([a-zA-Z0-9_-]+) *: .*$')
|
||||
| select()
|
||||
| map('regex_replace', '^ *([a-zA-Z0-9_-]+) *: .*$', '\1')
|
||||
| list
|
||||
}}
|
||||
when: ansible_distribution != 'CentOS' or ansible_distribution_major_version != '6'
|
||||
# CentOS comes with a very old jinja2 which does not include the map() filter...
|
||||
- name: Compile list of elliptic curves supported by OpenSSL (CentOS 6)
|
||||
set_fact:
|
||||
openssl_ecc_list:
|
||||
- secp384r1
|
||||
- secp521r1
|
||||
- prime256v1
|
||||
when: ansible_distribution == 'CentOS' and ansible_distribution_major_version == '6'
|
||||
|
||||
- name: List of elliptic curves supported by OpenSSL
|
||||
debug: var=openssl_ecc_list
|
||||
|
||||
- block:
|
||||
- name: Running tests with pyOpenSSL backend
|
||||
include_tasks: impl.yml
|
||||
vars:
|
||||
select_crypto_backend: pyopenssl
|
||||
|
||||
- import_tasks: ../tests/validate.yml
|
||||
|
||||
# FIXME: minimal pyOpenSSL version?!
|
||||
when: pyopenssl_version.stdout is version('0.6', '>=')
|
||||
|
||||
- name: Remove output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
state: absent
|
||||
path: '{{ output_dir }}/privatekey4.pem'
|
||||
|
||||
- name: Generate privatekey5 - standard - with passphrase
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey5.pem'
|
||||
passphrase: ansible
|
||||
cipher: aes256
|
||||
|
||||
- name: Generate privatekey5 - standard - idempotence
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey5.pem'
|
||||
passphrase: ansible
|
||||
cipher: aes256
|
||||
register: privatekey5_idempotence
|
||||
|
||||
- name: Generate privatekey6 - standard - with non-ASCII passphrase
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/privatekey6.pem'
|
||||
passphrase: ànsïblé
|
||||
cipher: aes256
|
||||
|
||||
- import_tasks: ../tests/validate.yml
|
||||
|
||||
- name: Re-create output directory
|
||||
file:
|
||||
path: "{{ output_dir }}"
|
||||
state: directory
|
||||
|
||||
- block:
|
||||
- name: Running tests with cryptography backend
|
||||
include_tasks: impl.yml
|
||||
vars:
|
||||
select_crypto_backend: cryptography
|
||||
|
||||
- import_tasks: ../tests/validate.yml
|
||||
|
||||
when: cryptography_version.stdout is version('0.5', '>=')
|
||||
|
||||
- name: Check that fingerprints do not depend on the backend
|
||||
block:
|
||||
- name: "Fingerprint comparison: pyOpenSSL"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/fingerprint-{{ item }}.pem'
|
||||
type: "{{ item }}"
|
||||
size: 1024
|
||||
select_crypto_backend: pyopenssl
|
||||
loop:
|
||||
- RSA
|
||||
- DSA
|
||||
register: fingerprint_pyopenssl
|
||||
|
||||
- name: "Fingerprint comparison: cryptography"
|
||||
openssl_privatekey:
|
||||
path: '{{ output_dir }}/fingerprint-{{ item }}.pem'
|
||||
type: "{{ item }}"
|
||||
size: 1024
|
||||
select_crypto_backend: cryptography
|
||||
loop:
|
||||
- RSA
|
||||
- DSA
|
||||
register: fingerprint_cryptography
|
||||
|
||||
- name: Verify that fingerprints match
|
||||
assert:
|
||||
that: item.0.fingerprint[item.2] == item.1.fingerprint[item.2]
|
||||
when: item.0 is not skipped and item.1 is not skipped
|
||||
loop: |
|
||||
{{ query('nested',
|
||||
fingerprint_pyopenssl.results | zip(fingerprint_cryptography.results),
|
||||
fingerprint_pyopenssl.results[0].fingerprint.keys()
|
||||
) if fingerprint_pyopenssl.results[0].fingerprint else [] }}
|
||||
loop_control:
|
||||
label: "{{ [item.0.item, item.2] }}"
|
||||
when: pyopenssl_version.stdout is version('0.6', '>=') and cryptography_version.stdout is version('0.5', '>=')
|
||||
|
Loading…
Reference in New Issue