Skip to main content
timothyd
New Member
December 22, 2022
Solved

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?

timothyd
timothydAnswer
New Member
January 3, 2023

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.

4 replies

Anthony_E
Staff
Staff
December 25, 2022

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,

Best Regards
Anthony_E
Staff
Staff
January 2, 2023

Hello Timothy,

 

We are still looking for someone to help you.

We will come back to you ASAP.


Regards

Best Regards
Anthony_E
Staff
Staff
January 3, 2023

Hello Timothy,

 

I found this documentation:

 

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

 

Could you please indicate me if it helped?

 

Regards,

Best Regards
timothyd
timothydAuthorAnswer
New Member
January 3, 2023

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.

Thought Leadership. Security Summit. Thursday, November 12th, PGA National Resort, Palm Beach Gardens, FL.
Thought Leadership. Security Summit. Thursday, October 8th. Disney's Grand Californian Hotel & SPA, Anaheim, CA.
Security Operations Summit: Modernize SecOps. Operate AI-Native.AMER: November 4 | 9:00 AM PST. India and SAARC: November 5 | 10:00 AM IST. EMEA: November 5 | 10:30 AM CET. APAC: November 5 | 11:00 AM SGT