---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later

- name: Get servers certificate for SNI test part 1
  get_certificate:
    host: "{{ httpbin_host }}"
    port: 443
    server_name: "{{ sni_host }}"
    asn1_base64: true
  register: result

- debug: var=result

- assert:
    that:
      # This module should never change anything
      - result is not changed
      - result is not failed
      # We got the correct ST from the cert
      - "'{{ sni_host }}' == result.subject.CN"

- name: Get servers certificate for SNI test part 2
  get_certificate:
    host: "{{ sni_host }}"
    port: 443
    server_name: "{{ httpbin_host }}"
    asn1_base64: true
  register: result

- debug: var=result

- assert:
    that:
      # This module should never change anything
      - result is not changed
      - result is not failed
      # We got the correct ST from the cert
      - "'{{ httpbin_host }}' == result.subject.CN"

- name: Get servers certificate
  get_certificate:
    host: "{{ httpbin_host }}"
    port: 443
    select_crypto_backend: "{{ select_crypto_backend }}"
    asn1_base64: true
  register: result

- debug: var=result

- assert:
    that:
      # This module should never change anything
      - result is not changed
      - result is not failed
      # We got the correct ST from the cert
      - "'North Carolina' == result.subject.ST"

- name: Connect to http port (will fail because there is no SSL cert to get)
  get_certificate:
    host: "{{ httpbin_host }}"
    port: 80
    select_crypto_backend: "{{ select_crypto_backend }}"
    asn1_base64: true
  register: result
  ignore_errors: true

- assert:
    that:
      - result is not changed
      - result is failed
      # We got the expected error message
      - >-
        'The handshake operation timed out' in result.msg
        or 'unknown protocol' in result.msg
        or 'wrong version number' in result.msg
        or 'record layer failure' in result.msg
 
- name: Test timeout option
  get_certificate:
    host: "{{ httpbin_host }}"
    port: 1234
    timeout: 1
    select_crypto_backend: "{{ select_crypto_backend }}"
    asn1_base64: true
  register: result
  ignore_errors: true

- assert:
    that:
      - result is not changed
      - result is failed
      # We got the expected error message
      - "'Failed to get cert from port with error: timed out' == result.msg or 'Connection refused' in result.msg"

- name: Test failure if ca_cert is not a valid file
  get_certificate:
    host: "{{ httpbin_host }}"
    port: 443
    ca_cert: dn.e
    select_crypto_backend: "{{ select_crypto_backend }}"
    asn1_base64: true
  register: result
  ignore_errors: true

- assert:
    that:
      - result is not changed
      - result is failed
      # We got the correct response from the module
      - "'ca_cert file does not exist' == result.msg"

- name: Download CA Cert as pem from server
  get_url:
    url: "http://ansible.http.tests/cacert.pem"
    dest: "{{ remote_tmp_dir }}/temp.pem"

- name: Get servers certificate comparing it to its own ca_cert file
  get_certificate:
    ca_cert: '{{ remote_tmp_dir }}/temp.pem'
    host: "{{ httpbin_host }}"
    port: 443
    select_crypto_backend: "{{ select_crypto_backend }}"
    asn1_base64: true
    get_certificate_chain: "{{ has_get_certificate_chain }}"
  register: result

- assert:
    that:
      - result is not changed
      - result is not failed

- name: Read CA cert
  slurp:
    src: '{{ remote_tmp_dir }}/temp.pem'
  register: cacert
  when: has_get_certificate_chain

- name: Validate get_certificate_chain=true results
  assert:
    that:
      - result.verified_chain is sequence
      - result.unverified_chain is sequence
      - result.verified_chain[0] == result.cert
      - result.unverified_chain[0] == result.cert
      - result.verified_chain[-1] == cacert.content | b64decode
      - result.verified_chain == result.unverified_chain + [cacert.content | b64decode]
  when: has_get_certificate_chain

- name: Validate get_certificate_chain=false results
  assert:
    that:
      - result.verified_chain is undefined
      - result.unverified_chain is undefined
  when: not has_get_certificate_chain

- name: Generate bogus CA privatekey
  openssl_privatekey:
    path: '{{ remote_tmp_dir }}/bogus_ca.key'
    type: ECC
    curve: secp256r1

- name: Generate bogus CA CSR
  openssl_csr:
    path: '{{ remote_tmp_dir }}/bogus_ca.csr'
    privatekey_path: '{{ remote_tmp_dir }}/bogus_ca.key'
    subject:
      commonName: Bogus CA
    useCommonNameForSAN: false
    basic_constraints:
      - 'CA:TRUE'
    basic_constraints_critical: true

- name: Generate selfsigned bogus CA certificate
  x509_certificate:
    path: '{{ remote_tmp_dir }}/bogus_ca.pem'
    csr_path: '{{ remote_tmp_dir }}/bogus_ca.csr'
    privatekey_path: '{{ remote_tmp_dir }}/bogus_ca.key'
    provider: selfsigned
    selfsigned_digest: sha256

- name: Get servers certificate comparing it to an invalid ca_cert file
  get_certificate:
    ca_cert: '{{ remote_tmp_dir }}/bogus_ca.pem'
    host: "{{ httpbin_host }}"
    port: 443
    select_crypto_backend: "{{ select_crypto_backend }}"
    asn1_base64: true
  register: result
  ignore_errors: true

- assert:
    that:
      - result is not changed
      - result is failed
