Support Forum
The Forums are a place to find answers on a range of Fortinet products from peers and product experts.
timothyd
New Contributor II

Use Ansible to import Local Certificate

I would like to use an Ansible playbook to import an SSL certificate into my Fortigate appliance and set that newly-imported certificate as the Server Certificate. Does anyone have any code examples on how to do that?

Timothy
Timothy
1 Solution
timothyd
New Contributor II

I found that after uploading the certificate to Fortinet, I needed to update the SSL VPN configuration so that the Fortinet appliance was using the latest generated LetsEncrypt certificate. After that, I needed to update the SSO configuration to use the same newly-generated SSL certificate. 

 

Because I wasn't able to find Ansible modules to do that in the `fortinet.fortios collection` collection (someone feel free to correct me if these do exist), I ended up writing a playbook that utilised the Fortinet HTTP API directly.

 

I will be writing a blog post about this on our website sometime within the next week or two. In the interim, see the entire playbook below:

 

 

 

---
- hosts: all
  gather_facts: no

  vars:
    cert_fc: /path/to/fullchain.pem
    cert_pk: /path/to/privkey.pem
    cert_fn: /path/to/subdomain.example.com.pem

  tasks:
    - block:
        - name: Create temporary directory
          ansible.builtin.tempfile:
            state: directory
            suffix: ansible_pb
          register: temp_dir

        - name: Copy Full Chain and Private Key to Temp Folder
          ansible.builtin.copy:
            src: "{{item}}"
            dest: "{{ temp_dir.path }}"
            remote_src: yes
          loop:
            - "{{cert_fc}}"
            - "{{cert_pk}}"


        - name: Assemble into a cert file
          ansible.builtin.assemble:
            src: "{{ temp_dir.path }}"
            dest: "{{ cert_fn }}"
          register: cert
          no_log: true


        - name: Convert file to PEM to PKCS12
          ansible.builtin.command: openssl pkcs12 -export -in {{cert_fc}} -inkey {{cert_pk}} -out {{temp_dir.path}}/domain.pfx -password pass:Example1234
          register: cert_pkcs12
          when: cert.changed == true
          no_log: true


        - name: Read certificate into Base64
          ansible.builtin.slurp:
            src: "{{temp_dir.path}}/domain.pfx"
          register: cert_b64
          when: cert.changed == true
          no_log: true

        - name: Upload SSL certificate to Fortinet
          ansible.builtin.uri:
            url: "https://192.168.1.1/api/v2/monitor/vpn-certificate/local/import?access_token={{ Fortinet_APIKey }}"
            method: POST
            body_format: json
            body:
              type: pkcs12
              certname: subdomain.example.com
              password: Example1234
              scope: global
              file_content: "{{cert_b64.content}}"
            validate_certs: false
          when: cert.changed == true
          delegate_to: localhost
          no_log: true

        - name: Change VPN certificate to newly uploaded cert
          ansible.builtin.uri:
            url: "https://192.168.1.1/api/v2/cmdb/vpn.ssl/settings?access_token={{ Fortinet_APIKey }}"
            method: PUT
            body:
              servercert:
                q_origin_key: "subdomain.example.com"
            validate_certs: false
            body_format: json
          when: cert.changed == true
          delegate_to: localhost
          no_log: true

        - name: Change SSO certificate to newly uploaded cert
          ansible.builtin.uri:
            url: "https://192.168.1.1/api/v2/cmdb/user/saml/fac-sslvpn?access_token={{ Fortinet_APIKey }}"
            method: PUT
            body:
              cert: "subdomain.example.com"
            body_format: json
            validate_certs: false
          when: cert.changed == true
          delegate_to: localhost
          no_log: true

      rescue:
        - name: Failed to combine cert
          set_stats:
            data:
              ErrorCode: 166f54e4-d9b7-41b6-9fbc-d56420933f0

        - meta: end_play


      always:
        - name: Remove Temporary Directory
          ansible.builtin.file:
            path: "{{ temp_dir.path }}"
            state: absent
          when: temp_dir.path is defined

 

 

* Use at your own risk.

Timothy

View solution in original post

Timothy
4 REPLIES 4
Anthony_E
Community Manager
Community Manager

Hello Timothy,

 

Thank you for using the Community Forum.

I will seek to get you an answer or help. We will reply to this thread with an update as soon as possible.


