Import Cert to FortiGate FortiOS

Hi All, I’m trying to develop a script that will export a multi SAN cert from CTW and then upload it to a FortiGate unit running FortiOS 7.0.1.

I know this version has limited ability to do it’s own request but it needs an ACME challenge server behind it so it’s much simpler if I can get it from my CTW instance uploaded to the FortiGate and then I can run an additional command to set it for a particular usage.

If anyone has even some basic clues to follow or some examples, that’d be extremely helpful.

Just to clarify, the cert is generating fine on my Windows 2019 box and it goes into the local certificate store without issue.

I don’t know anything about FortiGate myself but a useful feature of Certify is Deployment Tasks (under Tasks) - these are steps you can add at the end of certificate renewal to convert and deploy the certificate in various ways. You can also add a task and run it immediately if you already have a working certificate.

Some of the tasks include:

  • Deploy to Generic Server: this can export as .pem format files (.crt, .key etc) and optionally copy the file over SFTP to a remote host.
  • Script: this can run local scripts or even SSH into a remote host and run scripts there.

Ideally you need the fortigate to have an API you can push the certificate to, or accept SSH/SFTP, or in some cases people use powershell etc to login to the web UI and post files etc, but that’s a bit brittle if the admin UI ever changes.

It looks to me like the FortiGate OS has some built in support for ACME (e.g. Let’s Encrypt) if you look at the CLI section at the bottom of this document: New Features | FortiGate / FortiOS 7.0.0 | Fortinet Documentation Library

1 Like

I had written a script prior to FortiOS 7 that could do this (not from certifytheweb but actually from Win-Acme. It used a whole bunch of commands using a script for Putty. It wasn’t elegant and wasn’t secure but it worked.

The Fortigate can now do this on it’s own, though I don’t think with multi-SAN. If that is absolutely needed I would actually look for a way to do it via the Fortigate API and then try to figure it out as a web deployment task.

If you want though I can find (I hope) and send my old scripts. But honestly it seems like in this case I would allow the Fortigate to do it on it’s own.

1 Like

If you could find them I think that’d be a fantastic help. The main requirement I have is to grab the cert that CTW generates and upload it because

  1. The FortiGate using it’s built in Let’s Encrypt option won’t allow SAN or Wildcard, only single name certs and the objective is to use the certificate for Web Load Balancing, SSL-VPN and Management interface, all with different FQDN’s

  2. Using the built in engine also expects that there is ACME server sitting behind the requesting IP and I’m not keen on that as it adds complexity (As well as a Linux box which I’m not keen on managing)

Definitely appreciate the replies so far

Thanks webprofusion,

The FortiGate definitely has an API, and being really upfront, I wouldn’t have a clue how to use it. I’m doing a bit of research at the moment however if I could do something in PowerShell like nsummer uses, I think I’d be far more competent at fixing it long term if I had to do any troubleshooting.

1 Like

I just went hunting and finally found it.

Some obvious changes to protect the innocent.

@echo off
set username=admin
set password=Notachance
set firewallip=fw.mydomain.com
echo config vpn certificate local > fgscript.txt
echo.edit fw.mydomain.com >> fgscript.txt
echo.set private-key ^" >> fgscript.txt
copy fgscript.txt + c:\sslcerts\fw\fw.mydomain.com-key.pem fgscript.txt
echo ^" >> fgscript.txt
echo.set certificate ^" >> fgscript.txt
copy fgscript.txt + c:\sslcerts\fw\fw.mydomain.com-crt.pem fgscript.txt
echo.^" >> fgscript.txt
echo.end >> fgscript.txt
echo.config system global >> fgscript.txt
echo.unset admin-server-cert >> fgscript.txt
echo.end >> fgscript.txt
echo.config system global >> fgscript.txt
echo.set admin-server-cert fw.mydomain.com >> fgscript.txt
echo.end >> fgscript.txt
echo.exit >> fgscript.txt

plink -ssh %firewallip% -l %username% -pw %password% -batch -m fgscript.txt
1 Like

I believe this was the last used version of the script. Obviously I had everything export (in a task) to c:\sslcerts\fw\

The really annoying thing is that it isn’t too secure. It uses plink (which is part of Putty) to do the actual connection. I looked at doing it with Powershell but this was honestly just way easier.

There is also a Script task under Tasks which you can use for ssh, so you could potentially run it using that instead of plink.

So as it turns out I went to use this. I had 2 problems.

The first is for some reason it couldn’t run plink but I am sure I could give a full path and make that work.

But what I really wanted to do was use the built in SSH task. It runs in zero time flat, but doesn’t actually work. How can I tell what it is doing. I told it to run the “batch or script” of c:\fgcrt\fgscript.txt which contains exactly what I need run within the SSH session.

If you give the SSH task a script it will try to run the script on the remote host. If you view the status log for the managed certificate it may (or may not) show you extra information about what happened during ssh. Look for Executing command via SSH

Another possible trick is to create a windows scheduled task (but not schedule it) that runs whatever script you want as whichever user then use the powershell Task in Certify to start the scheduled task using Start-ScheduledTask - I haven’t tried it myself but it seems plausible for some scenarios.

So it sounds like in this case using the execution of a command via SSH is not going to work. I don’t need/can’t run a BASH script. I need the commands that I have to be run. I take it unfortunately there is no way to do this correct?

Where there’s a will there’s a way. I’m not clear on whether your script is one that should run on the remote host or if it should run on the machine running Certify? If it runs on that machine that certify is on, then it’s not a remote SSH script, it’s just a script (and should run on the local machine). I just don’t know anything about your script how it should work, maybe you could share it?

Sorry, unexpectedly flew to the US and back in the course of 2 and a half days…

The “script” is just a whole bunch of commands that get run via plink. Look at the 8th post here. I took this and ran with it. Really overly simple.

1 Like