n8n-nodes-tenable 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -0
- package/dist/credentials/TenableApi.credentials.d.ts +9 -0
- package/dist/credentials/TenableApi.credentials.js +52 -0
- package/dist/nodes/Tenable/GenericFunctions.d.ts +4 -0
- package/dist/nodes/Tenable/GenericFunctions.js +62 -0
- package/dist/nodes/Tenable/TenableOne.node.d.ts +5 -0
- package/dist/nodes/Tenable/TenableOne.node.js +658 -0
- package/dist/nodes/Tenable/TenableVulnerabilityManagement.node.d.ts +14 -0
- package/dist/nodes/Tenable/TenableVulnerabilityManagement.node.js +1288 -0
- package/dist/nodes/Tenable/tenable.png +0 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# n8n-nodes-tenable
|
|
2
|
+
|
|
3
|
+
This package provides n8n community nodes for interacting with Tenable APIs:
|
|
4
|
+
|
|
5
|
+
- **Tenable Vulnerability Management** - Full-featured node for vulnerability scanning, asset management, and security assessments
|
|
6
|
+
- **Tenable One** - Node for Tenable One Exposure Management platform
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
### Community Nodes (Recommended)
|
|
11
|
+
|
|
12
|
+
1. Go to **Settings > Community Nodes**
|
|
13
|
+
2. Select **Install**
|
|
14
|
+
3. Enter `n8n-nodes-tenable`
|
|
15
|
+
4. Agree to the risks and select **Install**
|
|
16
|
+
|
|
17
|
+
### Manual Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install n8n-nodes-tenable
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Credentials
|
|
24
|
+
|
|
25
|
+
Both nodes use the same Tenable API credentials:
|
|
26
|
+
|
|
27
|
+
1. In n8n, go to **Credentials > New**
|
|
28
|
+
2. Search for "Tenable API"
|
|
29
|
+
3. Enter your Tenable API credentials:
|
|
30
|
+
- **Access Key**: Your Tenable API access key
|
|
31
|
+
- **Secret Key**: Your Tenable API secret key
|
|
32
|
+
- **Base URL**: Usually `https://cloud.tenable.com`
|
|
33
|
+
|
|
34
|
+
To generate API keys, go to your Tenable.io account settings.
|
|
35
|
+
|
|
36
|
+
## Tenable Vulnerability Management Node
|
|
37
|
+
|
|
38
|
+
### Resources & Operations
|
|
39
|
+
|
|
40
|
+
#### Scan
|
|
41
|
+
- **Create** - Create a new scan configuration
|
|
42
|
+
- **Delete** - Delete a scan
|
|
43
|
+
- **Get** - Get scan details
|
|
44
|
+
- **Get Many** - List all scans
|
|
45
|
+
- **Launch** - Launch a scan
|
|
46
|
+
- **Pause** - Pause a running scan
|
|
47
|
+
- **Resume** - Resume a paused scan
|
|
48
|
+
- **Stop** - Stop a running scan
|
|
49
|
+
|
|
50
|
+
#### Asset
|
|
51
|
+
- **Get** - Get asset details
|
|
52
|
+
- **Get Many** - List all assets
|
|
53
|
+
- **Import** - Import assets
|
|
54
|
+
|
|
55
|
+
#### Export
|
|
56
|
+
- **Start Assets Export** - Start an assets export job
|
|
57
|
+
- **Start Vulnerabilities Export** - Start a vulnerabilities export job
|
|
58
|
+
- **Start Compliance Export** - Start a compliance export job
|
|
59
|
+
- **Get Status** - Get export job status
|
|
60
|
+
- **Cancel** - Cancel an export job
|
|
61
|
+
- **Download Chunk** - Download an export chunk
|
|
62
|
+
|
|
63
|
+
#### Folder
|
|
64
|
+
- **Create** - Create a folder
|
|
65
|
+
- **Delete** - Delete a folder
|
|
66
|
+
- **Get Many** - List all folders
|
|
67
|
+
- **Update** - Rename a folder
|
|
68
|
+
|
|
69
|
+
#### Plugin
|
|
70
|
+
- **Get** - Get plugin details
|
|
71
|
+
- **Get Families** - List all plugin families
|
|
72
|
+
- **Get Family Plugins** - List plugins in a family
|
|
73
|
+
|
|
74
|
+
#### Policy
|
|
75
|
+
- **Copy** - Copy a policy
|
|
76
|
+
- **Create** - Create a policy
|
|
77
|
+
- **Delete** - Delete a policy
|
|
78
|
+
- **Get** - Get policy details
|
|
79
|
+
- **Get Many** - List all policies
|
|
80
|
+
|
|
81
|
+
#### Vulnerability
|
|
82
|
+
- **Get Many** - List vulnerabilities
|
|
83
|
+
|
|
84
|
+
#### Workbench
|
|
85
|
+
- **Get Assets** - Get assets from workbench
|
|
86
|
+
- **Get Asset Info** - Get detailed asset information
|
|
87
|
+
- **Get Asset Vulnerabilities** - Get vulnerabilities for an asset
|
|
88
|
+
- **Get Vulnerabilities** - Get vulnerabilities from workbench
|
|
89
|
+
|
|
90
|
+
## Tenable One Node
|
|
91
|
+
|
|
92
|
+
### Resources & Operations
|
|
93
|
+
|
|
94
|
+
#### Attack Path
|
|
95
|
+
- **Search Attack Paths** - Search for top attack paths
|
|
96
|
+
- **Search Attack Techniques** - Search for top attack techniques (MITRE ATT&CK)
|
|
97
|
+
|
|
98
|
+
#### Exposure View
|
|
99
|
+
- **Get Cards** - Get all exposure view cards
|
|
100
|
+
- **Get Card** - Get a specific card
|
|
101
|
+
|
|
102
|
+
#### Inventory
|
|
103
|
+
- **Search Assets** - Search for assets
|
|
104
|
+
- **Search Findings** - Search for findings
|
|
105
|
+
- **Search Software** - Search for software
|
|
106
|
+
- **Get Asset Properties** - Get available asset properties for filtering
|
|
107
|
+
- **Get Finding Properties** - Get available finding properties
|
|
108
|
+
- **Get Software Properties** - Get available software properties
|
|
109
|
+
|
|
110
|
+
#### Inventory Export
|
|
111
|
+
- **Start Assets Export** - Start an assets export
|
|
112
|
+
- **Start Findings Export** - Start a findings export
|
|
113
|
+
- **Get Status** - Get export status
|
|
114
|
+
- **Get Export Status** - Get specific export status
|
|
115
|
+
- **Download Chunk** - Download an export chunk
|
|
116
|
+
|
|
117
|
+
#### Tag
|
|
118
|
+
- **Search** - Search for tags
|
|
119
|
+
- **Get Properties** - Get available tag properties
|
|
120
|
+
|
|
121
|
+
## Query Examples
|
|
122
|
+
|
|
123
|
+
### Tenable One Inventory Search (Advanced Mode)
|
|
124
|
+
|
|
125
|
+
Find cloud assets with critical vulnerabilities:
|
|
126
|
+
```
|
|
127
|
+
Assets HAS sources = "CLOUD" WITH Weakness HAS severity = "Critical"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Find assets with high AES score:
|
|
131
|
+
```
|
|
132
|
+
Assets HAS aes >= 700
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## License
|
|
136
|
+
|
|
137
|
+
MIT
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
export declare class TenableApi implements ICredentialType {
|
|
3
|
+
name: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
documentationUrl: string;
|
|
6
|
+
properties: INodeProperties[];
|
|
7
|
+
authenticate: IAuthenticateGeneric;
|
|
8
|
+
test: ICredentialTestRequest;
|
|
9
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TenableApi = void 0;
|
|
4
|
+
class TenableApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'tenableApi';
|
|
7
|
+
this.displayName = 'Tenable API';
|
|
8
|
+
this.documentationUrl = 'https://developer.tenable.com/docs/authorization';
|
|
9
|
+
this.properties = [
|
|
10
|
+
{
|
|
11
|
+
displayName: 'Access Key',
|
|
12
|
+
name: 'accessKey',
|
|
13
|
+
type: 'string',
|
|
14
|
+
typeOptions: { password: true },
|
|
15
|
+
default: '',
|
|
16
|
+
required: true,
|
|
17
|
+
description: 'Your Tenable API access key',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
displayName: 'Secret Key',
|
|
21
|
+
name: 'secretKey',
|
|
22
|
+
type: 'string',
|
|
23
|
+
typeOptions: { password: true },
|
|
24
|
+
default: '',
|
|
25
|
+
required: true,
|
|
26
|
+
description: 'Your Tenable API secret key',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
displayName: 'Base URL',
|
|
30
|
+
name: 'baseUrl',
|
|
31
|
+
type: 'string',
|
|
32
|
+
default: 'https://cloud.tenable.com',
|
|
33
|
+
description: 'The base URL for your Tenable instance',
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
this.authenticate = {
|
|
37
|
+
type: 'generic',
|
|
38
|
+
properties: {
|
|
39
|
+
headers: {
|
|
40
|
+
'X-ApiKeys': '=accessKey={{$credentials.accessKey}};secretKey={{$credentials.secretKey}}',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
this.test = {
|
|
45
|
+
request: {
|
|
46
|
+
baseURL: '={{$credentials.baseUrl}}',
|
|
47
|
+
url: '/folders',
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.TenableApi = TenableApi;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IDataObject, IExecuteFunctions, IHttpRequestMethods, ILoadOptionsFunctions } from 'n8n-workflow';
|
|
2
|
+
export declare function tenableApiRequest(this: IExecuteFunctions | ILoadOptionsFunctions, method: IHttpRequestMethods, endpoint: string, body?: IDataObject, qs?: IDataObject): Promise<IDataObject | IDataObject[]>;
|
|
3
|
+
export declare function tenableApiRequestAllItems(this: IExecuteFunctions | ILoadOptionsFunctions, method: IHttpRequestMethods, endpoint: string, propertyName: string, body?: IDataObject, qs?: IDataObject): Promise<IDataObject[]>;
|
|
4
|
+
export declare function validateJSON(json: string | undefined): IDataObject | undefined;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tenableApiRequest = tenableApiRequest;
|
|
4
|
+
exports.tenableApiRequestAllItems = tenableApiRequestAllItems;
|
|
5
|
+
exports.validateJSON = validateJSON;
|
|
6
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
7
|
+
async function tenableApiRequest(method, endpoint, body = {}, qs = {}) {
|
|
8
|
+
const credentials = await this.getCredentials('tenableApi');
|
|
9
|
+
const options = {
|
|
10
|
+
method,
|
|
11
|
+
url: `${credentials.baseUrl}${endpoint}`,
|
|
12
|
+
headers: {
|
|
13
|
+
'Accept': 'application/json',
|
|
14
|
+
'Content-Type': 'application/json',
|
|
15
|
+
},
|
|
16
|
+
qs,
|
|
17
|
+
body,
|
|
18
|
+
json: true,
|
|
19
|
+
};
|
|
20
|
+
if (Object.keys(body).length === 0) {
|
|
21
|
+
delete options.body;
|
|
22
|
+
}
|
|
23
|
+
if (Object.keys(qs).length === 0) {
|
|
24
|
+
delete options.qs;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'tenableApi', options);
|
|
28
|
+
return response;
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function tenableApiRequestAllItems(method, endpoint, propertyName, body = {}, qs = {}) {
|
|
35
|
+
const returnData = [];
|
|
36
|
+
let responseData;
|
|
37
|
+
let offset = 0;
|
|
38
|
+
const limit = 100;
|
|
39
|
+
do {
|
|
40
|
+
qs.offset = offset;
|
|
41
|
+
qs.limit = limit;
|
|
42
|
+
responseData = (await tenableApiRequest.call(this, method, endpoint, body, qs));
|
|
43
|
+
const items = responseData[propertyName];
|
|
44
|
+
if (items) {
|
|
45
|
+
returnData.push(...items);
|
|
46
|
+
}
|
|
47
|
+
offset += limit;
|
|
48
|
+
} while (responseData[propertyName] &&
|
|
49
|
+
responseData[propertyName].length === limit);
|
|
50
|
+
return returnData;
|
|
51
|
+
}
|
|
52
|
+
function validateJSON(json) {
|
|
53
|
+
if (json === undefined || json === '') {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
return JSON.parse(json);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
|
|
2
|
+
export declare class TenableOne implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
5
|
+
}
|