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 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 contain 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
Returns a JSON stream including the following properties:
Property |
Description |
time |
Milliseconds 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. Further described below |
vulnerabilityCount |
The number of vulnerabilities found in all processes |
vulnerabilities |
An array of vulnerabilities found |
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
}
The processes
array contains an object with the following properties:
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
Returns objects which contain summary information about all the applications
available to N|Solid.
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
Returns a JSON stream including the following properties:
Property |
Description |
time |
Milliseconds since epoch time message was sent |
applications |
Array of application objects. Further described below |
Example JSON Result
{
"time": 1474520766732,
"applications": [
{
"processCount": 1,
"vulnerabilityCount": 0,
"name": "my-app-name",
"hostCount": 1
}
]
}
The applications
array contains an object with the following properties:
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 via the assets
command described below. 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
Returns a JSON stream including the following properties:
Property |
Description |
time |
Milliseconds since epoch time message was sent |
asset |
An asset id to use with the asset command |
type |
'snapshot' for heap snapshots, or '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 |
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"
}
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 in determining where an application is hanging, if there are any
left-behind callbacks, or a misuse 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
Returns a JSON stream including the following properties:
Property |
Description |
handles |
An array of async operations. Usually longer-lived, larger-scale asynchronous operations, such as open sockets or timers |
requests |
An array of async operations. Usually shorter-lived, smaller-scale operations such as writing to file handles and other file-related operations |
pending |
An array of async operations. Represents async activity that is lower level. Often activity created by code inside core, like DNS lookups, signal handlers and TCP connections |
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"
}
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
Returns a JSON object with the following properties:
Property |
Description |
time |
Milliseconds 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 |
Example JSON Result
{
"time": 1476754051460,
"id": "81535293aea1fe8c1e2f3f7518d8db3f96cf7b39",
"app": "nsolid2",
"hostname": "pmuellr-MacBook-Pro.local",
"tags": [
"foobar"
],
"result": {
"verbose": false
}
}
generate-keypair
Returns 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
Returns a JSON object with the following properties:
Property |
Description |
public |
Public key value. publicKey in N|Solid Storage configuration, and env variable NSOLID_PUBKEY for N|Solid Runtime |
private |
Private key value. privateKey in N|Solid Storage configuration |
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@[^"
}
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
Returns a JSON stream including the following properties:
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 |
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"
}
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
Returns a JSON object including the following properties:
Property |
Description |
info |
The object returned from the info command |
metrics |
The object returned from the metrics command |
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 ... },
}
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
Consult the Metrics in Detail section for complete details on the metrics available.
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.874302319950784,
"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,
"totalHeapSizeExecutable": 8388608,
"totalPhysicalSize": 28397568,
"totalAvailableSize": 1471514720,
"heapSizeLimit": 1501560832,
"loopIdlePercent": 42.59350634392232,
"loopEstimatedLag": 47.882432888888886,
"loopsPerSecond": 11.989051138919644,
"loopAvgTasks": 1.5833333333333333,
"loopTotalCount": 5695,
"blockInputOpCount": 0,
"blockOutputOpCount": 4,
"cpuPercent": 0.874302319950784,
"cpuSystemPercent": 0.4728451232242015,
"cpuUserPercent": 0.40145719672658253,
"gcForcedCount": 0,
"gcFullCount": 0,
"gcCount": 233,
"gcCpuPercent": 0.03792483595186012,
"gcDurUs99Ptile": 3380,
"gcDurUsMedian": 524,
"gcMajorCount": 14,
"pageFaultHardCount": 8,
"pageFaultSoftCount": 106091,
"ctxSwitchInvoluntaryCount": 16338,
"ctxSwitchVoluntaryCount": 2061,
"ipcReceivedCount": 10347,
"ipcSentCount": 10383,
"signalCount": 0,
"swapCount": 0,
"tags": [
"region:north",
"zone:A"
]
}
metrics with the --force
option
Returns 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
Returns a list of packages and modules available in the specified process.
Options |
Description |
--id |
The agent id (required) |
Usage
$ nsolid-cli packages --id=[agent id]
Returns a JSON object with the following properties:
Property |
Description |
time |
Milliseconds 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 |
An object with packages info, further described below. Contains the modules object |
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"
}
]
}
]
}
The packages
object contains the following properties:
Property |
Description |
path |
The path the package was loaded from |
name |
The name of the package |
main |
The main module for the package |
version |
The version of the package |
dependencies |
An array of relative package names this package depended on |
modules |
An array of module objects, described below |
The modules
object contains the following properties:
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
Returns a JSON stream including the following properties:
Property |
Description |
time |
Milliseconds since epoch time message was sent |
id |
The agent id |
pong |
Will always have the value true |
Example JSON Result
{
"pong": true,
"id": "7e5c0f931033a6b1cd8e037b8ea099f9cf78af65",
"time": 1474521577972
}
profile
Generates a V8 CPU profile of 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
Once the profile file has been created, it can be opened using Chrome’s
Development Tool’s CPU Profile Debugging
Tool.
Note: To load the file, Chrome requires that the generated file have the
extension .cpuprofile
.
snapshot
Generates a V8 heap snapshot of the specified process.
Options |
Description |
--id |
The agent id (required) |
Usage
$ nsolid-cli snapshot --id=[agent id] > my.heapsnapshot
Once the snapshot file has been created, it can be opened using Chrome’s
Development Tool’s heap snapshot browser
Note: To load the file, Chrome requires that the generated file have the
extension .heapsnapshot
.
startup-times
Lists the time to reach certain process lifecycle startup phases from initial process execution.
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
Returns a JSON stream including the following properties:
Property |
Description |
time |
Milliseconds 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 |
An array of two integers. The time it took to initialize the Node internals, reported as [seconds, nanoseconds] |
initialized_v8 |
An array of two integers. The time it took to initialize the V8 engine, reported as [seconds, nanoseconds] |
loaded_environment |
An array of two integers. 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, reported as [seconds, nanoseconds] |
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
]
}
Additional timers can be added to your application with custom lifecycle events.
vulnerabilities
Returns known security vulnerabilities for all processes.
Options |
Description |
--interval |
Number of seconds before returning next current object (default: 1) |
Usage
$ nsolid-cli vulnerabilities
Returns a JSON stream including the following properties:
Property |
Description |
time |
Milliseconds 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 those 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 |
A description of the vulnerability, in markdown |
apps |
An array of application objects, describing which applications and processes are running the vulnerable module, the version loaded, and path to the package |
patches |
A link to patches available for the vulnerability |
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 description 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 ..."
]
}
]
}
Custom Commands
Custom commands can be triggered 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.
Create A Custom Command
To implement a custom command, create a function to handle the command, and register that 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:
Property |
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 N|Solid Agent will reply with the value passed as a parameter |
request.throw(error) |
A function to call if an error is encountered. The N|Solid 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.
To get access to N|Solid's built-in nsolid
module, call require("nsolid")
. A custom command handler is registered using the nsolid.on()
function:
The nsolid.on()
function takes the following parameters:
Parameter |
Description |
commandName |
The string name of the command to implement |
handler |
The custom command function implementing the command |
nsolid.on(commandName, handler)
Example Custom Command Registration
const nsolid = require("nsolid")
...
nsolid.on("foo", fooCommand)
...
function fooCommand(request) { ... }
Sample Case: 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, use the app
parameter instead of the id
parameter:
$ nsolid-cli --app my-verbose-app custom --name verbose --data on
$ nsolid-cli --app my-verbose-app custom --name verbose --data off
This will allow multiple instances of the app to respond 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 select security-related policies to help harden your application. These currently 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 Resources
N|Solid includes the ability to disable core modules with a policy file. This can be used to restrict access to system resources or features that should not be used by your application.
Modules and bindings are the two types of core resources that can be disabled:
- 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. 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
}
}
}
The policy file can also be used to restrict access to bindings. The example policy file above disables both the dns
module and the cares_wrap
binding, 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.
Using A Policy File
A DNS connection is made in a separate file, faux-dns.js. To implement the above policy file, disable-dns-all.policy.json, enter the following command. Note the printed result:
$ 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
Example: Restricting Access to Modules and Bindings
The cares_wrap
binding can be used directly for DNS access. We will invoke it and restrict access with a policy file.
# fauxdns.js
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;
}
Call the function:
# lookup.js
var look = require("./fauxdns.js");
look("nodesource.com", function (err, data) {
console.log(data);
});
Without a policy file in place, you still have access to the network via the dns
module:
$ nsolid lookup.js
[ '162.243.142.64' ]
Create a policy file that prevents just the dns
module:
# disable_dns.js
{
"blacklist": {
"modules": {
"dns": 2
}
}
But, we still have DNS access:
$ nsolid --policies disable_dns.js lookup.js
[ '162.243.142.64' ]
To prevent the circumvention of the modulesBlacklist
, we need to blacklist the cares_wrap
binding directly:
# disable_cares.json
{
"blacklist": {
"bindings": {
"cares_wrap": 2
}
}
}
The behavior is now 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/user/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/user/develop/nodesource/policies/fauxdns.js:7:13)
at Object.<anonymous> (/Users/user/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
More Policy Usage
Example: Disabling A Child Process
In this example we will blacklist the child_process
module with severity level 2
.
# disable_childprocess.json
{
"blacklist": {
"modules": {
"child_process": 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/user/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/user/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
JSON Comments
To be able to include comments in your JSON files, N|Solid ignores properties whose keys start with "//".
{
"//this": "is an N|Solid JSON comment"
}
N|Solid Policies and Security
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 in the dns
and cares_wrap
example. Compiled add-ons have complete freedom to insert new functionality that can replace anything that has been disabled.
N|Solid's policy 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.
Invalid Policies
Anytime an unexpected property or a property with an invalid value is encountered, the policies are considered invalid and the process is halted.
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 |
assert |
Used for writing unit tests for your applications, you can access it with require('assert') |
async_hooks |
Provides an API to register callbacks tracking the lifetime of asynchronous resources |
buffer |
Raw data is stored in instances of the Buffer class |
bootstrap_node |
Bootstraps the Node.js core, with a special eye on performance |
child_process |
Provides a tri-directional popen(3) facility in order to create a child process |
cluster |
Allows you to easily create child processes that all share server ports |
console |
Console object is a special instance of Console whose output is sent to stdout or stderr |
constants |
Deprecated way of accessing constant values. Updated: require('someModule').constants |
crypto |
Crypto module offers a way of encapsulating secure credentials to be used as part of a secure HTTPS net or HTTP connection |
dgram |
Provides Datagram sockets |
dns |
Provides name resolution |
domain |
Pending deprecation - provide a way to handle multiple different IO operations as a single group |
encoding |
Converts strings from one encoding to another |
errors |
Provides an API for handling errors |
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 |
http2 |
Provides ability to create HTTP2 servers and clients |
https |
Provides ability to create HTTPS 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 |
inspector |
Provides an API for interacting with the V8 inspector |
inspector_async_hook |
Registers async hooks with the V8 inspector |
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 |
perf_hooks |
Supports collection of high resolution performance metrics |
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 |
socket_list |
Provides a way to monitor socket connections |
stream |
Provides streaming functionality |
_stream_duplex |
Provides the DuplexStream exposed via the stream module |
_stream_passthrough |
Provides the PassThroughStream exposed via the stream module |
_stream_readable |
Provides the ReadableStream exposed via the stream module |
_stream_transform |
Provides the TransformStream exposed via the stream module |
_stream_wrap |
Provides the wrapper to the libuv stream implementation, mostly used internally |
_stream_writable |
Provides the WritableStream exposed via the stream module |
string_decoder |
Decodes a buffer to a string with utf8 support |
sys |
Deprecated 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 compile and run code immediately, or compile, save, and run code later |
wrap_js_stream |
Provides an interface for the C++ side of Node and a standard JS stream |
zlib |
Provides bindings to Gzip/Gunzip |
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 |
config |
Build configuration |
constants |
Provides access to C++ constants |
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 |
icu |
Internationalization API and database |
inspector |
Provides the source code for the --inspect debug tooling |
js_stream |
Binding that provides support for Node.js streams |
os |
Interface to libuv in order to obtain process state information |
performance |
Provides the code for the perf_hooks module |
pipe_wrap |
Wraps libuv's socket implementation |
process_wrap |
Provides process functionality such as spawning child processes |
serdes |
Polyfill for the Node.js 8.x serializer API |
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 |
url |
WhatWG URL parser |
util |
Backing code for Node's util module |
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 |