- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
TCL Script to apply Private Data Encryption (PDE) to Fortigates
Private data encryption (PDE) protects encrypted passwords that are configured on Fortigates. PDE does this by ensuring that encrypted passwords cannot be decrypted by third parties. This is particularly important in ensuring that bad actors who manage to get their hands on a Fortigate configuration cannot decrypt the passwords that are in the configuration. PDE is applied by applying a 32 character hexadecimal "key" to a Fortigate.
WARNING: Once you apply PDE key, you cannot change the key without first returning the Fortigate to a configuration that does not have PDE configured. So it is crucial to retain a backup of the Fortigate configuration just prior to applying PDE. Or otherwise, the Fortigate would have to be returned to default configuration, reconfiguring it, and then applying a new PDE key.
This article: https://community.fortinet.com/t5/FortiGate/Technical-Tip-How-to-enable-private-data-encryption-feat... includes this important key piece of information: "If [the PDE key is lost or] forgotten, changing the private data encryption key is possible and does not prompt for the old key or password. However, this key is not saved in the configuration and cannot be shown/extracted."
Well, I think "changing the private data encryption key is possible" is actually a typing mistake. It should say: "changing the private data encryption key is NOT POSSIBLE". And while the clear text PDE key is not stored in the configuration, the encrypted (and probably hashed first too) key IS stored in the configuration.
Another important thing to consider, is that once you apply PDE to a Fortigate, the key will need to be entered into FortiManager GUI (next time you try to access the Fortigate via FortiManager). You only need to enter it into FMG once. See: https://docs.fortinet.com/document/fortimanager/7.4.2/administration-guide/30332/verifying-devices-w...
But, this does mean that you don't want to lose/misplace/forget the PDE key! Or else you need to factory reset your Fortigate to recover. Or, revert it to the pre-PDE config (remember that backup that you saved just prior to applying PDE). And if you ever have to rebuild FortiManager from nothing, any lost PDE keys could cause you a lot of work!
The TCL script below is for applying PDE to Fortigates from Fortimanager.
#!
################################################################
#--------------------------------------------------------------#
# -------- Apply private data encryption to Fortigate -------- #
#--------------------------------------------------------------#
################################################################
# Author: mhawkins@wantegrity.com
# Created: January 10th, 2025
# Last Edited: January 13th, 2025
################################################################
################################################################
# Caveats:
# As of version 7.6.1, FortiOS handles PDE keys automatically;
# making this script unnecessary. Do not run this script against
# Fortigates running 7.6.1 or higher. If you do, this script
# will fail.
################################################################
# WARNING: Once PDE is applied to a Fortigate, the key remains
# in place even if PDE is disabled later. And then, if you
# re-enable it again, it does not prompt you for a new key, it
# just uses the one that's already in place. This means that you
# MUST keep a backup of the Fortigate configuration taken just
# prior to enabling PDE (with this script). That backup config
# will be needed if you ever want to change the PDE key. To
# change PDE key, it will be necessary to revert the FGT to the
# pre-PDE configuration (from the pre-PDE backup config). Then,
# and only then, is it possible to apply a different PDE key.
# The alternative is to reset the Fortigate back to factory
# settings, reconfigure, and then apply PDE with a new key.
#
# WARNING: The PDE key is applied to Fortigate in clear text.
# So this script contains the actual key. But once the key is
# applied, the Fortigate immediately encrypts it (probably an
# encrypted hash actually). So only the encrypted key appears
# on the Fortigate.
#
################################################################
# INSTRUCTIONS:
# The Fortigate PDE key must be a randomised and unique 32
# character hexadecimal string.
# Example: "cc03942587ab024a3dc8f10dd85b8566"
# To easily generate a random key, see:
# https://www.wantegrity.com/tools/fortinet/pdekey.php
#
# IMPORTANT: Save your PDE key in a secure place! And then remove
# it from the two variables below!
#
# The two variables below must be set to the PDE key. They are
# both there to help ensure that you enter the correct key
# before applying it to the Fortigate.
#
# IMPORTANT: Save your PDE key in a secure place! After you run
# this script, remove the key from the two variables below!
################################################################
set pde_key1 "<enter 32 character hexadecimal key here>"
set pde_key2 "<enter 32 character hexadecimal key here>"
################################################################
################################################################
# set verbose to true to increase script output
set verbose true
################################################################
################################################################
# Procedures
################################################################
proc do_cmd {cmd} {
return [puts [exec "$cmd\n" "# " 15]]
}
proc get_sys_status aname {
upvar $aname a
set a(vdom) true
set a(maxVdoms) 0
set input [exec "get system status\n" " # " 10 ]
set linelist [split $input \n]
foreach line $linelist {
if {[regexp {Virtual domain configuration: disable} $line]} { set a(vdom) false }
if {![regexp {([^:]+):(.*)} $line dummy key value]} continue
switch -regexp -- $key {
"Version" { regexp {FortiGate-([^ ]+) ([^,]+),build([\d]+),.*} $value dummy a(platform) a(version) a(build) }
"Serial-Number" { set a(serial-number) [string trim $value] }
"Hostname" { set a(hostname) [string trim $value] }
"Max number of virtual domains" { set a(maxVdoms) [string trim $value] }
}
}
}
################################################################
################################################################
# MAIN
set check true
# check that the keys are the same, correct length, and hexadecimal
if { ( $pde_key1 != $pde_key2 ) } {
puts "ERROR: The pde keys (defined in this script) do not match (are not equal). The keys MUST be equal."
set check false
}
if { ( [ string length $pde_key1 ] != 32 ) } {
puts "ERROR: pde_key1 (defined in this script) is not 32 characters long. PDE keys must be 32 characters long."
set check false
}
if { ![ regexp {^[a-fA-F0-9]{32}$} $pde_key1 ] } {
puts "ERROR: pde_key1 (defined in this script) is not hexadecimal. PDE keys must be hexadecimal strings."
set check false
}
if { ( [ string length $pde_key2 ] != 32 ) } {
puts "ERROR: pde_key2 (defined in this script) is not 32 characters long. PDE keys must be 32 characters long."
set check false
}
if { ![ regexp {^[a-fA-F0-9]{32}$} $pde_key2 ] } {
puts "ERROR: pde_key2 (defined in this script) is not hexadecimal. PDE keys must be hexadecimal strings."
set check false
}
if { ( $check == true ) } {
# get FortiGate information to determine if vdoms are enabled
# and exit if they ARE enabled
get_sys_status status
if { ($verbose == true) } {
puts "This Fortigate is model: \[$status(platform)\]."
puts "It is running FortOS version: \[$status(version)\]."
puts "The firmware is build number: \[$status(build)\]."
puts "The device serial number is: \[$status(serial-number)\]."
puts "The machine hostname is: \[$status(hostname)\]."
puts -nonewline "VDOMs: \["
if { ($status(vdom) == true) } { puts "enabled\]" } else { puts "disabled\]." }
}
if { ($status(vdom) == true) } {
if { ($verbose == true) } { puts "VDOMs are enabled. So entering: 'config global'" }
do_cmd "config global"
}
if { ($verbose == true) } { puts "Sending: 'config system global'" }
do_cmd "config system global"
if { ($verbose == true) } { puts "Sending: 'set private-data-encryption enable'" }
do_cmd "set private-data-encryption enable"
if { ($verbose == true) } { puts "Sending: 'end'" }
set result [ exec "end\n" ":| # " 15 ]
if { [ regexp "numbers" $result ] } {
if { ($verbose == true) } { puts "Got colon for a prompt. Sending key for the first time..." }
set result [ exec "$pde_key1\n" "again:| # " 15 ]
if { [ regexp "again:" $result ] } {
if { ($verbose == true) } { puts "Got colon for a prompt. Sending key for the second time..." }
set result [ exec "$pde_key2\n" "Error:| # " 15 ]
if { [ regexp "Error" $result ] } {
puts "ERROR: Something went wrong entering the key the second time."
} else {
puts "INFO: The private data encryption key was successfully applied to the Fortigate."
}
} else {
puts "ERROR: Something went wrong entering the key the first time."
if { [ regexp "not the correct format" $result ] } {
puts "Something went wrong with the PDE key (pde_key1). The Fortigate says it is not in the correct format."
}
}
} else {
puts "WARNING: private data encyption is already enabled and initialized. Exiting..."
}
} else {
puts "ERROR: There was a failure with the PDE keys. Nothing was done. Script finished and exiting..."
return -1
}
################################################################
puts "Script Finished. Exiting..."
################################################################
- Labels:
-
FortiGate
-
FortiManager
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
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.
Thanks,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Anthony,
I don't have any questions on this topic. I posted this article as a service to other Fortinet customers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you then :)