Querying Postured Macs
The pxGrid client queries the posture topic for the list of mac addresses containing posture data. To view the available posture attributes, please visit: Posture Topic
Code Step-Through
The references that are applicable to pxGrid 2.0 are highlighted
The public class PostureQueryAll calls timestamp
The private static void downloadUsingAccessSecret calls the SampleConfigurationObject. Ths SampleConfig object is parsed for pxGrid hostnames, pxGrid client certificates, identity keystore filename and password, truststore filename and password, and password if pre-shared keys are used for the initial connection.
We get the pxGrid client configuration account which contains the approved pxGrid client account and registered and connected to the ISE pxGrid node via access secret.
For // pxGrid ServiceLookup for posture service, we lookup the posture service, com.cisco.ise.posture, since we are interested in obtaining the posture information. The posture service can be found:Github. This returns a list of the ISE nodes that are publishing the restBaseURL that will be used for WebSockets REST API calls.
For // Use first service. Note that ServiceLookup randomize ordering of services. The pubsub service provides a list of ISE pxGrid nodes, if you have Active/Active.
For example if you have (3) ISE pxGrid nodes, the value is randomized so you will only connect to one pxGrid node. However the service will be shared across all three ISE pxGrid nodes, this distributes the load.
For //Account Activate, we wait 60 seconds for the account to be enabled. The ISE admin need to approve the pxGrid client account. We retrieve the pxGrid controller version.
For //pxGrid AccessSecret for the node we retrieve the accesssecret from the ISE pxGrid node and make a PostureQueryRequest and include the startTimestamp
Main parses the SampleConfiguration config file. The sample config object contains the pxGrid client connection parameters such as the pxGrid hostname, identity filename (.jks file) and trusted keystore filesname (.jks file) or pre-share keys if implemented.
For //Account Activate, we wait 60 seconds for the account to be enabled. The ISE admin need to approve the pxGrid client account. We retrieve the pxGrid controller version.
For //pxGrid get AccessSecret, we receive all authenticated sessions.
Complete Java SampleCode
package com.cisco.pxgrid.samples.ise;
import com.cisco.pxgrid.samples.ise.model.AccountState;
import com.cisco.pxgrid.samples.ise.model.Service;
import org.apache.commons.cli.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.OffsetDateTime;
/**
* Demonstrates how to retrieve all Postured endpoint macAddresses
*/
public class GetPosturedMacs {
public static final String SERVICE_NAME = "com.cisco.ise.posture";
private static Logger logger = LoggerFactory.getLogger(GetPosturedMacs.class);
private static void downloadUsingAccessSecret(SampleConfiguration config) throws Exception {
PxgridControl https = new PxgridControl(config);
// pxGrid ServiceLookup for posture service
Service[] services = https.serviceLookup(SERVICE_NAME);
if (services == null || services.length == 0) {
logger.warn("Service unavailable");
return;
}
// Use first service
Service service = services[0];
String url = service.getProperties().get("restBaseUrl") + "/getPosturedMacs";
logger.info("url={}", url);
// pxGrid AccesssSecret for the node
String secret = https.getAccessSecret(service.getNodeName());
String payload = "{}";
SampleHelper.postAndPrint(url, config.getNodeName(), secret, config.getSSLContext().getSocketFactory(), payload);
}
public static void main(String [] args) throws Exception {
// Parse arguments
SampleConfiguration config = new SampleConfiguration();
try {
config.parse(args);
} catch (ParseException e) {
config.printHelp("getPosturedMacs");
System.exit(1);
}
// AccountActivate
PxgridControl control = new PxgridControl(config);
while (control.accountActivate() != AccountState.ENABLED)
Thread.sleep(60000);
logger.info("pxGrid controller version={}", control.getControllerVersion());
downloadUsingAccessSecret(config);
}
}
Sample Output
/Library/Java/JavaVirtualMachines/jdk-11.0.14.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=51220:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/userhome/IdeaProjects/Sep2022/pxgrid-rest-ws/java/target/classes:/Users/userhome/.m2/repository/javax/xml/bind/jaxb-api/2.2.11/jaxb-api-2.2.11.jar:/Users/userhome/.m2/repository/javax/websocket/javax.websocket-api/1.1/javax.websocket-api-1.1.jar:/Users/userhome/.m2/repository/org/glassfish/tyrus/tyrus-client/1.17/tyrus-client-1.17.jar:/Users/userhome/.m2/repository/org/glassfish/tyrus/tyrus-core/1.17/tyrus-core-1.17.jar:/Users/userhome/.m2/repository/org/glassfish/tyrus/tyrus-spi/1.17/tyrus-spi-1.17.jar:/Users/userhome/.m2/repository/jakarta/xml/bind/jakarta.xml.bind-api/2.3.2/jakarta.xml.bind-api-2.3.2.jar:/Users/userhome/.m2/repository/jakarta/activation/jakarta.activation-api/1.2.1/jakarta.activation-api-1.2.1.jar:/Users/userhome/.m2/repository/org/glassfish/tyrus/tyrus-container-grizzly-client/1.17/tyrus-container-grizzly-client-1.17.jar:/Users/userhome/.m2/repository/org/glassfish/grizzly/grizzly-framework/2.3.22/grizzly-framework-2.3.22.jar:/Users/userhome/.m2/repository/org/glassfish/grizzly/grizzly-http-server/2.3.22/grizzly-http-server-2.3.22.jar:/Users/userhome/.m2/repository/org/glassfish/grizzly/grizzly-http/2.3.22/grizzly-http-2.3.22.jar:/Users/userhome/.m2/repository/com/google/code/gson/gson/2.1/gson-2.1.jar:/Users/userhome/.m2/repository/commons-io/commons-io/2.7/commons-io-2.7.jar:/Users/userhome/.m2/repository/commons-cli/commons-cli/1.4/commons-cli-1.4.jar:/Users/userhome/.m2/repository/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar:/Users/userhome/.m2/repository/ch/qos/logback/logback-core/1.2.0/logback-core-1.2.0.jar:/Users/userhome/.m2/repository/ch/qos/logback/logback-classic/1.2.0/logback-classic-1.2.0.jar:/Users/userhome/.m2/repository/org/apache/commons/commons-lang3/3.8.1/commons-lang3-3.8.1.jar com.cisco.pxgrid.samples.ise.GetPosturedMacs -a 10.76.231.99 -u pxtest002 -k /Users/userhome/ise99/self1.jks -p cisco123 -t /Users/userhome/ise99/root1.jks -q cisco123
------ config ------
hostname = 10.76.231.99
nodename = pxtest002
password = (not specified)
description = (not specified)
keystorefilename = /Users/userhome/ise99/self1.jks
keystorepassword = cisco123
truststorefilename = /Users/userhome/ise99/root1.jks
truststorepassword = cisco123
--------------------
11:27:43.230 [main] INFO com.cisco.pxgrid.samples.ise.PxgridControl - AccountActivate request={}
11:27:43.649 [main] INFO com.cisco.pxgrid.samples.ise.PxgridControl - AccountActivate response={"accountState":"ENABLED","version":"2.0"}
11:27:43.650 [main] INFO com.cisco.pxgrid.samples.ise.GetPosturedMacs - pxGrid controller version=2.0
11:27:43.658 [main] INFO com.cisco.pxgrid.samples.ise.PxgridControl - ServiceLookup request={"name":"com.cisco.ise.posture"}
11:27:43.744 [main] INFO com.cisco.pxgrid.samples.ise.PxgridControl - ServiceLookup response={"services":[{"name":"com.cisco.ise.posture","nodeName":"~ise-admin-iselab99","properties":{"postureVisibilityTopic":"/topic/com.cisco.ise.posture.visibility","wsPubsubService":"com.cisco.ise.pubsub","restBaseUrl":"https://iselab99.cisco.com:8910/pxgrid/ise/posture"}}]}
11:27:43.744 [main] INFO com.cisco.pxgrid.samples.ise.GetPosturedMacs - url=https://iselab99.cisco.com:8910/pxgrid/ise/posture/getPosturedMacs
11:27:43.748 [main] INFO com.cisco.pxgrid.samples.ise.PxgridControl - AccessSecret request={"peerNodeName":"~ise-admin-iselab99"}
11:27:43.791 [main] INFO com.cisco.pxgrid.samples.ise.PxgridControl - AccessSecret response={"secret":"Rz7zhMNvC1zJYNnC"}
11:27:43.806 [main] INFO com.cisco.pxgrid.samples.ise.SampleHelper - postData="{}"
11:27:44.259 [main] INFO com.cisco.pxgrid.samples.ise.SampleHelper - Response status=200
Content: ["00:50:56:83:2B:D3","84:EB:EF:BC:7D:DE","D4:EB:68:5B:FD:89","D4:EB:68:5B:FD:88"]
Process finished with exit code 0