- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
This is the second part in this series - the first part is available here Importance of Credential Management
A popular credential repository is Thycotic Secret Server. Lets look at an example of setup the integration between the MID Server and Secret Server. How to install the Thycotic Secret Server is beyond the scope for this blog — but for Windows you basically get a "setup.exe" file, which starts a wizard to install the software.
During the installation you will create an "administrator" user. You need to create an additional user if you want to use the API. The reason for this is that when you setup the API, the password will automatically be changed to something secret.
You need to request the API JAR file separately from Thycotic support and they will send it to you via email. Extract the zip file to reveal the JAR file (secretserver-jconsole.jar).
To setup the API you will need to place the JAR file in the directory where it will execute from — in our case the MID server "agent" folder. Copy the file to the "agent" folder and follow the Java API setup instructions here: https://thycotic.force.com/support/s/article/Java-Client-Console-API-for-Accessing-Secret-Values-Pro...
Now when the Java API is setup we can look closer at the CredentialResolver.java file we need. Below is an example — but you can of course download the template from ServiceNow documentation and add your own code.
First lets create a directory for compiling the Java code e.g. F:\ServiceNow\JavaSource
Next create a directory structure like this: F:\ServiceNow\JavaSource\com\snc\discovery - this is where we're going to place the compiled Java code
Copy the "secretserver-jconsole.jar" file to the "JavaSource" folder.
Create a new file in the "JavaSource" folder called CredentialResolver.java - here is an example file which is based on the template from the documentation. The additional code is highlighted in blue.
package com.snc.discovery;
import java.util.*;
import java.io.*;
import thycotic.secretserver.jconsole.service.* ;
import thycotic.secretserver.business.utilities.BusinessInitializer;
/**
* Basic implementation of a CredentialResolver that uses secret server.
*/
public class CredentialResolver {
// These are the permissible names of arguments passed INTO the resolve()
// method.
// the string identifier as configured on the ServiceNow instance...
public static final String ARG_ID = "id";
// a dotted-form string IPv4 address (like "10.22.231.12") of the target
// system...
public static final String ARG_IP = "ip";
// the string type (ssh, snmp, etc.) of credential as configured on the
// instance...
public static final String ARG_TYPE = "type";
// the string MID server making the request, as configured on the
// instance...
public static final String ARG_MID = "mid";
// These are the permissible names of values returned FROM the resolve()
// method.
// the string user name for the credential, if needed...
public static final String VAL_USER = "user";
// the string password for the credential, if needed...
public static final String VAL_PSWD = "pswd";
// the string pass phrase for the credential if needed:
public static final String VAL_PASSPHRASE = "passphrase";
// the string private key for the credential, if needed...
public static final String VAL_PKEY = "pkey";
// the string authentication protocol for the credential, if needed...
public static final String VAL_AUTHPROTO = "authprotocol";
// the string authentication key for the credential, if needed...
public static final String VAL_AUTHKEY = "authkey";
// the string privacy protocol for the credential, if needed...
public static final String VAL_PRIVPROTO = "privprotocol";
// the string privacy key for the credential, if needed...
public static final String VAL_PRIVKEY = "privkey";
private Properties fProps;
public CredentialResolver() {
}
private void loadProps(String id, String type) {
if(fProps == null)
fProps = new Properties();
int secretID = Integer.parseInt(id);
BusinessInitializer.initialize();
System.err.println("user.dir := " + System.getProperty("user.dir"));
IUtilities util = new Utilities();
try {
String user = util.getSecretField(secretID, "username");
String password = util.getSecretField(secretID, "password");
//String token = util.getUserToken();
System.err.println("User: '" + user + "'" );
System.err.println(" pw: '" + password + "'");
String kPre = "" + secretID + "." + type + ".";
fProps.setProperty(kPre + VAL_USER,user);
fProps.setProperty(kPre + VAL_PSWD,password);
System.err.println(" PROPERTIES: '" + fProps + "'");
//System.out.println(" token: '" + token + "'");
} catch (java.lang.Exception e) {
System.err.println("EXCEPTION");
System.err.println(e.getMessage());
System.err.println("STACK");
e.printStackTrace();
}
System.out.println("OK - we are done!");
}
/**
* Resolve a credential.
*/
public Map resolve(Map args) {
String id = (String) args.get(ARG_ID);
String type = (String) args.get(ARG_TYPE);
String keyPrefix = id+"."+type+".";
if(id.equalsIgnoreCase("misbehave"))
throw new RuntimeException("I've been a baaaaaaaaad CredentialResolver!");
//get credential info from external source
loadProps(id,type);
// the resolved credential is returned in a HashMap...
Map result = new HashMap();
result.put(VAL_USER, fProps.get(keyPrefix + VAL_USER));
result.put(VAL_PSWD, fProps.get(keyPrefix + VAL_PSWD));
result.put(VAL_PKEY, fProps.get(keyPrefix + VAL_PKEY));
result.put(VAL_PASSPHRASE, fProps.get(keyPrefix + VAL_PASSPHRASE));
result.put(VAL_AUTHPROTO, fProps.get(keyPrefix + VAL_AUTHPROTO));
result.put(VAL_AUTHKEY, fProps.get(keyPrefix + VAL_AUTHKEY));
result.put(VAL_PRIVPROTO, fProps.get(keyPrefix + VAL_PRIVPROTO));
result.put(VAL_PRIVKEY, fProps.get(keyPrefix + VAL_PRIVKEY));
System.err.println("Resolving credential id/type["+id+"/"+type+"] -> "+result.get(VAL_USER)+"/"+result.get(VAL_PSWD)+"/"+result.get(VAL_PASSPHRASE)+"/"+result.get(VAL_PKEY)+"/"+result.get(VAL_AUTHPROTO)+"/"+result.get(VAL_AUTHKEY)+"/"+result.get(VAL_PRIVPROTO)+"/"+result.get(VAL_PRIVKEY));
return result;
}
/**
* Return the API version supported by this class.
*/
public String getVersion() {
return "1.0";
}
public static void main(String[] args) {
CredentialResolver obj = new CredentialResolver();
//obj.loadProps();
System.err.println("I spy the following credentials: ");
for(Object key: obj.fProps.keySet()) {
System.err.println(key+": "+obj.fProps.get(key));
}
}
}
Once we've saved this we're ready to compile the code. Note that your Java executable might reside in a different location. Use a CommandPrompt and navigate to to the "JavaSource" folder and use "javac" to compile the Java source file:
F:\ServiceNow\JavaSource>"c:\Program Files\Java\jdk1.8.0_92\bin\javac.exe" -classpath secretserver-jconsole.jar CredentialResolver.java -d .
You may see the following "warnings" which can be ignored:
Note: com\snc\discovery\CredentialResolver.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Now when we have our Java class file we need to wrap it into a JAR file using this command:
F:\ServiceNow\JavaSource>"c:\Program Files\Java\jdk1.8.0_92\bin\jar.exe" -cvf CredentialResolver.jar com
We are done with the command line and the next step is to upload the file to the ServiceNow instance. From the MID Server — open a browser and navigate to your instance, logon as an administrator and navigate to "MID Server" —> "JAR Files"
Create a record for the "secretserver-jconsole.jar" - and attach the JAR file to the record.
On the ServiceNow instance - go to "MID Server" —> "JAR Files" Create a record for the "CredentialResolver.jar" - and attach the JAR file to the record.
The JAR files will synchronize with the MID Servers — but you may want to restart the MID Server to make sure the new files are picked up. You will be able to see the new "jar" files in the "extlib" folder on the MID Server.
Next we need to set up the external credentials in ServiceNow. Unless you've already done so, you need to request the External Credential Store plugin to be enabled from HI (Activate external credential storage). Create a new credential in the credential table and make sure you tick the "External Credential" option. The "Credential ID" is the ID used to request the credential from Thycotic Secret Server — in the example below it's simply just the number "1". The "Tag" is not required but can be useful if you use "credential tagging" in your Orchestration activities.
Finally we should test our integration to make sure we can connect and pick up the required credentials. You may want to disable other credentials for the initial tests.
You can track the output from the Java code in the "wrapper.log" file on the MID Server. Using a tool like "Notepad++" you can refresh the file without having to reopen it each time. Once it's all working make sure you comment out or remove the output of username and password from the code.
I hope this article has given you a good understanding on how to implement an external credential store with ServiceNow. The CredentialResolver allows you to connect to various repositories whether it's a file, command line executable, a database or API integration.
Co-author angelonappi
- 15,032 Views
- « Previous
-
- 1
- 2
- 3
- Next »
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.