Command Line Interface (CLI)
N|Solid comes with a set of predefined endpoints for interaction and introspection that can be accessed at the command-line using the N|Solid Command Line Interface, nsolid-cli
.
To see a list of all commands and options available with nsolid-cli
, use the -h
option:
nsolid-cli -h
The output of the nsolid-cli
commands, unless otherwise noted, is line-delimited JSON (each line is separated by a newline delimiter \n
). The output shown in the examples below is shown expanded for readability.
--start
and --end
options
For commands that take --start
and --end
options, you can pass the following
formats for the date/time value:
format |
description |
milliseconds since epoch |
value returned from Date.now() |
yyyy-mm-ddThh:mm:ss |
ISO date |
-Ns |
N seconds since now |
-Nm |
N minutes since now |
-Nh |
N hours since now |
-Nd |
N days since now |
0 |
now, when used with the --end option |
The --end
option can only be specified if the --start
option is also
specified. If the --end
option is not specified, the command will continue
returning JSON objects till terminated.
application
Returns objects which contains summary information about all the processes in
the specified application.
The current object will be returned on the specified interval.
Options |
Description |
--app |
Application name (required) |
--interval |
Number of seconds before returning next current object (default: 1) |
Usage
nsolid-cli application --app=my-app-name
Example JSON Result
{
"time": 1474520062141,
"app": "my-app-name",
"hostCount": 1,
"processCount": 1,
"processes": [
{
"id": "7e5c0f931033a6b1cd8e037b8ea099f9cf78af65",
"app": "my-app-name",
"hostname": "my-computer.local",
"tags": [
"region:north",
"zone:A"
],
"cpu": 0.007,
"heapUsed": 19178512,
"title": "my-app-name",
"uptime": 4697.88,
"pid": 23888,
"processStart": 1474515364290,
"packageCount": 80,
"vulnerabilityCount": 0,
"thresholds": {}
}
],
"vulnerabilities": [],
"vulnerabilityCount": 0
}
Returns a stream of the following objects:
Property |
Description |
time |
Millisecond since epoch time message was sent |
app |
The NSOLID_APPNAME value |
hostCount |
The number of hosts this application is running on |
processCount |
The number of processes running this application |
processes |
Array of process objects, described below |
vulnerabilityCount |
The number of vulnerabilities found in all processes |
vulnerabilities |
An array of vulnerabilities found |
Process objects:
Property |
Description |
id |
The agent id |
app |
The NSOLID_APPNAME value |
hostname |
The host the process is running on |
tags |
The NSOLID_TAGS values |
cpu |
% cpu being used by the process |
heapUsed |
The size of the JavaScript heap used (bytes) |
title |
The process title |
uptime |
The time in seconds this process has been running |
pid |
The operating system process id |
processStart |
The time the process started |
packageCount |
The number of packages loaded |
vulnerabilityCount |
The number of vulnerabilities found |
thresholds |
Threshold data |
applications
Return objects which contains summary information about all the applications
available.
The current object will be returned on the specified interval.
Options |
Description |
--interval |
Number of seconds before returning next current object (default: 1) |
Usage
nsolid-cli applications
Example JSON Result
{
"time": 1474520766732,
"applications": [
{
"processCount": 1,
"vulnerabilityCount": 0,
"name": "my-app-name",
"hostCount": 1
}
]
}
Returns a stream of the following objects:
Property |
Description |
time |
Millisecond since epoch time message was sent |
applications |
Array of application objects, described below |
Application objects:
Property |
Description |
name |
The NSOLID_APPNAME value |
processCount |
The number of processes running this application |
vulnerabilityCount |
The number of vulnerabilities found |
hostCount |
The number of hosts this application is running on |
asset
Download an asset.
Options |
Description |
--asset |
The asset id (required) |
Usage
nsolid-cli asset --asset 217040c0-02d1-4956-8648-7fb84b78c65e > my.heapsnapshot
Asset id's are available from the assets
command. The bytes of the asset
will be written to stdout.
assets
Lists the assets - CPU profiles and heap snapshots - that are currently
available for download.
Options |
Description |
--id |
The agent id |
--app |
The NSOLID_APPNAME value |
--hostname |
The host the process is running on |
--tag |
An NSOLID_TAGS value (may be specified multiple times) |
--type |
either 'snapshot' or 'profile', to limit the type of asset returned |
--start |
Return assets that were created after the specified time |
--end |
Return assets that were created before the specified time |
Usage
nsolid-cli assets --app my-app-name --type snapshot
Example JSON Result
{
"time": 1476464230018,
"asset": "217040c0-02d1-4956-8648-7fb84b78c65e",
"type": "snapshot",
"id": "a6d4acf3e713043a293b3fdbd5df9bac885c727a",
"app": "my-app-name",
"hostname": "my-computer.local",
"tags": [
"region:north",
"zone:A"
],
"size": 12206681,
"pid": 77465,
"title": "my-app-name"
}
Returns a stream of the following objects:
Property |
Description |
time |
Millisecond since epoch time message was sent |
asset |
an asset id to use the the asset command |
type |
'snapshot' for heap snapshots, 'profile' for CPU profiles |
id |
The agent id |
app |
The NSOLID_APPNAME value |
hostname |
The host the process is running on |
tags |
The NSOLID_TAGS values |
size |
The size of the asset in bytes |
pid |
The operating system process id |
title |
The process title |
async-activity
N|Solid can list any pending asynchronous operations and where the JavaScript callbacks will resume. This can be extremely helpful for determining how many concurrent operations a given N|Solid
process is handling and what they are. It can also be useful to determine where an application is hanging, if there are any
left-behind callbacks or a misue of resources (e.g. reading the same file repetitively)
The output will list the in-flight asynchronous activity, including the function location and line of source code to
reference where the callback will resume.
Options |
Description |
--id |
The agent id |
--app |
The NSOLID_APPNAME value |
--hostname |
The host the process is running on |
--tag |
An NSOLID_TAGS value (may be specified multiple times) |
Usage
nsolid-cli async-activity
Example JSON Result
{
"handles": [
{
"name": "onrequest",
"location": {
"file": "nsolid-user/server-http.js",
"line": 3,
"column": 19,
"inferredName": ""
},
"anonymous": false,
"code": "function onrequest(req, res) { res.end('ok\n') }",
"type": {
"group": "handle",
"flag": 4,
"name": "TCP server connection"
},
"details": {
"fd": 10,
"transport": "TCP",
"connectionKey": "6::::0",
"connections": 0,
"unrefd": false
},
"metadata": {
"async_wrap_provider": "TCPWRAP",
"async_wrap_providerKey": "15"
}
},
{
"type": {
"group": "handle",
"flag": 64,
"name": "pipe socket"
},
"details": {
"fd": 1,
"transport": "Pipe",
"bytesDispatched": 0,
"hadError": false,
"host": null,
"pendingData": "<Buffer>"
},
"metadata": {
"async_wrap_provider": "PIPEWRAP",
"async_wrap_providerKey": "8"
}
},
{
"type": {
"group": "handle",
"flag": 64,
"name": "pipe socket"
},
"details": {
"fd": 2,
"transport": "Pipe",
"bytesDispatched": 57985,
"hadError": false,
"host": null,
"pendingData": "<Buffer>"
},
"metadata": {
"async_wrap_provider": "PIPEWRAP",
"async_wrap_providerKey": "8"
}
}
],
"requests": [
{
"name": "onreadFile",
"location": {
"file": "nsolid-user/server-http.js",
"line": 14,
"column": 20,
"inferredName": ""
},
"anonymous": false,
"code": "function onreadFile(err, src) {\n if (err) return console.error(err)\n readAgain()\n}",
"type": {
"group": "request",
"flag": 4,
"name": "readFile",
"api": "fs.readFile(filename[, options], callback)"
},
"details": {
"path": "nsolid-user/server-http.js",
"flag": "r",
"isUserFd": false,
"buffers": [
"<Buffer>"
],
"buffer": "<Buffer>",
"pos": 0,
"encoding": null,
"err": null
},
"metadata": {
"async_wrap_provider": "FSREQWRAP",
"async_wrap_providerKey": "3"
}
}
],
"pending": [],
"time": 1474407457414,
"id": "8ed04c57f248624c6068945b68a5f023497498cd",
"app": "runtime/async-activity/03-server-http_app",
"hostname": "ebc192f5fae2"
}
Returns a stream of the following objects:
Property |
Description |
handles |
tend to be longer-lived larger-scale asynchronous operations, such as open sockets or timers |
requests |
tend to be shorter-lived smaller-scale operations such as writing to file handles and other file-related operations |
pending |
represent async activity that is lower level and a lot of times are created by cod inside core, like DNS lookups, signal handlers and TCP connections |
custom
Invoke a custom command. For more information on custom commands, see
Custom Commands.
Options |
Description |
--id |
The agent id (required) |
--name |
The name of the custom command (required) |
--data |
Data to be sent with the command |
Usage
nsolid-cli custom --id=[agent id] --name=verbose --data=off
Example JSON Result
{
"time": 1476754051460,
"id": "81535293aea1fe8c1e2f3f7518d8db3f96cf7b39",
"app": "nsolid2",
"hostname": "pmuellr-MacBook-Pro.local",
"tags": [
"foobar"
],
"result": {
"verbose": false
}
}
Returns a JSON object with the following properties
Property |
Description |
time |
Millisecond since epoch time message was sent |
id |
The agent id |
app |
The NSOLID_APPNAME value |
hostname |
The host the process is running on |
tags |
The NSOLID_TAGS values |
result |
The result of the custom command |
generate-keypair
Return a randomly generated keypair suitable for use in the N|Solid Storage
socket configuration. If your N|Solid Storage instance is running on an
untrusted network, it is recommended that you generate and use new keys.
Usage
nsolid-cli generate-keypair
Example JSON Result
{
"public": "[t&m}{EZH7=HR(IW:+Ttk:=r.Y$:CP+-Q&5L?2N!",
"private": "4QZof={^Pman?I?mB0o!]%z/{Jlu6:mJfl[Ms@[^"
}
Returns a JSON object with the following properties
Property |
Description |
public |
Public key value, publicKey in N|Solid Storage configuration and env var NSOLID_PUBKEY for N|Solid Runtime |
private |
Private key value, privateKey in N|Solid Storage configuration |
info
Returns objects which contain static information about processes and the hosts
they are running on.
Options |
Description |
--id |
The agent id |
--app |
The NSOLID_APPNAME value |
--hostname |
The host the process is running on |
--tag |
An NSOLID_TAGS value (may be specified multiple times) |
--field |
Output field (may be specified multiple times) |
--start |
Return objects for processes that started after the specified time |
--end |
Return objects for processes that started before the specified time |
Usage
nsolid-cli info
Example JSON Result
{
"id": "7e5c0f931033a6b1cd8e037b8ea099f9cf78af65",
"tags": [
"region:north",
"zone:A"
],
"pid": 23888,
"processStart": 1474515364290,
"execPath": "/Users/me/nsolid",
"main": "/Users/me/Projects/my-app-name.js",
"arch": "x64",
"platform": "darwin",
"totalMem": 17179869184,
"versions": {
"http_parser": "2.7.0",
"node": "6.5.1",
"nsolid": "2.0.0",
"v8": "5.1.281.81",
"uv": "1.9.1",
"zlib": "1.2.8",
"ares": "1.10.1-DEV",
"icu": "57.1",
"modules": "48",
"openssl": "1.0.2h",
"nsolid_lib": {
"v8_profiler": "nsolid",
"sodium": "nsolid",
"cjson": "nsolid",
"function_origin": "nsolid",
"nan": "v2.3.5",
"cli": "master",
"agent": "master",
"zmq-bindings": "nsolid",
"zmq": "nsolid",
"persistents_with_classid": "v1.1.0"
}
},
"cpuCores": 8,
"cpuModel": "Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz",
"time": 1474520894162,
"app": "my-app-name",
"appVersion": "1.0.0",
"hostname": "my-computer.local"
}
Returns a stream of the following objects:
Property |
Description |
time |
Millisecond since epoch time message was sent |
id |
The agent id |
app |
The NSOLID_APPNAME value or name property from package.json |
appVersion |
The version property from package.json |
hostname |
The host the process is running on |
tags |
The NSOLID_TAGS values |
pid |
Operating system process id |
processStart |
The time the process started |
execPath |
Path of the executable running the application |
main |
The main module used when the application started up |
arch |
The CPU architecture |
platform |
Name of the N|Solid platform |
totalMem |
Total available memory in the system |
cpuCores |
The number of CPU cores |
cpuModel |
The CPU model |
versions |
Object describing the versions of components used in the runtime |
info with the --force
option
Requests current information from each running agent, or specified agents if using a filter.
Options |
Description |
--id |
The agent id |
--app |
The NSOLID_APPNAME value |
--hostname |
The host the process is running on |
--tag |
An NSOLID_TAGS value (may be specified multiple times) |
--field |
Output field (may be specified multiple times) |
list
Returns an array of all available matching N|Solid processes, along with their
most recent info
and metrics
data.
Options |
Description |
--id |
The agent id |
--app |
The NSOLID_APPNAME value |
--hostname |
The host the process is running on |
--tag |
An NSOLID_TAGS value (may be specified multiple times) |
Usage
nsolid-cli list
Example JSON Result
{
"id": "7e5c0f931033a6b1cd8e037b8ea099f9cf78af65",
"app": "my-app-name",
"hostname": "my-computer.local",
"tags": [
"region:north",
"zone:A"
],
"info": { ... output from the info command ... },
"metrics": { ... output from the metrics command ... },
}
Returns an array of the following object shapes:
Property |
Description |
info |
The object returned from the info command |
metrics |
The object returned from the metrics command |
metrics
Returns a stream of metrics
records matching the query string parameters.
Options |
Description |
--id |
The agent id |
--app |
The NSOLID_APPNAME value |
--hostname |
The host the process is running on |
--tag |
An NSOLID_TAGS value (may be specified multiple times) |
--field |
Output field (may be specified multiple times) |
--start |
Return metrics created after the specified time |
--end |
Return metrics created before the specified time |
Usage
nsolid-cli metrics
Example JSON Result
{
"time": 1474521264390,
"uptime": 5900.431,
"rss": 88784896,
"heapTotal": 26275840,
"heapUsed": 22151064,
"activeRequests": 0,
"activeHandles": 7,
"title": "my-app-name",
"user": "me",
"cpu": 0,
"freeMem": 190222336,
"systemUptime": 1705341,
"load1m": 2.20068359375,
"load5m": 1.9150390625,
"id": "7e5c0f931033a6b1cd8e037b8ea099f9cf78af65",
"load15m": 1.81689453125,
"cpuSpeed": 2500,
"app": "my-app-name",
"hostname": "my-computer.local",
"percentCpuThreshold": -1,
"percentHeapThreshold": -1,
"percentHostMemoryUsedByProcess": 0.0052,
"percentHostMemoryUsed": 0.9889,
"tags": [
"region:north",
"zone:A"
]
}
Returns a stream of the following objects:
Property |
Description |
time |
Millisecond since epoch time message was sent |
id |
The agent id |
app |
The NSOLID_APPNAME value |
hostname |
The host the process is running on |
tags |
The NSOLID_TAGS values |
uptime |
The time in seconds this process has been running |
rss |
The total Resident Set Size (total memory used) by this process (bytes) |
heapTotal |
The total allocated size of the JavaScript heap (bytes). A subset of rss |
heapUsed |
The amount of heapTotal being used by JavaScript (bytes)Returns live metrics reflecting the health and resource utilization of the process. |
activeRequests |
The number of active requests the event loop will process. For more information see the async-activity command. |
activeHandles |
The number of active handles the event loop will process. For more information, see the async-activity command. |
title |
The process title |
user |
The user the process is running as |
cpu |
% cpu being used by the process |
freeMem |
The amount of free (unused) memory in bytes |
systemUptime |
The uptime of the system, in seconds |
load1m |
The one-minute load average* |
load5m |
The five-minute load average* |
load15m |
The fifteen-minute load average* |
cpuSpeed |
The current speed of the CPU (averaged across all cores) in MHz |
percentCpuThreshold |
Percent of CPU threshold used (or -1 if no threshold set) |
percentHeapThreshold |
Percent of heap threshold used (or -1 if no threshold set) |
percentHostMemoryUsedByProcess |
Percent of memory used by process |
percentHostMemoryUsed |
Percent of memory used by all processes |
metrics with the --force
option
Requests current metrics from each running agent, or specified agents if using a filter.
Options |
Description |
--id |
The agent id |
--app |
The NSOLID_APPNAME value |
--hostname |
The host the process is running on |
--tag |
An NSOLID_TAGS value (may be specified multiple times) |
--field |
Output field (may be specified multiple times) |
packages
Return the list of packages and modules available in the specified process.
Options |
Description |
--id |
The agent id (required) |
Usage
nsolid-cli packages --id=[agent id]
Example JSON Result
{
"packages": [
{
"path": "/Users/me/my-app-name",
"name": "my-app-name",
"main": "my-app-name",
"version": "1.0.0",
"dependencies": [
"node_modules/async",
"node_modules/bole",
"node_modules/client-request",
"node_modules/lodash",
"node_modules/marked",
"node_modules/minimist",
"node_modules/mkdirp",
"node_modules/semver",
"node_modules/stringcase",
"node_modules/toml",
"node_modules/user-home",
"node_modules/uuid"
],
"modules": [
{
"path": "index.js",
"shasum": "b76d1c3b6af5515dca0b36ed0ef87b248d9acc94"
}
]
}
]
}
Returns an object with the following shape:
Property |
Description |
time |
Millisecond since epoch time message was sent |
id |
The agent id |
app |
The NSOLID_APPNAME value |
hostname |
The host the process is running on |
tags |
The NSOLID_TAGS values |
packages |
A packages object, described below |
Packages objects:
Property |
Description |
path |
The path the package was loaded from |
name |
The name of the package |
version |
The version of the package |
main |
The main module for the package |
dependencies |
An array of relative package names this package depended on |
modules |
An array of module objects, described below |
Modules objects:
Property |
Description |
path |
The package-relative path name of the module loaded |
shasum |
The SHASUM hash of the module contents |
ping
Have all matching processes send a simple response back.
Options |
Description |
--id |
The agent id |
--app |
The NSOLID_APPNAME value |
--hostname |
The host the process is running on |
--tag |
An NSOLID_TAGS value (may be specified multiple times) |
Usage
nsolid-cli ping
Example JSON Result
{
"pong": true,
"id": "7e5c0f931033a6b1cd8e037b8ea099f9cf78af65",
"time": 1474521577972
}
Returns a stream of the following objects:
Property |
Description |
time |
Millisecond since epoch time message was sent |
id |
The agent id |
pong |
Will always have the value true |
profile
Have a CPU profile taken in in the specified process.
Options |
Description |
--id |
The agent id (required) |
--duration |
Duration of profile in seconds. Default is 5 seconds |
Usage
nsolid-cli profile --id=[agent id] > my.cpuprofile
Returns a V8 CPU profile.
Once the profile file has been created, it can be opened using Chrome’s
Development Tool’s CPU Profile Debugging
Tool.
It’s important to note that Chrome requires the generated file to have the
extension .cpuprofile
to load the file.
snapshot
Have a heap snapshot taken in in the specified process.
Options |
Description |
--id |
The agent id (required) |
Usage
nsolid-cli snapshot --id=[agent id] > my.heapsnapshot
Returns a V8 heap snapshot.
Once the snapshot file has been created, it can be opened using Chrome’s
Development Tool’s heap snapshot browser
It’s important to note that Chrome requires the generated file to have the
extension .heapsnapshot
to load the file.
startup-times
Lists the time from initial process execution to reach certain process lifecycle startup phases.
Options |
Description |
--id |
The agent id |
--app |
The NSOLID_APPNAME value |
--hostname |
The host the process is running on |
--tag |
An NSOLID_TAGS value (may be specified multiple times) |
Usage
nsolid-cli startup-times
Example JSON Result
{
"time": 1476755309783,
"id": "7e5c0f931033a6b1cd8e037b8ea099f9cf78af65",
"app": "my-app-name",
"hostname": "my-computer.local",
"initialized_node": [
0,
166736
],
"initialized_v8": [
0,
366153
],
"loaded_environment": [
0,
80486563
]
}
Returns a stream of the following objects:
Property |
Description |
time |
Millisecond since epoch time message was sent |
id |
The agent id |
app |
The NSOLID_APPNAME value |
hostname |
The host the process is running on |
initialized_node |
The time it took to initialize the Node internals |
initialized_v8 |
The time it took to initialize the V8 engine |
loaded_environment |
The time it took to complete all initialization, which includes running some of node's internal JavaScript code, and your main module's top-level code |
The times are provided in hrtime
syntax: an array of 2 integers representing the time since the initial process execution in [seconds, nanoseconds].
Additional timers can be added to your application with custom lifecycle events.
vulnerabilities
Returns the known security vulnerabilities of all processes.
Options |
Description |
--interval |
Number of seconds before returning next current object (default: 1) |
Usage
nsolid-cli vulnerabilities
Example JSON Result
{
"time": 1476755941704,
"vulnerabilities": [
{
"package": "moment",
"title": "Regular Expression Denial of Service",
"published": "2016-02-01T19:00:03.862Z",
"credit": [
"Adam Baldwin"
],
"ids": {
"CWE": [
"CWE-400"
],
"CVE": [],
"NSP": 55,
"ALTERNATIVE": [
"SNYK-JS-MOMENT-10084"
]
},
"vulnerable": "<=2.11.1",
"description": "markdown descript of vulnerability",
"apps": [
{
"appname": "my-app-name",
"processes": [
{
"id": "7e5c0f931033a6b1cd8e037b8ea099f9cf78af65",
"hostname": "my-computer.local",
"pid": 23888,
"loaded": [
{
"version": "2.11.0",
"path": "/Users/me/Projects/my-app-name/node_modules/moment"
}
]
}
]
}
],
"patches": [
"... url to patches ..."
]
}
]
}
Returns a stream of the following objects:
Property |
Description |
time |
Millisecond since epoch time message was sent |
vulnerabilities |
An array of vulnerability objects, described below |
Vulnerability objects:
Property |
Description |
package |
the package with the vulnerability |
title |
the title of the vulnerability |
published |
date the vulnerability was published |
credit |
names of the people credited with finding the vulnerability |
ids |
identifiers for the vulnerability; CVE, CWE, etc |
vulnerable |
semver expression describing what versions of the package are vulnerable |
description |
description of the vulnerability, in markdown |
apps |
an array of application objects, describing which applications and processes are running the vulnerable module, along with the version loaded and path to the package |
patches |
link to patches available for the vulnerability |
Custom Commands
As a developer, you can trigger your own custom commands via the N|Solid Command Line Interface (CLI). Custom commands allow you to interact with your application's processes in ways specific to your business needs.
You can implement a custom command by creating a function to handle the command, and then registering the function with N|Solid.
The custom command function should be defined to take a single parameter, request
:
function customCommandHandler(request) { ... }
The request parameter is an object with the following properties/functions:
Parameter |
Description |
request.value |
An optional piece of data sent with the command, using the nsolid-cli parameter --data . |
request.return(value) |
The function to call when you are ready to return the result of this command. The Agent will reply with the value passed as a parameter. |
request.throw(error) |
A function to call if an error is encountered. The Agent will reply with the error passed as a parameter. |
Your function you must call either request.return()
or request.throw()
to signal completion of the command.
A custom command handler is registered using the nsolid.on()
method. You can get access to N|Solid's built-in nsolid
module, by calling require("nsolid")
. The nsolid.on()
function takes the following parameters:
nsolid.on(commandName, handler)
Parameter |
Description |
commandName |
The string name of the command to implement |
handler |
The custom command function implementing the command |
The structure of implementing and registering a custom command will look like the code below:
...
const nsolid = require("nsolid")
...
nsolid.on("foo", fooCommand)
...
function fooCommand(request) { ... }
Example: Log Level Custom Command
Below is an example of how you can use custom commands to dynamically change the configuration state of the application; specifically the log level. The example assumes that a global boolean variable Verbose
is used to indicate whether to log verbosely or not.
//------------------------------------------------------------------------------
// This program is a simple "server" which does nothing, but does implement
// an N|Solid custom command, named `verbose`. Once you've started this program
// with the N|Solid agent enabled, you can send the `verbose` command as in:
//
// nsolid-cli --id $NSOLID_AGENTID custom --name verbose
// nsolid-cli --id $NSOLID_AGENTID custom --name verbose --data on
// nsolid-cli --id $NSOLID_AGENTID custom --name verbose --data off
//
// All these forms get or set the "verbose" level of logging in the program.
//
// The server logs a message every second when "verbose" is off, and logs
// an additional message after that one when "verbose" is on. The default
// setting of "verbose" is false.
//------------------------------------------------------------------------------
"use strict"
// get access to N|Solid's built-in module `nsolid`
const nsolid = require("nsolid")
// the current "verbose" level
let Verbose = false
// register the `verbose` command for nsolid-cli
nsolid.on("verbose", verboseCommand)
// your server which doesn't do much
setInterval(onInterval, 2000)
console.log("N|Solid custom command demo - log-level - started")
console.log("")
console.log("to use the verbose command with `nsolid-cli`, run:")
console.log(" nsolid-cli --id $NSOLID_AGENTID custom --name verbose")
console.log(" nsolid-cli --id $NSOLID_AGENTID custom --name verbose --data on ")
console.log(" nsolid-cli --id $NSOLID_AGENTID custom --name verbose --data off ")
//------------------------------------------------------------------------------
function onInterval() {
log("interval event!")
logVerbose("some extra logging here")
}
//------------------------------------------------------------------------------
// implements the `verbose` command for nsolid-cli
//------------------------------------------------------------------------------
function verboseCommand(request) {
// if "on" or "off" passed in with --data, set Verbose appropriately
if (request.value == "on") {
Verbose = true
}
else if (request.value == "off") {
Verbose = false
}
else if (request.value) {
return request.throw("expecting data of `on` or `off`, got " + request.value)
}
// return current value of Verbose
return request.return({verbose: Verbose})
}
//------------------------------------------------------------------------------
function log(message) {
console.log(message)
}
//------------------------------------------------------------------------------
function logVerbose(message) {
if (!Verbose) return
log(message)
}
When running your application with the N|Solid agent active, you can use the following command to return the current value of the Verbose
setting:
nsolid-cli --id $NSOLID_AGENTID custom --name verbose
To set Verbose
on or off, use one of the following commands:
NSOLID_AGENTID="69d916ad395061f80589e20bef9af3cb50ece9cb" # This will change
nsolid-cli --id $NSOLID_AGENTID custom --name verbose --data on
nsolid-cli --id $NSOLID_AGENTID custom --name verbose --data off
The output of these three cli commands looks like the following.
{"verbose":false,"time":1472496720972,"timeNS":"1472496720972042976","id":"69d916ad395061f80589e20bef9af3cb50ece9cb","app":"my-verbose-app","hostname":"titania"}
In this example you have directed a command at a single instance of your app. If you have multiple copies of this app running and you want to set all of their log levels to "verbose" simultaneously, omit the id
parameter and use the app
parameter instead.
nsolid-cli --app my-verbose-app custom --name verbose --data on
nsolid-cli --app my-verbose-app custom --name verbose --data off
This time multiple instances of the app might respond to the request.
{"verbose":false,"time":1472496720956,"timeNS":"1472496720956429760","id":"69d916ad395061f80589e20bef9af3cb50ece9cb","app":"my-verbose-app","hostname":"titania"}
{"verbose":false,"time":1472496720961,"timeNS":"1472496720961042976","id":"f1a6492b6bdf44db003a163430c7c7244ae28212","app":"my-verbose-app","hostname":"titania"}
{"verbose":false,"time":1472496720972,"timeNS":"1472496720972132564","id":"54153b774190fa24672708120b94b10fd41f75b8","app":"my-verbose-app","hostname":"titania"}
Policies
N|Solid ships with the ability to enable some security-related policies to help harden your application. Currently these include the ability to disable core modules and bindings.
To enable policy configuration with N|Solid, you must create a policies file in JSON format, and specify that file via the policies flag when starting N|Solid.
nsolid --policies my-policies.json app.js
Disabling Core Modules
N|Solid includes the ability to disable core modules with a policy file. This can be used to restrict application access to system resources or features that should not be used by your application.
There are two types of core resources that can be disabled: modules and bindings:
- modules are the JavaScript APIs of Node, e.g.
fs
or http
;
- bindings are the wrappers for native code, e.g.
stream_wrap
or tcp_wrap
.
There are four different severity levels you can configure:
Parameter |
Level |
Description |
0 |
ignore |
No notice will be provided during the loading of the module or binding. This is the default behavior. |
1 |
warning |
A warning is written to stderr during the loading of the module or binding. The application otherwise runs normally. |
2 |
throw error |
A error is thrown only when the policy is _violated_ which doesn't occur during the _loading_ of the module, but when a function on it is called. You can catch this by writing a try/catch in your code around your require() calls. |
3 |
exit |
The application exits during the loading of the module or binding. |
Disabling a module in the policy file prevents all non-core modules from using it i.e a warning is printed when loaded, but only when it is used does the violation handler kick in). Core modules are still able to load it (e.g. the core module library can still use fs
to read new files via require()
)
Example Policy File: disable-dns-all.policy.json
{
"// severity levels": "0 - ignore; 1 - warning; 2 - throw error; 3 - exit",
"blacklist": {
"modules": {
"dns": 2
},
"bindings": {
"cares_wrap": 2
}
}
}
Access to bindings can also be restricted, if so desired, by the policy writer. The example policy file above disables both the dns
module and the cares_wrap
module, both of which can be used to access DNS.
When a non-core module attempts to access a disabled core module, messages will be logged to stdout
, and an exception thrown.
Usage of disable-dns-all.policy.json
$ nsolid --policies disable-dns-all.policy.json faux-dns.js
nsolid error Binding "cares_wrap" is requested via a process.binding call
nsolid error at Object.<anonymous> (/Users/user/nsolid-demos/demos/faux-dns.js:3:23)
nsolid error But it was disabled in the policies.
_module_wrap.js:423
throw new Error('Binding "' + id +
^
Error: Binding "cares_wrap" has been disabled by the policies flag, using "GetAddrInfoReqWrap" on it is not allowed, terminating execution.
at new throwError (_module_wrap.js:423:11)
at Module._compile (module.js:430:26)
... more stack trace lines here
More Policy Usage
Disabling a child process
{
"blacklist": {
"modules": {
"child_process": 2, -- blacklist entire child_process module with severity level 2
}
}
}
Code usage
var ls = require("child_process").execSync("ls -l")
console.log(ls.toString())
Running with policy
$ nsolid --policies disable_childprocess.json child_process_example.js
nsolid error Module "child_process" is required
nsolid error at Object.<anonymous> (/home/bryce/ns/nsolid-node/foo.js:1:72)
nsolid error But it was disabled in the policies.
child_process.js:75
throw new Error('"' + module.id + '" has been disabled ' +
^
Error: "child_process" has been disabled by the policies flag, terminating execution.
at handleDisabledMethodCall (child_process.js:75:9)
at Object.execSync (child_process.js:89:22)
at Object.<anonymous> (/home/bryce/ns/nsolid-node/foo.js:1:96)
at Module._compile (module.js:434:26)
at Object.Module._extensions..js (module.js:452:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:475:10)
at startup (node.js:149:18)
at node.js:985:3
Function using the binding 'cares_wraps'
module.exports = lookup;
var cares = process.binding('cares_wrap');
function lookup(hostname, callback) {
var req = new cares.GetAddrInfoReqWrap();
req.callback = callback;
req.family = 4;
req.hostname = hostname;
req.oncomplete = callback;
var err = cares.getaddrinfo(req, hostname, 4, 0);
if (err) {
callback(new Error("OOPS"));
return {};
}
return req;
}
Calling function
var look = require("./fauxdns.js");
look("nodesource.com", function (err, data) {
console.log(data);
});
Without a policy file we're able to access the network via the DNS binding
$ nsolid lookup.js
[ '162.243.142.64' ]
With a policy file that prevents just the dns
module
$ cat disable_dns.js
{
"blacklist": {
"modules": {
"dns": 2
}
}
We can still access it!!
$ nsolid --policies disable_dns.js lookup.js
[ '162.243.142.64' ]
To actually prevent this circumvention of the modulesBlacklist
we need to blacklist the cares_wrap binding
$ cat disable_cares.json
{
"blacklist": {
"bindings": {
"cares_wrap": 2
}
}
}
Now the behavior is blocked!
$ nsolid --policies disable_cares.json lookup.js
nsolid error Binding "cares_wrap" is requested via a process.binding call
nsolid error at Object.<anonymous> (/Users/kevin/develop/nodesource/policies/fauxdns.js:3:21)
nsolid error But it was disabled in the policies.
_module_wrap.js:423
throw new Error('Binding "' + id +
^
Error: Binding "cares_wrap" has been disabled by the policies flag, using "GetAddrInfoReqWrap" on it is not allowed, terminating execution.
at new throwError (_module_wrap.js:423:11)
at lookup (/Users/kevin/develop/nodesource/policies/fauxdns.js:7:13)
at Object.<anonymous> (/Users/kevin/develop/nodesource/policies/lookup.js:3:1)
at Module._compile (module.js:434:26)
at Object.Module._extensions..js (module.js:452:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:475:10)
at startup (node.js:150:18)
at node.js:986:3
A policy file that disables several modules and bindings
{
"blacklist": {
"modules": {
"child_process": 2, -- blacklist entire child_process module with severity level 2
"fs": 3, -- blacklist entire fs module with severity level 3
"path": 0 -- blacklist path with severity level 0, same as omitting `path` from blacklist all together
}
"bindings": {
"stream_wrap": 2 -- blacklist entire stream_wrap binding with severity level 2
},
}
}
Comments
We allow properties whose keys start with "//" anywhere and they are ignored.
Invalid Policies
Anytime an unexpected property or a property with an invalid value is encountered, the policies are considered invalid and the process halted.
Further Thoughts
N|Solid's policies feature should not be used as a blind replacement for good security practices with regard to your code and the code of your application's dependencies. Disabling core modules and bindings does not provide a complete guarantee that your application is unable to use the features provided by those parts of Node.js. For example, child processes interacting with Unix utilities, if not disabled, can be used to replace the functionality of many of the core modules. Some core modules may be completely re-implemented in user-land modules, such as the dns
and cares_wrap
functionality. Compiled add-ons have complete freedom to insert new functionality that can replace anything that has been disabled.
N|Solid's policies features augment and support existing enterprise-wide application security hardening programs. Please contact NodeSource if you wish to discuss your Node.js application security needs and prepare a customized security hardening program that involves the use of internal and third-party code review, application monitoring and the use of operating system security tools.
Modules That Can Be Blacklisted
The following is a list of modules that can be blacklisted. It should be noted that for most of these modules it is rare to have a business need where blacklisting makes sense.
Module |
Description |
_debug_agent |
Provides support for debugging node.js, mostly used internally. |
_debugger |
Provides support for debugging node.js, mostly used internally. |
_linklist |
Data structure used internally by node.js. |
assert |
Used for writing unit tests for your applications, you can access it with require('assert'). |
buffer |
Raw data is stored in instances of the Buffer class. |
child_process |
Provides a tri-directional popen(3) facility in order to create a child process. |
console |
Console object is a special instance of Console whose output is sent to stdout or stderr, - constants. |
crypto |
Crypto module offers a way of encapsulating secure credentials to be used as part of a secure HTTPS net or http connection. |
cluster |
Allows you to easily create child processes that all share server ports. |
dgram |
Provides Datagram sockets. |
dns |
Provides name resolution. |
domain |
Pending deprecation - provide a way to handle multiple different IO operations as a single group. |
events |
Provides event emitters. |
freelist |
Data structure used internally by node.js. |
fs |
Provides file I/O via simple wrappers around standard POSIX functions. |
http |
Provides ability to create http servers and clients. |
_http_agent |
Provides support for http and https modules, mostly used internally. |
_http_client |
Provides support for http and https modules, mostly used internally. |
_http_common |
Provides support for http and https modules, mostly used internally. |
_http_incoming |
Provides support for http and https modules, mostly used internally. |
_http_outgoing |
Provides support for http and https modules, mostly used internally. |
_http_server |
Provides support for http and https modules, mostly used internally. |
https |
Provides ability to create https servers and clients. |
module |
Provides the node.js module system, mostly used internally. |
net |
Net module provides asynchronous network wrapper for server and clients. |
os |
Provides basic operating-system related utility functions. |
path |
Provides utilities for handling and transforming file paths. |
process |
Same as the global process object. |
punycode |
Provides Unicode utilities. |
querystring |
Provides utilities for dealing with query strings. |
readline |
Allows reading of a stream (such as process.stdin) on a line-by-line basis. |
repl |
Provides a way to interactively run JavaScript and see the results. |
stream |
Provides streaming functionality. |
_stream_readable |
Provides the ReadableStream exposed via the stream module. |
_stream_writable |
Provides the WritableStream exposed via the stream module. |
_stream_duplex |
Provides the DuplexStream exposed via the stream module. |
_stream_transform |
Provides the TransformStream exposed via the stream module. |
_stream_passthrough |
Provides the PassThroughStream exposed via the stream module. |
_stream_wrap |
Provides the wrapper to the libuv stream implementation, mostly used internally. |
string_decoder |
Decodes a buffer to a string with utf8 support. |
sys |
Alias for util. |
timers |
Provides internal support for global Timers. |
tls |
Uses OpenSSL to provide Transport Layer Security and/or Secure Socket Layer: encrypted stream communication. |
_tls_common |
Provides support for tls module, mostly used internally. |
_tls_legacy |
Provides support for tls module, mostly used internally. |
_tls_wrap |
Provides support for tls module, mostly used internally. |
tty |
Provides the tty.ReadStream and tty.WriteStream classes. |
url |
Provides utilities for URL resolution and parsing. |
util |
Primarily designed to support the needs of node.js's internal APIs, but many of these utilities are useful for user programs. |
v8 |
Events and interfaces specific to the version of v8. |
vm |
Provides support to compiled code and run immediately or compile, save it, and run later. |
zlib |
Provides bindings to Gzip/Gunzip. |
profiler |
Profiler module (explained in nsolid docs). |
_function_origin |
Internal module used by nsolid. |
_module_wrap |
Internal module used by nsolid. |
_module_wrap_known_modules |
Internal module used by nsolid. |
_module_wrap_known_bindings |
Internal module used by nsolid. |
_policies_validation |
Internal module used by nsolid. |
nsolid |
Internal module used by nsolid. |
nsolid_versions |
Internal module used by nsolid. |
Bindings That Can Be Blacklisted
The following is a list of bindings that can be blacklisted. It should be noted that for most of these bindings it is rare to have a business need where blacklisting makes sense.
Binding |
Description |
async_wrap |
Base class for all async request modules which supports hooks into async events. |
buffer |
Interface to libuv methods to operate on buffers. |
cares_wrap |
Wraps the cares library for asynchronous name resolves. |
contextify |
Interface to v8 in order to create execution contexts. |
crypto |
Provides crypto functionality such as SSL and ciphers |
fs |
Interface to file system methods provided by libuv. |
fs_event_wrap |
Binding to listen to file related events in order to support watching files and directories for changes. |
http_parser |
Binding to http_parser. |
js_stream |
Binding that provides support for node.js streams. |
os |
Interface to libuv in order to obtain process state information. |
pipe_wrap |
Wraps libuv's socket implementation. |
process_wrap |
Provides process functionality such as spawning child processes. |
signal_wrap |
Supports sending and handling signals to processes. |
spawn_sync |
Supports child_process.execSync functionality via libuv. |
stream_wrap |
Wraps stream implementations exposed by libuv to communicate via file descriptors or network connections. |
tcp_wrap |
Integrates TCP functionality exposed by libuv in order to create TCP connections. |
timer_wrap |
Integrates with timer functionality provided by libuv so support things like setTimeout and setInterval. |
tls_wrap |
Provides TLS termination functionality via crypto. |
tty_wrap |
Integrates with TTY terminal functionality provided by libuv. |
udp_wrap |
Provides UDP protocol functionality such as binding and broadcasting. |
uv |
Provides libuv integration such as error name resolution. |
v8 |
Limited interface to the v8 API, i.e. to set flags and get process information. |
zlib |
Wraps the zlib library. |