As FortiSASE currently lacks an official public API, I thought I'd share a little bash-script I just wrote that uses cURL to login to FortiSASE via SAML/SSO and can then access the backend REST(ish)-API used by the FortiSASE portal natively.
I needed this to automate the process of adding ZTNA destinations as part of our customers build pipeline.
Please ignore the ugly grep/sed's and just see this as proof-of-concept code for inspiration.
Also be aware that as the API is currently not documented or intended to be used by end customers, I assume Fortinet will not give you any support if you experience problems with the API, so please use this code on your own risk.
#!/bin/bash
#################################################################################
# CURL snippet to use SAML IAM Login to FortiSASE to consume it's REST API.
#################################################################################
curl_opts="-s --cookie-jar saseCookieFile --cookie saseCookieFile --insecure"
fortisase_baseurl="https://portal.prod.fortisase.com"
fortisase_loginurl="https://portal.prod.fortisase.com/saml/ssoLogin"
fortisase_apiloginurl="https://portal.prod.fortisase.com/api/v1/system/login/sso"
fortisso_baseurl="https://customersso1.fortinet.com"
fortisso_loginurl="https://customersso1.fortinet.com/saml-idp/iam_login/"
forti_account="123456"
forti_username="firstname.lastname"
forti_password="xxxxx"
# Delete old Cookie-file:
rm saseCookieFile &> /dev/null
# Get FortiSASE pre-login page and save SAMLRequest:
echo "GET ${fortisase_baseurl}/pre-login"
saml_loginurl=$(curl -i ${curl_opts} ${fortisase_baseurl}/pre-login | grep Location | sed "s/Location: //g" | tr -d $'\r')
saml_request=$(echo "${saml_loginurl}" | sed 's/^.*\?SAMLRequest=/\?SAMLRequest=/')
# Get SAML pre-login page and save sessionid Cookie:
echo "GET ${saml_loginurl}"
curl ${curl_opts} ${saml_loginurl} &> /dev/null
# Get Fortinet IAM Login page and save CSRFTOKEN in login form:
echo "GET ${fortisso_loginurl}/?SAMLRequest=xxxx"
res=$(curl ${curl_opts} ${fortisso_loginurl}/${saml_request})
csrftoken=`echo "${res}" | grep csrfmiddlewaretoken | awk -F '"' '{print $6}' `
# Perform Forinet IAM SAML Login and save SAMLResponse:
echo "POST ${fortisso_loginurl}"
data="csrfmiddlewaretoken=${csrftoken}&next=/saml-idp/portal/&account=${forti_account}&username=${forti_username}&password=${forti_password}"
res=$(curl ${curl_opts} --location --referer ${fortisso_baseurl} --data ${data} ${fortisso_loginurl}${saml_request})
saml_response=`echo "${res}" | grep SAMLResponse | awk -F '"' '{print $6}'`
# Perform SAML SSO Login to FortiSASE to get x-auth-token Cookie:
echo "POST ${fortisase_loginurl}"
res=$(curl -i ${curl_opts} --location --referer ${fortisso_baseurl} --data-urlencode RelayState= --data-urlencode SAMLResponse=${saml_response} ${fortisase_loginurl})
xauthtoken=$(echo "${res}" | grep x-auth-token | sed -n 's/.*=\([^;]*\);.*/\1/p')
# Parse SAMLResponse and create API Login JSON data:
echo "Parse SAMLResponse and generate JSON Login data"
saml_decoded=$(echo "${saml_response}" | base64 -d | xmllint --format -)
iam_account_alias=$(echo "${saml_decoded}" | grep -A1 IAM_account_alias | sed -n 2p | sed -n 's/.*>\(.*\)<.*/\1/p')
iam_account_name=$(echo "${saml_decoded}" | grep -A1 IAM_account_name | sed -n 2p | sed -n 's/.*>\(.*\)<.*/\1/p')
iam_user_name=$(echo "${saml_decoded}" | grep -A1 IAM_username | sed -n 2p | sed -n 's/.*>\(.*\)<.*/\1/p')
nameID=$(echo "${saml_decoded}" | grep -A1 idp_user_id | sed -n 2p | sed -n 's/.*>\(.*\)<.*/\1/p')
data='
{
"auth_type": "iam",
"authentication_status": "password only",
"company": {
"name": ""
},
"iam_account_alias": "IAM_ACCOUNT_ALIAS",
"iam_account_name": "IAM_ACCOUNT_NAME",
"iam_user_name": "IAM_USER_NAME",
"name": "IAM_USER_NAME",
"nameID": "NAMEID",
"principal": "IAM_USER_NAME",
"root": false,
"tenant": {
"account_id": "IAM_ACCOUNT_NAME",
"root_principal": "IAM_ACCOUNT_NAME"
}
}'
data=$(sed "s/IAM_ACCOUNT_ALIAS/$iam_account_alias/g" <<< "$data")
data=$(sed "s/IAM_ACCOUNT_NAME/$iam_account_name/g" <<< "$data")
data=$(sed "s/IAM_USER_NAME/$iam_user_name/g" <<< "$data")
data=$(sed "s/NAMEID/$nameID/g" <<< "$data")
# Login to FortiSASE API to get access and refresh tokens:
echo "POST ${fortisase_apiloginurl}"
response=$(curl ${curl_opts} --referer ${fortisase_baseurl}/sso-login -H "auth-token: ${xauthtoken}" -H "Content-Type: application/json" -d "${data}" ${fortisase_apiloginurl})
access_token=$(echo "${response}" | jq -r .data.access_token)
refresh_token=$(echo "${response}" | jq -r .data.refresh_token)
# Perform API to get list of ZTNA destinations:
curl -s -H "Authorization: Bearer ${access_token}" https://portal.prod.fortisase.com/endpoint/fct/api/public/v1/sase_to_ems/profiles/ztna/2/get | jq .
Thanks bro
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.