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

FortiGate WebUI Tools > System info

Comment for more tool ideas!
Let's extend the FortiGate WebUI
Tested on FortiOS v7.0, 7.2

 

Installation:

  1. Login to your FortiGate's WebUI
  2. Create a new bookmark in your web browser and copy the JavaScript code below into the URL field.
  3. Click the bookmark and enjoy the Tools extension

Result:

image.png

Copy & paste into a bookmark:
javascript:(async function(){document.contains(document.getElementById("tools"))&&document.getElementById("tools").remove();let e="_cliWS",t="",s=["get system status","get system global","get system settings"],l=["get system arp","diag ip arp list"],n=window[e],i=!1,r;function a(e){n.send(`${e}\r`)}function o(e,t){let s=document.querySelector(`table[data-command="${r}"]`);if(s)switch(t){case"arp_cmd1":let[l,n,i,a]=e.replace(/\s+/g," ").split(" ");s.innerHTML+=`<tr><td style="border:1px solid grey;">${l}</td><td style="border:1px solid grey;text-align:center">${n}</td><td style="border:1px solid grey;text-align:center">${i}</td><td style="border:1px solid grey;text-align:center">${a}</td></tr>`;break;case"arp_cmd2":let[o,d,c,$,p,y,g,_,f]=e.replace(/\s+/g," ").split(" ");p=p.replace("00000000",'<span title="Pseudo state used while an ARP entry is initially created or just before it is removed"><f-icon class="fa-connected"></f-icon>&nbsp;NONE<span>'),p=p.replace("00000001",'<span title="First ARP request sent"><f-icon class="fa-connected"></f-icon>&nbsp;INCOMPLETE</span>'),p=p.replace("00000002",'<span title="ARP response is received"><f-icon class="fa-connected"></f-icon>&nbsp;REACHABLE</span>'),p=p.replace("00000004",'<span title="ARP response is not received within expected time"><f-icon class="fa-custom-action"></f-icon>&nbsp;STALE</span>'),p=p.replace("00000008",'<span title="Schedule ARP request"><f-icon class="fa-clock-plus"></f-icon>&nbsp;DELAY</span>'),p=p.replace("00000010",'<span title="Actively sending ARP requests to try and resolve the address"><f-icon class="fa-clock-plus"></f-icon>&nbsp;PROBE</span>'),p=p.replace("00000020",'<span title="Not managed to resolve ARP within max configured number of probes"><f-icon class="fa-cancel"></f-icon>&nbsp;FAILED</span>'),p=p.replace("00000040",'<span title="Device does not support ARP e.g. IPsec Interface"><f-icon class="fa-dismiss"></f-icon>&nbsp;NOARP</span>'),p=p.replace("00000080",'<span title="Statically configured ARP entry">PERMANENT</span>'),s.innerHTML+=`<tr><td style="border:1px solid grey;text-align:center">${d.substring(d.indexOf("=")+1)}</td><td style="border:1px solid grey">${c}</td><td style="border:1px solid grey;text-align:center">${$}</td><td style="border:1px solid grey">${p.substring(p.indexOf("=")+1)}</td><td style="border:1px solid grey;text-align:center">${y.substring(y.indexOf("=")+1)}</td><td style="border:1px solid grey;text-align:center">${g.substring(g.indexOf("=")+1)}</td><td style="border:1px solid grey;text-align:center">${_.substring(_.indexOf("=")+1)}</td><td style="border:1px solid grey;text-align:center">${f.substring(f.indexOf("=")+1)}</td></tr>`;break;default:let[m,b]=e.split(/:(.*)/s);b=b.replace(/[dD]isable/g,'<f-icon class="fa-disabled"></f-icon>&nbsp;<span style="color:silver">Disabled</span>'),b=b.replace(/[nN]ot [aV]vailable/g,'<f-icon class="fa-disabled"></f-icon>&nbsp;<span style="color:silver">Not available</span>'),b=b.replace(/[eE]nable/g,'<f-icon class="fa-enabled"></f-icon>&nbsp;<span>Enabled</span>'),b=b.replace(/[cC]ertified/g,'<f-icon class="fa-enabled"></f-icon>&nbsp;<span>Certified</span>'),s.innerHTML+=`<tr><td style="border: 1px solid grey;">${m}</td><td style="border: 1px solid grey;">${b}</td></tr>`}else{switch((s=document.createElement("table")).dataset.command=r,s.dataset.active="active",s.style.margin="1rem",t){case"arp_cmd1":s.innerHTML='<tr><th style="border:1px solid grey;text-align:left">IP Address</th><th style="border:1px solid grey">Age(min)</th><th style="border:1px solid grey">MAC Address</th><th style="border:1px solid grey">Interface</th></tr>';break;case"arp_cmd2":s.innerHTML='<tr><th style="border:1px solid grey">Interface</th><th style="border:1px solid grey;text-align:left">IP Address</th><th style="border:1px solid grey">MAC Address</th><th style="border:1px solid grey;text-align:left">Status</th><th style="border:1px solid grey">Use</th><th style="border:1px solid grey">Confirm</th><th style="border:1px solid grey">Update</th><th style="border:1px solid grey">Ref</th></tr>';break;default:s.innerHTML='<tr><th style="border:1px solid grey;">Key</th><th style="border:1px solid grey;">Value</th></tr>'}let x=document.querySelector(`li[data-command="${r}"]`);!function e(t,s){s.parentNode.insertBefore(t,s.nextSibling)}(s,x)}}let d="";async function c(e){let s=await e.data.text();if(i){let l="";for(let n in s){let r=s[n];"\r"===l?"\n"===r&&d.length>0?(o(d,t),d=""):"\0"===r&&(d=""):"\r"!==r&&(d+=r),l=r}}else i=!0,a("")}function $(){let t="https:"===location.protocol?"wss:":"ws:",s=`${t}//${location.hostname}:${location.port}/ws/cli/open?cols=500&rows=500`;window[e]=n=new WebSocket(s),n.addEventListener("message",c),n.addEventListener("close",()=>window[e]=null)}let p=[{label:"System info",content:"",script:function(e){n||$();let l=document.createElement("ul");l.id="system-info-command-list",s.forEach(e=>{let s=document.createElement("li");s.style.marginBottom="1rem",s.style.color="green",s.style.cursor="pointer",s.dataset.command=e,s.innerHTML=`&nbsp;${e}<nu-icon class="icon" style="margin-left:auto;width:18px;height:14px;transform:rotate(0deg)"><svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" style="width: 18px; height: 18px;"><path d="m12.01 9.531-4.25 4.25a.747.747 0 0 1-1.06 0l-.706-.706a.747.747 0 0 1 0-1.06l3.012-3.012-3.012-3.012a.747.747 0 0 1 0-1.06l.703-.712a.747.747 0 0 1 1.06 0l4.25 4.25a.748.748 0 0 1 .002 1.062z"></path></svg></nu-icon>`,s.onclick=function(){if(t="sys_cmd",n){let e=this.nextSibling&&"TABLE"===this.nextSibling.nodeName?this.nextSibling:null,l=this.querySelector(".icon");if(e)"active"===e.dataset.active?(e.dataset.active="",e.style.display="none",l.style.transform="rotate(0deg)"):(e.dataset.active="active",e.style.display="block",l.style.transform="rotate(90deg)");else{i=!0;let o=s.dataset.command;a(o),r=o,l.style.transform="rotate(90deg)"}}else $()},l.appendChild(s)}),e.innerHTML="",e.style.overflow="auto",e.style.padding="1.5rem",e.appendChild(l)}},{label:"ARP info",content:"",script:function(e){n||$();let s=document.createElement("ul");s.id="system-arp-command-list",l.forEach(e=>{let l=document.createElement("li");l.style.marginBottom="1rem",l.style.color="green",l.style.cursor="pointer",l.dataset.command=e,l.innerHTML=`&nbsp;${e}<nu-icon class="icon" style="margin-left:auto;width:18px;height:14px;transform:rotate(0deg)"><svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" style="width: 18px; height: 18px;"><path d="m12.01 9.531-4.25 4.25a.747.747 0 0 1-1.06 0l-.706-.706a.747.747 0 0 1 0-1.06l3.012-3.012-3.012-3.012a.747.747 0 0 1 0-1.06l.703-.712a.747.747 0 0 1 1.06 0l4.25 4.25a.748.748 0 0 1 .002 1.062z"></path></svg></nu-icon>`,l.onclick=function(){if(t="arp_cmd1","diag"==this.innerHTML.substr(6,4)&&(t="arp_cmd2"),n){let e=this.nextSibling&&"TABLE"===this.nextSibling.nodeName?this.nextSibling:null,s=this.querySelector(".icon");if(e)"active"===e.dataset.active?(e.dataset.active="",e.style.display="none",s.style.transform="rotate(0deg)"):(e.dataset.active="active",e.style.display="block",s.style.transform="rotate(90deg)");else{i=!0;let o=l.dataset.command;a(o),r=o,s.style.transform="rotate(90deg)"}}else $()},s.appendChild(l)}),e.innerHTML="",e.style.overflow="auto",e.style.padding="1.5rem",e.appendChild(s)}}],y=document.querySelector("nu-nav-entry"),g=document.createElement("li"),_='<svg version="1.1" id="L4" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve"><circle fill="#555" stroke="none" cx="6" cy="50" r="6"><animate attributeName="opacity" dur="1s" values="0;1;0" repeatCount="indefinite" begin="0.1"/></circle><circle fill="#555" stroke="none" cx="26" cy="50" r="6"><animate attributeName="opacity" dur="1s" values="0;1;0" repeatCount="indefinite" begin="0.2"/></circle>circle fill="#555" stroke="none" cx="46" cy="50" r="6"><animate attributeName="opacity" dur="1s" values="0;1;0" repeatCount="indefinite" begin="0.3"/></circle></svg>';g.style.listStyle="none",g.id="tools",g.innerHTML='<div id="menu-toggle" style="color:#000;background-color:goldenrod;margin:0;padding:4px 0 1px 5px;border-left:3px solid #ffd700; display: flex;"><f-icon class="ftnt-webhook icon-lg"></f-icon>&nbsp;Tools<nu-icon class="icon" style="margin-left:auto;width:18px;height:18px;transform:rotate(90deg)"><svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg" style="width:18px;height:18px"><path d="m12.01 9.531-4.25 4.25a.747.747 0 0 1-1.06 0l-.706-.706a.747.747 0 0 1 0-1.06l3.012-3.012-3.012-3.012a.747.747 0 0 1 0-1.06l.703-.712a.747.747 0 0 1 1.06 0l4.25 4.25a.748.748 0 0 1 .002 1.062z"></path></svg></nu-icon></div>',y.before(g);let f=!0,m=document.createElement("ul");async function b(e){let t,s=document.getElementById("ng1-app").getElementsByTagName("div")[0];s.innerHTML=`<div style="position:relative;overflow-y:auto"><pre style="padding:1em;margin:0;display:flex"><code style="width:100%; display:flex; justify-content:center;">${_}</code></pre></div>`,t=e.content,m.querySelectorAll("li").forEach(e=>{e.style["background-color"]="#ffd700",e.style.color="black",e.dataset.active=""}),s.style.width="100%",s.innerHTML=`<div style="position:relative;overflow-y:auto"><pre style="padding:1em;margin:0;display:flex"><code style="width:100%; display:flex; justify-content:center;">${t??_}</code></pre></div>`,e.script?.(s)}m.style.margin=0,m.style.padding=0,p.forEach((e,t)=>{let s=document.createElement("li");s.innerText=e.label,s.style.listStyle="none",s.style.color="black",s.style.backgroundColor="#FFD700",s.style.margin=0,s.style.padding="6px 0 5px 35px",s.style.cursor="pointer",s.style.fontWeight="normal",s.onmouseover=function(){this.style["background-color"]="#FFE86D"},s.onmouseout=function(){"active"!==this.dataset.active&&(this.style["background-color"]="#FFD700"),s.onclick=async function(){this.dataset.active="active",await b(e)}},m.appendChild(s)});let x=document.querySelector("#tools #menu-toggle"),u=x.querySelector(".icon");x.after(m),x.onclick=()=>{f?(m.style.display="none",u.style.transform="rotate(0deg)",f=!1):(m.style.display="block",u.style.transform="rotate(90deg)",f=!0)}})();

Roadmap (planned):

  • ARP info  Done
  • VPN diagnostics
  • FortiGate health check / audit / security assessment
  • FortiOS v7.4 support
12 REPLIES 12
RBS
New Contributor

How to do this?

Dannу
New Contributor III

Simply copy the JavaScript code into a new bookmark and click it to load the Tools menu.
animated.gif

RBS
New Contributor

Can you share the steps to access this? How to edit the URL with javascript you shared?