Getting started with PE and the ServiceNow CMDB integration
The ServiceNow CMDB integration module integrates ServiceNow’s Configuration Management Database (CMDB) with Puppet. It lets you:
- Access a node's CMDB record as trusted external data via the
trusted.external.servicenow
hash. - Classify nodes in the CMDB by using it to store the node's Puppet environment and classes. Puppet will automatically fetch and apply this classification in the node's subsequent Puppet runs.
Before you begin
- Install Puppet Enterprise >= 2019.7.0
- Make sure you have access to a ServiceNow instance (dev or enterprise)
A note on where to begin
The trusted external data feature does not depend on the classification feature, so you can enable it on its own. To get started, go to Setting up ServiceNow’s CMDB as trusted external data (below).
However, if you’re also interested in classifying nodes in the CMDB, you must enable both features. Start by following the steps in Setting up node classification in ServiceNow’s CMDB and then follow the steps in Setting up ServiceNow’s CMDB as trusted external data. The classification feature requires the trusted external data feature, and there are additional notes in the trusted external data tasks for users who are classifying nodes.
Setting up node classification in ServiceNow’s CMDB
1. Add custom fields to the ServiceNow cmdb_ci table
Note: You may skip this step if you’re already storing your nodes’ Puppet environment and classes in your own CMDB fields, and the JSON representation of those fields as returned by ServiceNow’s table API (via something like
curl -k https://dev57373.service-now.com/api/now/table/cmdb_ci -u user:password
) matches the specified types:
- JSON string for the Puppet environment
- JSON string representing an encoded JSON object for the Puppet classes
Add the following custom fields to the cmdb_ci
table in your ServiceNow instance:
Field Name | Column Label | Column Name | Type |
---|---|---|---|
Puppet Environment | Puppet Environment | u_puppet_environment | String (Full UTF-8) |
Puppet Classes | Puppet Classes | u_puppet_classes | String (Full UTF-8) |
- Note: Here,
Puppet Classes
is a JSON encoding of aHash[String, Hash[String, Any]]
type (informally, aHash[ClassName, Parameters]
object).- For example,
"{\"foo_class\":{\"foo_param\":\"foo_value\"}}"
is a valid value forPuppet Classes
. However,{"foo_class":{"foo_param":"foo_value"}}
is not.
- For example,
Here’s one way you can add these fields via ServiceNow’s System Definition application.
- Log on to your ServiceNow instance’s console.
- Type
System Definition
into theFilter Navigator
, click onTables
, then typecmdb_ci
into the search bar. Your screen should look something like this:
3. Press Enter, then click on Configuration Item
(which should be the first thing that pops up). Your screen should now look something like this:
This is the cmdb_ci
table’s definition. The Table Columns
represent the table’s fields. We will be adding two new columns representing the Puppet Environment
and the Puppet Classes
fields, respectively.
4. Click on New
next to Table Columns
and enter the following:
String (Full UTF-8)
for the field’sType
Puppet Environment
for the field’sColumn label
u_puppet_environment
for the field’sColumn name
4,000
for the field’s max length- Check the
Active
box
Your UI should look something like this:
Click Submit
. After a few minutes, you should be back at the cmdb_ci
table’s definition. The definition should now contain the new Puppet Environment
field. See for yourself:
Now let’s add the second column. Once again, click on New
next to Table Columns
and enter the following:
String (Full UTF-8)
for the field’sType
Puppet Classes
for the field’sColumn label
u_puppet_classes
for the field’sColumn name
4,000
for the field’smax length
- Check the
Active
box
Note:
You can also make Puppet Classes
a Name-Value pairs
field type, where the Name
corresponds to the classes and Value
corresponds to the parameters.
-
If you choose to do this, then know that ServiceNow’s API will return
Puppet Classes
as a JSON encoding of aHash[String, String]
type.-
For example, given a
classes
hash that’s something like{"foo_class":{"foo_param":"foo_value"}}
that’s stored as aString (Full UTF-8)
field type, ServiceNow’s API will return this as:"{\"foo_class\":\"{\"foo_param\":\"foo_value\"}\"}"
(if stored as a
Name-Value pairs
field type) vs."{\"foo_class\":{\"foo_param\":\"foo_value\"}}"
This means that parsing the classes hash for a
Name-Value pairs
field type will look something like:classes = JSON.parse(raw_value) classes.each do |class, params| classes[class] = JSON.parse(params) end
Or something like
classes = JSON.parse(raw_value)
for theString (Full UTF-8)
field type.
-
Click on Submit
to add the Puppet Classes
field to the cmdb_ci
table’s definition.
Note: We recommend storing pretty-printed JSON for the Puppet Classes
field’s values so that it’s easier to see (and edit) in the UI.
2. Update and commit changes to your control-repo
Add a commit to your control-repo that contains the following changes:
Puppetfile
: The linemod 'puppetlabs/servicenow_cmdb_integration', :latest
hiera.yaml
: The following backend (usually at the top of the hierarchy)
- name: "ServiceNow Hiera data"
data_hash: servicenow_cmdb_integration::getvar
options:
var: trusted.external.servicenow.hiera_data
manifests/site.pp
: The lineinclude servicenow_cmdb_integration::classification
at the bottom of the file.
The commit should look something like the following image:
The servicenow_cmdb_integration::classification
class includes all the classes specified in the trusted.external.servicenow.puppet_classes
variable (and noops on nodes where that variable is undefined). Class parameters are read from the servicenow_cmdb_integration::getvar
Hiera backend.
3. Deploy the update to your PE environments
Once you’ve created the commit, deploy it to all of your environments. (Otherwise, classification will not work.)
For all environments, add a rule of the form ['=', ['trusted', 'external', 'servicenow', 'puppet_environment'], '<environment>']
to their corresponding environment group. You can use the PE console to do this or the servicenow_cmdb_integration::add_environment_rule
task.
This step is necessary for the integration to set the node's environment to
Puppet Environment
.
If you're using the PE console, the rule should look something like:
If you're using the task, then the task invocation should look something like:
puppet task run servicenow_cmdb_integration::add_environment_rule --params '{"group_names": <array of environment group names>}' --nodes <fqdn of node containing the classifier service>
4. Set up the trusted external data feature
Set up the trusted external data feature by following the instructions in its corresponding section.
You should now be able to store per-node classification in ServiceNow’s CMDB and make Puppet aware of that classification.
Setting up ServiceNow’s CMDB as trusted external data
-
Install the puppetlabs-servicenow_cmdb_integration module on your Puppet server.
-
Add the
servicenow_cmdb_integration
class to thePE Master
node group.- In the PE console, navigate to
Classification
then expand thePE Infrastructure
group - Click
PE Master
thenConfiguration
- Add the
servicenow_cmdb_integration
class - Enable these parameters:
instance
: for example<instance_name>.service-now.com
user
: plain-text ServiceNow userpassword
: plain-text or a hiera-eyaml encrypted password- If you’re using a hiera-eyaml encrypted password, then make sure that
eyaml decrypt -s <encrypted_password>
returns the same password on all nodes in thePE Master
node group. - You can also pass-in a plain-text or hiera-eyaml encrypted oauth token via the
oauth_token
parameter instead of a username/password. If you’re passing-in a hiera-eyaml encrypted oauth token, then make sure thateyaml decrypt -s <encrypted_oauth_token>
returns the same oauth token on all nodes in thePE Master
node group.
- If you’re using a hiera-eyaml encrypted password, then make sure that
v. Commit the changes, then run Puppet on the node group. This will cause a restart of the
pe-puppetserver
service. - In the PE console, navigate to
The servicenow_cmdb_integration
class installs the servicenow.rb
script and points Puppet’s trusted_external_command
setting to that script. This script fetches the node's CMDB record from the cmdb_ci
table and stores it in the trusted.external.servicenow
variable.
Using a different CMDB table
You can set the table
parameter to point to a different CMDB table (like e.g. cmdb_ci_server
). However, keep in mind that the script will only fetch data for nodes that are in the specified table or a child of that table (such as nodes in the cmdb_ci_server
table or a child table like cmdb_ci_server_hardware
). It will return an empty hash for all other nodes.
Storing node certnames in a separate CMDB field
Puppet invokes the servicenow.rb
script via the calling-convention servicenow.rb <certname>
. The script fetches the node's CMDB record by querying the record whose fqdn
field matches <certname>
. If you're storing node certnames in a separate CMDB field, then you can set the certname_field
parameter to that CMDB field's column name.
Note to readers who are enabling classification
If you're already storing the node's environment and classes in their own CMDB fields, then make sure to specify those fields' column names in the environment_field
and classes_field
parameters, respectively. Otherwise, these default to u_puppet_environment
and u_puppet_classes
, respectively.
3. Verify that everything worked
To verify that everything worked, click on one of the nodes in the Matching nodes
tab of the PE Master
group and scroll down to the node’s trusted facts. You should see something like:
- If you see an empty hash for
trusted.external
, then run Puppet again on the node to refresh the data. - If you see an empty hash for
trusted.external.servicenow
, then the CMDB table that you’re fetching the data from might not have an entry for the node, or you might need to set theservicenow_cmdb_integration
class’certname_field
parameter to a valid value.
Note to readers who are enabling classification
If classification’s been properly set up, then you should also see values for the trusted.external.servicenow
hash’s puppet_environment
and puppet_classes
keys, respectively.
Conclusion
You should now be able to reference the node’s CMDB record when writing your Puppet manifests. For example, the line getvar('trusted.external.servicenow.asset_tag')
(or $trusted['external']['servicenow']['asset_tag']
) returns the node’s asset tag.
Have feedback? Let us know what you think!
Try the servicenow_cmdb_integration module out and let us know what you think at team-pie@puppet.com!