Need Help with Using the Discovery Tool for SSL Certificate Inventory and CI Upkeep.

humblecommitted
Kilo Guru

A call to arms fellow ServiceNow patrons,

right now i am currently using digicert scanner to extract what ports and servers that have ssl certs and exporting it to an excel spread sheet.

I am currently researching methods of determining how to run internal cmds on the servers via the discovery tool.

most cmds i have come across checks the servers externally.

i am trying to do the following:

  • find internal cmds such as:
    • port scan with finger print of services running on port
    • common file types, paths, etc. associated with ssl cert installation on the servers i.e. locate/find/which *.crt, *.key, *.cer, *.pem, etc.
    • expiration dates
    • (and any others that i have not thought of please feel free to include)
  • both powershell and bash scripts/cmd equivalents of the each other to run on both windows and linux environments.
  • then trying to configure a sensor script to interpret the output of those commands.
  • populate output to respective ci's (especially expiration dates to have a notification rule setup for that)

i would hate to reinvent the wheel, if anyone has already stumbled upon this please let me know.

any help you provide will help the greater community and i will do my best to reciprocate and share the information openly.

1 ACCEPTED SOLUTION

Hello Community,



I was able to build this out.



This solution is dependent on how you want to capture the SSL Cert information for your server.



  1. You can either run a command internally on the server to see the certs installed and capture that information, or
  2. You can run an external command that will capture the SSL cert information via externally connecting to the ssl port to request the header/thumbprint/output of the ssl cert. (This method will prove tricky because you would have to manually change the script on the probe to execute on every server, unless there is a script that can loop through all the known IPs/URLs to extract the Certs and associate them to the targeted CI)


For now I will use use case # 1 as an example:


  1. to check for certs installed locally/internally on the server we would have to know where the certs install files are located, we can do this by creating a probe to capture all locations of where .crt files are located (if needed, we can create a sensor to parse through the output to capture all the installed locations of the .crt file to populate the CI but I did not complete this step but when you read through this write up, you can tweak the script i have to collect cert expiration date to meet this need):

    locate *.crt


    find_real_file.png
  2. Once you get the output locations of where local certs are installed on the server, run this command while swapping out the files location with your own:

    openssl x509 -text -noout -in /etc/pki/tls/certs/localhost.crt


    find_real_file.png

    You can use these commands that are referenced/explained in the following URLs
    Windows based servers:
    How can I get a list of installed certificates on Windows? - Super User
    Linux based servers:
    The Most Common OpenSSL Commands

  3. After I created my probe, I then created the corresponding sensor to parse the output and relate them to the CI.
    find_real_file.png
  4. I then created this java script for the sensor to parse through the output and grab the "End date" of the ssl cmd.
    find_real_file.png
    find_real_file.png
    find_real_file.png
    find_real_file.png


/*


new DiscoverySensor({


process: function(result) {


var ssloutput = result."Not After : ";


var ssldate = new setDisplayValue();


ssldate.addSeconds(-ssloutput);


current.u_ssl_exp = ssldate;


},


type: "DiscoverySensor"


});


*/




