Skip to main content

I am trying to create a NQE query for all the F5 devices. The query searches for SSL profile on custom command. 

Custom Command is : 
show ltm virtual detail recursive | grep -E "Ltm::ClientSSL Profile:" -E "Virtual Server:"

The NQE should return SSL Profiles and the VIPs associated with them. 

 

Hey Shivang, 

the structure to access custom command is this: 

foreach d in network.devices

foreach c in d.output.commands

where c.commandText == "abc"

select {

name:d.name,

command:c.commandText,

response:c.response

}

 

However I see that your custom commands contains “” as in grep -E "Ltm::ClientSSL Profile:" -E "Virtual Server:"

This imposes a challenge during filtering of the commandText. My suggestion is to use a matches() function and globs to selectively filter for the custom command. Example: 

foreach d in network.devices

foreach c in d.output.commands

where matches(c.commandText, "*Ltm::ClientSSL Profile:*Virtual Server*")

select {

name:d.name,

command:c.commandText,

response:c.response

}

 

 

give it a try and let me know!

Jack 


Hey Jack, Thanks for sharing this the above mentioned query has already been tried and unfortunately it doesnt work at all ( Says to comment down the Where statement ) 

Also on a side note it should be outputs.commands ( For whoever is referring to this thread for their problems ) 


Hi Shivang, 

 

I see there is an issue with the double quote formatting. This should work for you. Make sure you are selecting the snapshot and network that has the custom command running. 

 

Regards,

Jack 

 

foreach d in network.devices
foreach c in d.outputs.commands
where isPresent(c.commandText)
where matches(c.commandText, "*Ltm::ClientSSL Profile:*Virtual Server*")
select { name: d.name, command: c.commandText, response: c.response }

 


This is a query I worked on with a customer for doing this for F5 devices.  We made it an export.  Also have a module like this for Netscaler. Then created another query where we put it all together.

See if this can give you inspiration.

/**
* @intent Collect F5 load balancer device certs
* @description Information grabbed in this NQE:
* - Device Name
* - Virtual Server and Address
* - Profile name
* - Profile cipher group
* - Profile cipher
* - Profile options
* - Certificate Name
* - Certificate key size
* - Certificate Expire Date
* - Certificate Serial
* - Certificate Alternative Name
* - Device Partition
*/

customCmdProfile =
"list ltm profile recursive client-ssl { partition cert ciphers cipher-group options }"
];

customCmdCert =
"list sys file ssl-cert recursive { expiration-string serial-number subject-alternative-name issuer certificate-key-size partition }"
];

// F5 Partition pattern - vip profile name
vipProfile =
```
ltm virtual {vserverName:string}
destination {vserverAddress:string}
partition {parition:string}
profiles
{profileName:string}
context clientside
```;

// F5 Partition pattern - certificate profile name match
certProfile =
```
ltm profile client-ssl {profileName:string}
cert {certName:string}
cipher-group {ciphergroup:string}
ciphers {ciphers:string}
options {options:(string*)}
partition {partition:string}
```;

// F5 Partition pattern - certification information
certInfo =
```
sys file ssl-cert {certName:string}
certificate-key-size {keySize:string}
expiration-string {expDate:(string*)}
issuer {issuer:(string*)}
partition {partition:string}
serial-number {serial:string}
subject-alternative-name {altName:(string*)}
```;

// vip output user function
getVipOutputs(outputs) =
foreach command in outputs.commands
where command.commandType == CommandType.F5_LTM_CONFIG
let vipOutput = parseConfigBlocks(OS.IOS, command.response)
let vipPartitions = blockMatches(vipOutput, vipProfile)

// Grab vip data from ltm config
foreach vip in vipPartitions
let vserverName = vip.data.vserverName
let vserverAddress = vip.data.vserverAddress
let profileName = vip.data.profileName
select { vserverName, vserverAddress, profileName };

