Fortigate VPN Certificate

Apparently I can’t do posts with more than one image yet (argh), so here is this same toutorial with images

We are using CertifyTheWeb to renew certificates on our FortiGate for use in the VPN portal. Here is a quick tutorial:

Create a folder accessable to the CertifyTheWeb service user, but not accessible to anyone who should not have access to the FortiGate API key or certificate key

create a new permissions profile using the CLI on the FortiGate

config system accprofile
    edit "certificate_update"
        set scope global
        set sysgrp custom
        set vpngrp read-write
        config sysgrp-permission
            set cfg read-write
        end
    next
end

create a new API user with the profile:
image

Save the api key it gives you to a text file named “apikey.txt” in the folder you created earlier

We will be using this script to upload certificates to the FortiGate. I have pre-compiled this to an EXE for you here (or use a mirror, or compile it yourself). Download the EXE and save it in the folder you created earlier.

We will use a batch file to upload the certificate (using the EXE), switch the certificate used by the SSL VPN portal, and do some cleanup. Save this as “deploy.bat” (replace “10.10.10.10:10443” with the IP and port of your FortiGate):

:: this file is run as a CertifyTheWeb deployment task
:: the only argument should be a name for the certificate

:: cd to current directory
cd /D "%~dp0"

:: format cert name as firstarg-2020-12-31
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YYYY=%dt:~0,4%"
set "MM=%dt:~4,2%"
set "DD=%dt:~6,2%"
set "certname=%*-%YYYY%-%MM%-%DD%"

:: upload the certificate to the fortigate
update-fortigate-cert.exe ^
--chain chain.pem ^
--cert cert.pem ^
--privkey key.pem ^
--cert-name-format "%certname%" ^
--prune-prefix "%*-" ^
--hostname "10.10.10.10:10443" ^
--no-verify ^
--api-key-file=apikey.txt

:: change the VPN certificate to the one we just uploaded
set /p apikey=<apikey.txt
curl ^
--insecure ^
--request PUT ^
--url "https://10.10.10.10:10443/api/v2/cmdb/vpn.ssl/settings?access_token=%apikey%" ^
--header "Content-Type: application/json" ^
--data "{""servercert"":{""q_origin_key"":""%certname%""}}"

del chain.pem
del cert.pem
del key.pem

Create a new certificate in CertifyTheWeb. Set up status/certificate/authorization as normal (you will probably want to use a DNS based form of authorization). Set deployment to “No Deployment”

We are going to create 2 custom deployment tasks. The first task should be of type “Deploy to Generic Server”. In the “Task Parameters” section, set the output filepath for cert, key, and CA chain to “cert.pem”, “key.pem”, and “chain.pem” in the folder you created earlier.

The second task should be of type “Run…”. Put in the path to the bat file you created earlier. In the arguments field put in a name that will be used for the certificate. This will only be visible in the FortiGate admin interface. I prefer to set a timeout, but it’s optional.

Save and request a certificate. It should be automatically pushed to the FortiGate. If you need to test the deployment part, you can just run the 2 tasks in order. You don’t have to get a new certificate each time just to test the scripts.

Debugging note: sometimes when you try to delete a certificate through the FortiGate GUI it doesn’t really delete it. Refresh the page to see if it comes back.

1 Like

Hi Jon, thanks very much for sharing. I had modified your “trust level” on the forum so you could try editing your post if you wanted to add anything.