new DiscoverySensor({


      process: function(result) {


              if (gs.nil(result.output))


                      return;




              this.parseOutput(result.output);


      },




      parseOutput: function(output) {


  var updated = false;


              var lines = output.split(/\n/);


  gs.log("This is the output for lines: "+lines);


  gs.log("Not After Index check >>>> "+output.indexOf("Not After"));


              var na = output.indexOf("Not After");


  gs.log(output.substring(na + 12, na + 32)); //to grab full date output


  gs.log(output.substring(na + 28, na + 32)); //to grab year


  gs.log(output.substring(na + 12, na + 15)); //to grab month


  gs.log(output.substring(na + 16, na + 18)); //to grab day


  gs.log(output.substring(na + 19, na + 27)); //to grab time


  var yyyy = output.substring(na + 28, na + 32);


  var mmm = output.substring(na + 12, na + 15);


  var dd = output.substring(na + 16, na + 18);


  var time = output.substring(na + 19, na + 27);


//convert cert output date to match servicenow date format.


  var mn;


  if (mmm == "Jan"){


  mn = "01";


  } else if(mmm == "Feb"){


  mn = "02";


  }else if(mmm == "Mar"){


  mn = "03";


  }else if(mmm == "Apr"){


  mn = "04";


  }else if(mmm == "May"){


  mn = "05";


  }else if(mmm == "Jun"){


  mn = "06";


  }else if(mmm == "Jul"){


  mn = "07";


  }else if(mmm == "Aug"){


  mn = "08";


  }else if(mmm == "Sep"){


  mn = "09";


  }else if(mmm == "Oct"){


  mn = "10";


  }else if(mmm == "Nov"){


  mn = "11";


  }else if(mmm == "Dec"){


  mn = "12";


  }


   




  gs.log("This is the output for mn: "+mn);


  //gs.log(yyyy+"-"+mn+"-"+dd+" "+time);


  var sslexpdate = yyyy+"-"+mn+"-"+dd+" "+time;


  gs.log(sslexpdate);


  updated = true;


  if (updated) //Only update it if the output has good value


  current.u_ssl_exp = sslexpdate;



  //gs.log("The month number is "+mn);



  //for (var i = 0; i < lines.length; i++) {


                      //var line = lines[i];


  //gs.log("This is the output for line: "+line);



                     


                      //var parts = line.split(":");


                      //var name = parts[0].trim();


                      //var value = parts[1].trim();


      //gs.log("Not After Index check >>>> "+output.indexOf("Not After"));


  //if (name == "Not After")


  //current.u_ssl_exp = value;


  //gs.log("The name is "+name+" and value is "+ value);


  //gs.log("Not After Index check >>>> "+output.indexOf("Not After"));



  //gs.log("The name is "+name+" and length is "+ name.length);


  //}


          },


             


      type: "DiscoverySensor"


});




5. Take notice that I also had to convert the output of the SSL cert date to match servicenow's date format i.e. variables "mmm", "mn" (for month number), and rearranging the date.


6. Attach the sensor to the probe.


find_real_file.png


find_real_file.png



7. Test the probe to see if there are any errors to re-mediate.


find_real_file.png


i.e. of error


find_real_file.png


find_real_file.png


find_real_file.png


i.e. of working probe:


find_real_file.png


find_real_file.png


8.   For trouble shooting of the script you can make your way to   Script Log Statements to see how your sensor code is parsing through the output.


find_real_file.png



9. I then created the corresponding variable on the CI called "u_ssl_exp" that is referenced on line 75 of my sensor code.


find_real_file.png


9. create a discovery schedule.


find_real_file.png


find_real_file.png


10. Scan will run, check with Discovery status, event logs, all (logs), script log statements, etc. to see status


find_real_file.pngfind_real_file.pngfind_real_file.png


find_real_file.png


11. Verify the CI field has been updated with the SSL expiration date:


find_real_file.png


12. Now that we have a servicenow format for a tangible date for the ssl cert, we can now have servicenow automate notifications based on cert expiration etc.



Note:   The commented out portions of my code also has portions that increment, or loop, through the ssl cert output to grab any other information if needed (it is separated by ":").   Please feel free to update the code and post here to share with the rest of the community any updated codes, practices, or methods, etc.



I hope this helps you all as much as it has helped me.



Thank you.


View solution in original post

6 REPLIES 6

humblecommitted
Kilo Guru

Hello community,



update:



Here is the probe I created:


find_real_file.png



I have the following command I am running:


openssl x509 -text -noout -in /etc/pki/tls/certs/localhost.crt


Note:


the path to the cert that were collecting data on is subject to change depending on where the internal cert has been installed.



This is the output for the command:


