Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

certificate_complete_chain fails with multiple intermediates with same CN (and same root) #399

Closed
shk3bq4d opened this issue Feb 11, 2022 · 4 comments · Fixed by #403
Closed
Labels
bug Something isn't working

Comments

@shk3bq4d
Copy link

SUMMARY

The module apparently can't find its way when there are multiple intermediate CA candidates with identical CN (and probably being issued by an unique root).

Maybe I am not understanding the module correctly, but I have a test case which could clarify things.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

certificate_complete_chain

ANSIBLE VERSION
ansible [core 2.12.2]
  python version = 3.8.10 (default, Nov 26 2021, 20:14:08) [GCC 9.3.0]
COLLECTION VERSION
Collection         Version
------------------ -------
community.crypto   2.2.1

cryptography==36.0.1
STEPS TO REPRODUCE
- hosts: localhost
  connection: local
  gather_facts: no

  tasks:

    - name: Setup - generate all private keys
      community.crypto.openssl_privatekey:
        path: /tmp/{{ item }}
      with_items:
        - a_root.key
        - b_intermediate.key
        - c_intermediate.key
        - d_cert.key

    - name: Setup - generate root csr
      register: a_openssl_csr
      community.crypto.openssl_csr:
        path:            /tmp/a_root.csr
        privatekey_path: /tmp/a_root.key
        common_name:     root common name

    - name: Setup - generate root CA cert
      register: a_x509_certificate
      community.crypto.x509_certificate:
        path:            /tmp/a_root.crt
        csr_path:        /tmp/a_root.csr
        privatekey_path: /tmp/a_root.key
        provider:        selfsigned
#       force:           "{{ a_openssl_csr.changed }}"

    - name: Setup - generate intermediate CAs' CSR
      register: bc_openssl_csr
      community.crypto.openssl_csr:
        path:            /tmp/{{ item }}.csr
        privatekey_path: /tmp/{{ item }}.key
        common_name:     intermediate common name #{{ item }} # appending {{ item }} would make all the tests pass
      with_items:
        - b_intermediate
        - c_intermediate

    - name: Setup - Generate intermediate CA
      register: bc_x509_certificate
      community.crypto.x509_certificate:
        path:                  /tmp/{{ item }}.crt
        csr_path:              /tmp/{{ item }}.csr
        ownca_path:            /tmp/a_root.crt
        ownca_privatekey_path: /tmp/a_root.key
        provider:               ownca
        force:                  "{{ a_x509_certificate.changed }}" # or bc_openssl_csr.changed }}"
      with_items:
        - b_intermediate
        - c_intermediate

    - name: Setup - generate leaf cert CSR

      community.crypto.openssl_csr:
        path:            /tmp/d_cert.csr
        privatekey_path: /tmp/d_cert.key
        common_name:     leaf certificate

    - name: Setup - Generate leaf cert
      community.crypto.x509_certificate:
        path:                  /tmp/d_cert.crt
        csr_path:              /tmp/d_cert.csr
        ownca_path:            /tmp/b_intermediate.crt
        ownca_privatekey_path: /tmp/b_intermediate.key
        provider:               ownca
        force:                  "{{ bc_x509_certificate.changed }}"

    - name: Case A => works
      community.crypto.certificate_complete_chain:
        input_chain: "{{ lookup('file', '/tmp/d_cert.crt') }}"
        intermediate_certificates:
        - /tmp/b_intermediate.crt
        root_certificates:
        - /tmp/a_root.crt

    - name: Case B => doesn't work, but this is expected
      failed_when: no
      register: caseb
      community.crypto.certificate_complete_chain:
        input_chain: "{{ lookup('file', '/tmp/d_cert.crt') }}"
        intermediate_certificates:
        - /tmp/c_intermediate.crt
        root_certificates:
        - /tmp/a_root.crt

    - name: Assert that case B failed
      assert:
        that: "'Cannot complete chain' in caseb.msg"

    - name: Case C => works
      community.crypto.certificate_complete_chain:
        input_chain: "{{ lookup('file', '/tmp/d_cert.crt') }}"
        intermediate_certificates:
        - /tmp/c_intermediate.crt
        - /tmp/b_intermediate.crt
        root_certificates:
        - /tmp/a_root.crt

    - name: Case D => fails, yet very very close from case C # only difference is order of intermediate_certificates
      community.crypto.certificate_complete_chain:
        input_chain: "{{ lookup('file', '/tmp/d_cert.crt') }}"
        intermediate_certificates:
        - /tmp/b_intermediate.crt
        - /tmp/c_intermediate.crt
        root_certificates:
        - /tmp/a_root.crt
@felixfontein
Copy link
Contributor

Right now the module's code assumes that no two intermediate certificates have the same subject. If two of them have, it will use the latter one added to its internal certificate set. That's why case C works, while case D does not.

@felixfontein
Copy link
Contributor

I've implemented a fix in #403.

@shk3bq4d
Copy link
Author

Excellent, thank you! I'll give a try on Monday!

@shk3bq4d
Copy link
Author

I confirm that fix #403 worked out for me (currently at 4f60d9b / felixfontein/certificate_complete_chain-intermediate-subject )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants