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?
Solved! Go to Solution.
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.
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,
Hello Timothy,
We are still looking for someone to help you.
We will come back to you ASAP.
Regards
Hello Timothy,
I found this documentation:
Could you please indicate me if it helped?
Regards,
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.
Select Forum Responses to become Knowledge Articles!
Select the “Nominate to Knowledge Base” button to recommend a forum post to become a knowledge article.
User | Count |
---|---|
1740 | |
1108 | |
752 | |
447 | |
240 |
The Fortinet Security Fabric brings together the concepts of convergence and consolidation to provide comprehensive cybersecurity protection for all users, devices, and applications and across all network edges.
Copyright 2024 Fortinet, Inc. All Rights Reserved.