Certificate:


      Data:


              Version: 3 (0x2)


              Serial Number: 19900 (0x4dbc)


      Signature Algorithm: sha256WithRSAEncryption


              Issuer: C=--, ST=SomeState, L=SomeCity, O=SomeOrganization, OU=SomeOrganizationalUnit, CN=qradar/emailAddress=root@qradar


              Validity


                      Not Before: Dec   6 09:31:46 2016 GMT


                      Not After : Dec   6 09:31:46 2017 GMT


              Subject: C=--, ST=SomeState, L=SomeCity, O=SomeOrganization, OU=SomeOrganizationalUnit, CN=qradar/emailAddress=root@qradar


              Subject Public Key Info:


                      Public Key Algorithm: rsaEncryption


                              Public-Key: (2048 bit)


                              Modulus:


                                      00:d2:6c:b6:7e:95:bf:69:4b:0a:5f:30:21:a2:f7:


                                      67:90:c2:1e:89:2e:98:d5:02:37:cc:76:08:00:1f:


                                      4a:97:c6:42:b5:bd:80:4b:db:ed:87:51:34:67:60:


                                      93:1e:e7:57:39:f6:48:22:00:5f:50:ca:e6:47:32:


                                      ba:84:da:f6:fa:13:d3:55:30:50:10:00:cc:83:cd:


                                      22:12:00:bd:20:99:59:6d:2f:22:8f:ae:67:7f:9d:


                                      c6:a3:d8:16:c2:35:ac:7c:e8:fb:51:9e:41:ff:1c:


                                      71:7c:e4:5d:15:4d:7c:01:1c:29:52:db:4e:ec:fa:


                                      d2:1f:6f:b7:80:70:70:ba:ec:82:55:56:26:e7:98:


                                      1f:32:b0:62:66:ba:55:45:7f:a9:f2:34:03:1d:85:


                                      21:e9:d8:99:7e:98:6e:38:0c:89:cf:c4:80:99:4d:


                                      12:30:63:0c:e3:a4:48:da:8a:ad:7c:b9:6f:f1:d6:


                                      81:9e:1b:72:81:7b:4a:37:a8:49:ff:75:6b:e8:34:


                                      5b:d1:e8:15:bf:97:dd:72:92:47:f4:ae:35:47:34:


                                      99:6f:60:dd:3d:94:5e:6b:ee:ed:5e:a5:db:50:e3:


                                      83:90:a8:94:7b:df:15:67:52:58:35:3c:53:4d:35:


                                      c0:e4:ad:38:7e:86:9c:c3:82:da:f4:a4:7e:3c:b6:


                                      9f:c5


                              Exponent: 65537 (0x10001)


              X509v3 extensions:


                      X509v3 Basic Constraints:


                              CA:FALSE


                      X509v3 Key Usage:


                              Digital Signature, Non Repudiation, Key Encipherment


      Signature Algorithm: sha256WithRSAEncryption


                4a:cb:6d:af:da:9c:a2:7d:7a:77:19:3c:ce:65:6d:f6:1d:18:


                91:83:bd:d2:04:78:de:d2:84:00:1a:fb:0d:dc:d4:b3:52:77:


                83:0b:34:c6:a2:cf:3d:14:a3:c0:c6:5c:fd:e5:fa:6c:2a:db:


                0b:1c:ad:f0:03:4e:3f:3a:b6:1b:c4:bd:e6:d5:4e:69:88:68:


                3c:1f:94:91:8a:17:cc:24:ca:ae:d8:cb:9a:4e:66:e2:30:d3:


                ad:8a:ed:dc:28:c6:61:25:65:22:8d:86:be:aa:20:fc:24:6b:


                b9:cb:ea:40:40:5d:e8:10:c8:9d:bc:65:e8:3e:57:45:27:d4:


                3a:f4:aa:57:3b:60:8c:5b:af:2e:6f:d8:a7:45:2d:2d:0d:56:


                8a:7f:2b:4f:3a:53:1c:30:4a:58:a0:12:af:07:e6:68:5e:c3:


                cf:4a:9c:45:c6:f3:7b:ae:52:47:41:d1:9d:6e:26:d8:98:c2:


                2b:87:16:ae:a0:f4:5f:bb:e1:8e:a5:42:0c:55:49:c0:b7:a7:


                e3:63:2e:29:cf:28:91:68:80:b0:db:ee:07:13:b4:57:1f:c6:


                e5:50:6a:05:ba:27:f8:4f:ee:dc:1a:c3:31:58:6e:4d:6d:38:


                c2:02:93:49:4d:b0:ec:1f:88:44:33:35:8c:8b:19:cf:0b:68:


                97:6a:c7:da



