Skip to main content
Solved

NQE Query to get SSL profiles from Custom Commands on F5


Forum|alt.badge.img

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. 

 

Best answer by jack.shen

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 }

 

View original
Did this topic help you find an answer to your question?

5 replies

  • Employee
  • 8 replies
  • April 9, 2024

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 


Forum|alt.badge.img
  • Author
  • Ramping Up
  • 2 replies
  • April 9, 2024

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 ) 


  • Employee
  • 8 replies
  • Answer
  • April 9, 2024

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 }

 


Tyson Henrie
Employee
Forum|alt.badge.img+1

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 [1]
// 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
};

 


Forum|alt.badge.img
  • Author
  • Ramping Up
  • 2 replies
  • April 10, 2024

@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

 


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings