Forum Discussion

mhashemi's avatar
4 years ago

Trouble with Fortigate PropertySource script

I am trying to write a Groovy PropertySource script, which will SSH into Fortigate devices and return the list of available VDOMs.

In Putty, I would run the command

    config vdom -> Enter

Then I would type "edit ?" and without hitting enter, the list of available VDOMs would appear (where each VDOM entry beginning with "<vdom> Virtual Domain Name"):

    

I have the following Groovy script (modified from a ConfigSource in the portal):

import com.santaba.agent.util.Settings
import net.schmizz.sshj.SSHClient
import net.schmizz.sshj.connection.channel.direct.Session
import net.schmizz.sshj.transport.verification.PromiscuousVerifier
import java.util.concurrent.TimeUnit
import java.security.MessageDigest

//def host = hostProps.get("system.hostname")
def host = "<ip address>"
//def user = hostProps.get("ssh.user", hostProps.get("config.user"))
def user = "<username>"
//def pass = hostProps.get("ssh.pass", hostProps.get("config.pass"))
def pass = "<password>"
//def port = hostProps.get("auto.config.port", "22")
def port = "22"

def time = (Settings.getSettingInt("configcollector.script.timeout", 120) - 1) * 1000

def startTime = System.currentTimeMillis()

def client = new SSHClient()
client.setTimeout(time)
client.setConnectTimeout(time)
client.addHostKeyVerifier(new PromiscuousVerifier())

try { client.loadKnownHosts() } catch (ex) { /* No Known Hosts File */ }

def session

try {
    client.connect(host, port.toInteger())

    if(pKey && new File(pKey).exists()) {
        client.authPublickey(user, client.loadKeys(pKey))
    } else {
        client.authPassword(user, pass)
    }

    session = client.startSession()
    session.allocateDefaultPTY()

    def cmd = session.exec("config vdom\n edit ?")
    cmd.join(time.toInteger(), TimeUnit.MILLISECONDS)
    cmd.close()

    def rawOut = cmd.getInputStream().text
    print "rawout: " + rawOut
    def out = rawOut.trim()

    if(out) {
        print out
    }
}
catch (Exception ex) {
    println ex
}
finally {
    session?.close()
    client?.disconnect()
}

The result is only "true" (from !groovy).

I'm not super great with Groovy, what am I missing here? Thanks.

  • Anonymous's avatar
    Anonymous
    4 years ago

    Hm, so the issue is that, when executing these commands manually, the question mark itself prompts a response from the target device. I'm not familiar with the library used to perform the SSH session here, but the target device should receive the question mark and spit out the output the same. Do you need to get the output stream instead of the input stream?

        def rawOut = cmd.getInputStream().text
    

    Like i said, not familiar with that particular method of connecting via SSH. I use JSch or Expect.

  • 3 hours ago, Stuart Weenig said:

    Like i said, not familiar with that particular method of connecting via SSH. I use JSch or Expect.

     

    This seems to be working better (at least I can get back data). Now I am running into a problem adding the VDOMs to a list, which I will (eventually) turn into a property. I am getting the following output:

    Any idea why, with the code below, I am failing to append "root" and "exit" to the list of VDOMs?

     

    import com.santaba.agent.groovyapi.expect.Expect
    
    hostname = hostProps.get("system.hostname")
    userid = hostProps.get("ssh.user")
    passwd = hostProps.get("ssh.pass")
    def list = new ArrayList()
    
    try {
        ssh_connection = Expect.open(hostname, userid, passwd)
    
        ssh_connection.expect("# ")
        ssh_connection.send("config vdom\n")
        ssh_connection.expect("# ")
        cmd_output = ssh_connection.before()
    
        if (cmd_output =~ /\(vdom\)/) {
            println "in vdom config, running the edit command"
            ssh_connection.send("edit ?\n")
            ssh_connection.expect("# ")
        }
    
        cmd_output2 = ssh_connection.before()
    
        println "attempting to parse vdoms"
        cmd_output2.eachLine { line ->
            if (!(line =~ /\<vdom\>/) && !(line =~ /^\s*$/) && !(line =~ "edit") && !(line =~ /\(vdom\)/)) {
                println "adding " + line + " to the list of vdoms"
                list.Add(line)
            }
        }
    
        ssh_connection.send("\025")
        ssh_connection.send("exit\n")
    
        println "returning vdoms:"
        println list.join(", ")
    
        return 0
    }
    catch (Exception e) {println e;return 1}
    finally {if (ssh_connection){ssh_connection.expectClose()}}
  • Anonymous's avatar
    Anonymous

    Hm, so the issue is that, when executing these commands manually, the question mark itself prompts a response from the target device. I'm not familiar with the library used to perform the SSH session here, but the target device should receive the question mark and spit out the output the same. Do you need to get the output stream instead of the input stream?

        def rawOut = cmd.getInputStream().text
    

    Like i said, not familiar with that particular method of connecting via SSH. I use JSch or Expect.

  • Just to be clear, I should add that, once this actually gets the command output, I will want to remove the "<vdom> Virtual Domain Name" lines and return the actual VDOM list as a comma-separated string.