Here is the sensor code that I am trying to parse through the output and populate the respected CI with the target data being the "Not After :" date (which will be built out to have ServiceNow automate notifications when the expiration dates are close to approaching).


find_real_file.png


find_real_file.png



Here is the javascript to collect this information:



new DiscoverySensor({


      process: function(result) {


              if (gs.nil(result.output))


                      return;




              this.parseOutput(result.output);


      },




      parseOutput: function(output) {


              var updated = false;


              var ssl = 0;


              var lines = output.split(/\n/);




              for (var i = 0; i < lines.length; i++) {


                      var columns = lines[i].split(/\s+/);


                      if (columns[0] == "Not After :") {


                              ssl = columns[1];


                              updated = true;


                      }


              }


              if (updated) //Only update it if the output has good value


                      current.u_ssl_exp = new RoundingInterval("ssl").getRoundedValue(ssl);


      },




      type: "DiscoverySensor"


});



Here is the CI field that I am trying to populate with this sensor:


find_real_file.png



I have yet to test this script due to some connectivity issues I am experiencing in another open forum located here


discovery tcp error


Until I am able to connect with the mid server via ssh to test this out, I will continue to keep the community up-to-date on this much needed solution.



If anyone has any input, code correction, and/or solutions please do not hesitate to help out your fellow patrons.


Hello Community,



I was able to build this out.



This solution is dependent on how you want to capture the SSL Cert information for your server.



  1. You can either run a command internally on the server to see the certs installed and capture that information, or
  2. You can run an external command that will capture the SSL cert information via externally connecting to the ssl port to request the header/thumbprint/output of the ssl cert. (This method will prove tricky because you would have to manually change the script on the probe to execute on every server, unless there is a script that can loop through all the known IPs/URLs to extract the Certs and associate them to the targeted CI)


For now I will use use case # 1 as an example:


  1. to check for certs installed locally/internally on the server we would have to know where the certs install files are located, we can do this by creating a probe to capture all locations of where .crt files are located (if needed, we can create a sensor to parse through the output to capture all the installed locations of the .crt file to populate the CI but I did not complete this step but when you read through this write up, you can tweak the script i have to collect cert expiration date to meet this need):

    locate *.crt


    find_real_file.png
  2. Once you get the output locations of where local certs are installed on the server, run this command while swapping out the files location with your own:

    openssl x509 -text -noout -in /etc/pki/tls/certs/localhost.crt


    find_real_file.png

    You can use these commands that are referenced/explained in the following URLs
    Windows based servers:
    How can I get a list of installed certificates on Windows? - Super User
    Linux based servers:
    The Most Common OpenSSL Commands

  3. After I created my probe, I then created the corresponding sensor to parse the output and relate them to the CI.
    find_real_file.png
  4. I then created this java script for the sensor to parse through the output and grab the "End date" of the ssl cmd.
    find_real_file.png
    find_real_file.png
    find_real_file.png
    find_real_file.png


/*


new DiscoverySensor({


process: function(result) {


var ssloutput = result."Not After : ";


var ssldate = new setDisplayValue();


ssldate.addSeconds(-ssloutput);


current.u_ssl_exp = ssldate;


},


type: "DiscoverySensor"


});


*/




