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?
1 REPLY 1
TuncayBAS
Contributor II

Thanks bro

Tuncay BAS
RZK Muhendislik Turkey
FCA,FCP,FCF,FCSS
Tuncay BASRZK Muhendislik TurkeyFCA,FCP,FCF,FCSS
Announcements

Select Forum Responses to become Knowledge Articles!

Select the “Nominate to Knowledge Base” button to recommend a forum post to become a knowledge article.

Labels
Top Kudoed Authors