getCertProfiles(outputs) =
// cert profile output - custom command output
foreach command in outputs.commands
where command.commandType == CommandType.CUSTOM
where command.commandText in customCmdProfile
let profileOutput = parseConfigBlocks(OS.IOS, command.response)
let profilePartitions = blockMatches(profileOutput, certProfile)
// Match vip profile name in profile parition
foreach profile in profilePartitions
let profileName = profile.data.profileName
let certificateName = profile.data.certName
let cipherGroup = profile.data.ciphergroup
let cipher = profile.data.ciphers
let options = profile.data.options
select { profileName, certificateName, cipherGroup, cipher, options };

getCertInfos(outputs) =
// cert info output - custom command output
foreach command in outputs.commands
where command.commandType == CommandType.CUSTOM
where command.commandText in customCmdCert
let certOutput = parseConfigBlocks(OS.IOS, command.response)
let certPartitions = blockMatches(certOutput, certInfo)
// Match certifciate name to certificate partition
foreach cert in certPartitions
// let certificateName = cert.data.certName
let certificateName = replace(cert.data.certName, "\\", "")
let certKeySize = cert.data.keySize
let expireDate = cert.data.expDate
let issuer = cert.data.issuer
let partition = cert.data.partition
let serial = cert.data.serial
let alternativeName = cert.data.altName
select {
certificateName,
certKeySize,
expireDate,
issuer,
partition,
serial,
alternativeName
};

getProfileMatch(profileOutputs, profileName) =
max(foreach profile in profileOutputs
where profileName == profile.profileName
let certificateName = profile.certificateName
let cipherGroup = profile.cipherGroup
let cipher = profile.cipher
let options = profile.options
select { certificateName, cipherGroup, cipher, options });

getCertMatch(certOutputs, certificateName) =
max(foreach cert in certOutputs
where certificateName == cert.certificateName
let certKeySize = cert.certKeySize
let expireDate = cert.expireDate
let issuer = cert.issuer
let partition = cert.partition
let serial = cert.serial
let alternativeName = cert.alternativeName
select {
certKeySize, expireDate, issuer, partition, serial, alternativeName
});

// Start here for each device
export f5Certs(device:Device)=
foreach x in n1]
// foreach device in network.devices
where device.platform.vendor == Vendor.F5
let outputs = device.outputs
//
// get output from show commands
let vipOutputs = getVipOutputs(outputs)
let profileOutputs = getCertProfiles(outputs)
let certOutputs = getCertInfos(outputs)
//
// loop through vips to add in the additional info from the other show commands
foreach vip in vipOutputs
// where suffix(vip.vserverAddress, 4) != "http"
let matchedProfile = getProfileMatch(profileOutputs, vip.profileName)
let matchCert = getCertMatch(certOutputs, matchedProfile?.certificateName)
select {
device: device.name,
deviceVendor: device.platform.vendor,
vserver: vip.vserverName,
vserver_address: vip.vserverAddress,
profile_name: vip.profileName,
profile_cipher_group: matchedProfile?.cipherGroup,
profile_cipher: matchedProfile?.cipher,
profile_options: if isPresent(matchedProfile?.options)
then join(" ", matchedProfile.options)
else "null",
certificate_name: matchedProfile?.certificateName,
certificate_keySize: matchCert?.certKeySize,
certificate_status: null:String,
certificate_issueDate: null:String,
certificate_expireDate: if isPresent(matchCert?.expireDate)
then join(" ", matchCert?.expireDate)
else "null",
certificate_issuer: if isPresent(matchCert?.issuer)
then join(" ", matchCert?.issuer)
else "null",
certificate_serial: matchCert?.serial,
certificate_alternativeName: if isPresent(matchCert?.alternativeName)
then join(" ", matchCert?.alternativeName)
else "null",
device_partition: matchCert?.partition
};

 


@jack.shen : This does work, Thank you so very much. We tried the exact same query before but made a very minute mistake. 

Appreciate the help

 


Reply