Support Forum
The Forums are a place to find answers on a range of Fortinet products from peers and product experts.
msundman
New Contributor II

FortiSASE API cURL script

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 .

 

 

 

 

 

- How hard can it be?
- How hard can it be?
0 REPLIES 0
Labels
Top Kudoed Authors