- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
09-22-2023 09:32 AM - edited 07-10-2024 09:20 AM
DISCLAIMER: The code snippets and examples in this article come with no warranty or support, implicit or explicit. Caveat Emptor!
Introduction
With the introduction of the Scan Container Image pattern, ServiceNow added the ability to discover software packages running inside container workloads. This ability does not currently work with AWS ECS task definitions -- while the definitions themselves are discovered, the image metadata is not ingested. Here's an example of how to add that to your CMDB, so that ECS task definitions are tied to the container images they are using (and in turn, the software packages which reside there).
NOTE: the approach I took uses a post-sensor script to create the relationships between the task definition and image because I couldn't get it to work correctly within the pattern itself -- intuitively it seems like the pattern should be able to do it natively, but in the interest of having _something_ that works, I've taken this bifurcated approach.
Enhance Pattern
The first part of adding image information from ECS task definitions is to augment the Amazon AWS - ECS pattern as follows:
- After step "Add the TaskDefinition compatibilities" (step 5.8 on my current version of Discovery Patterns), add a Parse Variable step (e.g., "Parse the TaskDefinition images) which extracts the container image metadata from the existing $describe_taskdefinitions_response variable. Configure advanced parsing options per the figure below.
- After the new "Add the TaskDefinition images" step (5.9 in my example), create a Transform Table step (e.g., "Add the TaskDefinition images", which will place a comma-separated list of images in the "Comments" attribute for the task definition records. Configure it per the figure below.
- Here's the inline JavaScript code for the field value:
var rtrn = '' var td_arn = ${task_definitions[].td_arn} var td_image_arn = ${td_images[*].td_arn}.toArray() var td_image = ${td_images[*].td_image}.toArray() var separator = '' var length = td_image_arn.length for(i=0; i < length; i++){ if (td_arn==td_image_arn[i]) { rtrn += separator + td_image[i] separator = ',' } } rtrn
- After the existing step "Populate cmdb_ci_cloud_ecs_task_definition table" (5.11 in my example), add a Transform Table step (e.g., "Populate cmdb_ci_docker_image"). Configure per the figure below.
- In the CI Attributes pane in the upper right, click the three sliders icon to add a new CI type. In the resulting dialog box, add the "Docker Image" CI type to the pattern.
The pattern is now adjusted to parse out images from ECS task definitions and store them as records in cmdb_ci_docker_image as well as the Comments attribute in cmdb_ci_cloud_ecs_task_definition.
Post Sensor Script
The next piece required for this example is a post sensor script to execute after the Amazon AWS - ECS pattern. Under Pattern Designer->Pre Post Processing, create a new record as seen in the figure below.
The following is the JavaScript code for the record:
/*
* Post sensor: You can update/add missing info to the DB based on result (Json) from
* Identification Engine
* Output parameters in Post sensor mode: payload
*/
var rtrn = {};
// parsing the json string to a json object
var payloadObj = JSON.parse(payload);
gs.info("ECS TASK DEF: payload is " + payload);
// Clearing payload string to save memory
payload = null;
// Put your business logic here
// For node logger, please use: prePostNodeLogger.info\warn\error\debug(prePostLogPrefix + '<YOUR_LOG_STATEMENT>')
// iterate through the payload, parse ECS task definition comments to create image relationships
var tdGr = new GlideRecord('cmdb_ci_cloud_ecs_task_definition');
var relGr = new GlideRecord('cmdb_rel_ci');
for (i in payloadObj.items) {
item = payloadObj.items[i];
if (item.className == "cmdb_ci_cloud_ecs_task_definition") {
tdGr.get(item.sysId);
gs.info("ECS TASK DEF: checking task definition " + tdGr.object_id);
if (toString(tdGr.comments).length > 0) {
gs.info("ECS TASK DEF: processing image list for " + tdGr.object_id + ", " + tdGr.comments);
var imageList = tdGr.comments.split(',');
for (var j = 0; j < imageList.length; j++) {
// add relationship payload
var imGr = new GlideRecord('cmdb_ci_docker_image');
imGr.addQuery('name', imageList[j]);
imGr.query();
if (!(imGr.next())) {
gs.error("ECS TASK DEF: no image found: " + imageList[j] + " for task def " + tdGr.object_id);
continue;
}
// look for existing relationship
relGr.addEncodedQuery('parent=' + tdGr.sys_id + '^type=cb5592603751200032ff8c00dfbe5d17^child=' + imGr.sys_id);
relGr.query();
if (!relGr.hasNext()) {
gs.info("ECS TASK DEF: adding relationship for " + imageList[j] + " to task def " + tdGr.object_id);
relGr.initialize();
relGr.setValue('type', 'cb5592603751200032ff8c00dfbe5d17');
relGr.setValue('parent', tdGr.sys_id);
relGr.setValue('child', imGr.sys_id);
relGr.insert();
} else {
gs.info("ECS TASK DEF: existing relationship found for "+imageList[j] + " to task def " + tdGr.object_id);
}
}
}
}
}
// You can return a message and a status, on top of the input variables that you MUST return.
// Returning the payload as a Json String is mandatory in case of a pre sensor script, and optional in case of post sensor script.
// If you want to terminate the payload processing due to your business logic - you can set isSuccess to false.
rtrn = {
'status': {
'message': 'Processed ECS task definition image relationships',
'isSuccess': true
},
'patternId': patternId,
'payload': JSON.stringify(payloadObj)
};
This script code iterates through the IRE payload from the pattern and for each cmdb_ci_cloud_ecs_definition CI, it parses the list of images from the Comments attribute and creates a "Uses::Used by" (per sys_id cb5592603751200032ff8c00dfbe5d17) relationship between the ECS task definition and the cmdb_ci_docker_image record which matches each image name.
Result
The result of this enhancement is when I discover my AWS environment, the ECS task definition records now show which container images they depend on. The resulting cmdb_ci_docker_image records can now be scanned for package inventory via the Scan Container Image pattern (for more information on image scanning, see https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB1218504).
- 1,043 Views