Regards,

Anthony-Fortinet Community Team.
Anthony_E
Community Manager
Community Manager

Hello Timothy,

 

We are still looking for someone to help you.

We will come back to you ASAP.


Regards

Anthony-Fortinet Community Team.
Anthony_E
Community Manager
Community Manager

Hello Timothy,

 

I found this documentation:

 

https://docs.ansible.com/ansible/latest/collections/fortinet/fortios/fortios_certificate_ca_module.h...

 

Could you please indicate me if it helped?

 

Regards,

Anthony-Fortinet Community Team.
timothyd
New Contributor II

I found that after uploading the certificate to Fortinet, I needed to update the SSL VPN configuration so that the Fortinet appliance was using the latest generated LetsEncrypt certificate. After that, I needed to update the SSO configuration to use the same newly-generated SSL certificate. 

 

Because I wasn't able to find Ansible modules to do that in the `fortinet.fortios collection` collection (someone feel free to correct me if these do exist), I ended up writing a playbook that utilised the Fortinet HTTP API directly.

 

I will be writing a blog post about this on our website sometime within the next week or two. In the interim, see the entire playbook below:

 

 

 

---
- hosts: all
  gather_facts: no

  vars:
    cert_fc: /path/to/fullchain.pem
    cert_pk: /path/to/privkey.pem
    cert_fn: /path/to/subdomain.example.com.pem

  tasks:
    - block:
        - name: Create temporary directory
          ansible.builtin.tempfile:
            state: directory
            suffix: ansible_pb
          register: temp_dir

        - name: Copy Full Chain and Private Key to Temp Folder
          ansible.builtin.copy:
            src: "{{item}}"
            dest: "{{ temp_dir.path }}"
            remote_src: yes
          loop:
            - "{{cert_fc}}"
            - "{{cert_pk}}"


        - name: Assemble into a cert file
          ansible.builtin.assemble:
            src: "{{ temp_dir.path }}"
            dest: "{{ cert_fn }}"
          register: cert
          no_log: true


        - name: Convert file to PEM to PKCS12
          ansible.builtin.command: openssl pkcs12 -export -in {{cert_fc}} -inkey {{cert_pk}} -out {{temp_dir.path}}/domain.pfx -password pass:Example1234
          register: cert_pkcs12
          when: cert.changed == true
          no_log: true


        - name: Read certificate into Base64
          ansible.builtin.slurp:
            src: "{{temp_dir.path}}/domain.pfx"
          register: cert_b64
          when: cert.changed == true
          no_log: true

        - name: Upload SSL certificate to Fortinet
          ansible.builtin.uri:
            url: "https://192.168.1.1/api/v2/monitor/vpn-certificate/local/import?access_token={{ Fortinet_APIKey }}"
            method: POST
            body_format: json
            body:
              type: pkcs12
              certname: subdomain.example.com
              password: Example1234
              scope: global
              file_content: "{{cert_b64.content}}"
            validate_certs: false
          when: cert.changed == true
          delegate_to: localhost
          no_log: true

        - name: Change VPN certificate to newly uploaded cert
          ansible.builtin.uri:
            url: "https://192.168.1.1/api/v2/cmdb/vpn.ssl/settings?access_token={{ Fortinet_APIKey }}"
            method: PUT
            body:
              servercert:
                q_origin_key: "subdomain.example.com"
            validate_certs: false
            body_format: json
          when: cert.changed == true
          delegate_to: localhost
          no_log: true

        - name: Change SSO certificate to newly uploaded cert
          ansible.builtin.uri:
            url: "https://192.168.1.1/api/v2/cmdb/user/saml/fac-sslvpn?access_token={{ Fortinet_APIKey }}"
            method: PUT
            body:
              cert: "subdomain.example.com"
            body_format: json
            validate_certs: false
          when: cert.changed == true
          delegate_to: localhost
          no_log: true

      rescue:
        - name: Failed to combine cert
          set_stats:
            data:
              ErrorCode: 166f54e4-d9b7-41b6-9fbc-d56420933f0

        - meta: end_play


      always:
        - name: Remove Temporary Directory
          ansible.builtin.file:
            path: "{{ temp_dir.path }}"
            state: absent
          when: temp_dir.path is defined

 

 

* Use at your own risk.

Timothy
Timothy
Top Kudoed Authors