new DiscoverySensor({


      process: function(result) {


              if (gs.nil(result.output))


                      return;




              this.parseOutput(result.output);


      },




      parseOutput: function(output) {


  var updated = false;


              var lines = output.split(/\n/);


  gs.log("This is the output for lines: "+lines);


  gs.log("Not After Index check >>>> "+output.indexOf("Not After"));


              var na = output.indexOf("Not After");


  gs.log(output.substring(na + 12, na + 32)); //to grab full date output


  gs.log(output.substring(na + 28, na + 32)); //to grab year


  gs.log(output.substring(na + 12, na + 15)); //to grab month


  gs.log(output.substring(na + 16, na + 18)); //to grab day


  gs.log(output.substring(na + 19, na + 27)); //to grab time


  var yyyy = output.substring(na + 28, na + 32);


  var mmm = output.substring(na + 12, na + 15);


  var dd = output.substring(na + 16, na + 18);


  var time = output.substring(na + 19, na + 27);


//convert cert output date to match servicenow date format.


  var mn;


  if (mmm == "Jan"){


  mn = "01";


  } else if(mmm == "Feb"){


  mn = "02";


  }else if(mmm == "Mar"){


  mn = "03";


  }else if(mmm == "Apr"){


  mn = "04";


  }else if(mmm == "May"){


  mn = "05";


  }else if(mmm == "Jun"){


  mn = "06";


  }else if(mmm == "Jul"){


  mn = "07";


  }else if(mmm == "Aug"){


  mn = "08";


  }else if(mmm == "Sep"){


  mn = "09";


  }else if(mmm == "Oct"){


  mn = "10";


  }else if(mmm == "Nov"){


  mn = "11";


  }else if(mmm == "Dec"){


  mn = "12";


  }


   




  gs.log("This is the output for mn: "+mn);


  //gs.log(yyyy+"-"+mn+"-"+dd+" "+time);


  var sslexpdate = yyyy+"-"+mn+"-"+dd+" "+time;


  gs.log(sslexpdate);


  updated = true;


  if (updated) //Only update it if the output has good value


  current.u_ssl_exp = sslexpdate;



  //gs.log("The month number is "+mn);



  //for (var i = 0; i < lines.length; i++) {


                      //var line = lines[i];


  //gs.log("This is the output for line: "+line);



                     


                      //var parts = line.split(":");


                      //var name = parts[0].trim();


                      //var value = parts[1].trim();


      //gs.log("Not After Index check >>>> "+output.indexOf("Not After"));


  //if (name == "Not After")


  //current.u_ssl_exp = value;


  //gs.log("The name is "+name+" and value is "+ value);


  //gs.log("Not After Index check >>>> "+output.indexOf("Not After"));



  //gs.log("The name is "+name+" and length is "+ name.length);


  //}


          },


             


      type: "DiscoverySensor"


});




5. Take notice that I also had to convert the output of the SSL cert date to match servicenow's date format i.e. variables "mmm", "mn" (for month number), and rearranging the date.


6. Attach the sensor to the probe.


find_real_file.png


find_real_file.png



7. Test the probe to see if there are any errors to re-mediate.


find_real_file.png


i.e. of error


find_real_file.png


find_real_file.png


find_real_file.png


i.e. of working probe:


find_real_file.png


find_real_file.png


8.   For trouble shooting of the script you can make your way to   Script Log Statements to see how your sensor code is parsing through the output.


find_real_file.png



9. I then created the corresponding variable on the CI called "u_ssl_exp" that is referenced on line 75 of my sensor code.


find_real_file.png


9. create a discovery schedule.


find_real_file.png


find_real_file.png


10. Scan will run, check with Discovery status, event logs, all (logs), script log statements, etc. to see status


find_real_file.pngfind_real_file.pngfind_real_file.png


find_real_file.png


11. Verify the CI field has been updated with the SSL expiration date:


find_real_file.png


12. Now that we have a servicenow format for a tangible date for the ssl cert, we can now have servicenow automate notifications based on cert expiration etc.



Note:   The commented out portions of my code also has portions that increment, or loop, through the ssl cert output to grab any other information if needed (it is separated by ":").   Please feel free to update the code and post here to share with the rest of the community any updated codes, practices, or methods, etc.



I hope this helps you all as much as it has helped me.



Thank you.


Hi Expert,

Greetings!!!

I was going through your post and found that the information provided by you is very useful.

I have similar kind of requirement to implement for my customer but with extra functionality i.e. discovering the SSL certifications on Load balancer's as well. If you have implemented solution for any of such requirements please help us with documentation for the same.

I was unable to see the configuration done for "Linux - SSL Expiration Dates with Custom Probe" in the screen shots which confused me.

 

Thanks in Advance. 

Thanks for sharing this useful information. Could you please also share how you implemented the same in windows.