appdynamics 21.9.0 → 22.5.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/appdynamics_version.json +2 -2
- package/lib/core/agent.js +22 -0
- package/lib/core/appDProxy.js +12 -12
- package/lib/core/logger.js +27 -79
- package/lib/core/opentelemetry-tracer.js +97 -0
- package/lib/libagent/libagent-connector.js +24 -0
- package/lib/libagent/libagent.js +2 -1
- package/lib/libagent/transaction-sender.js +14 -13
- package/lib/probes/apollo-entry-probe.js +69 -0
- package/lib/probes/couchbase-probe.js +19 -0
- package/lib/probes/grpc-exit-probe.js +1 -1
- package/lib/probes/http-common.js +97 -0
- package/lib/probes/http-entry-probe.js +42 -116
- package/lib/probes/http-exit-probe.js +93 -31
- package/lib/probes/http-ot-utils.js +117 -0
- package/lib/probes/http-probe.js +14 -7
- package/lib/probes/mongodb-probe.js +200 -113
- package/lib/profiler/profiler.js +5 -1
- package/lib/secure_app/library_metadata.js +56 -0
- package/lib/secure_app/secure_app.js +276 -0
- package/lib/utility.js +20 -1
- package/package.json +13 -8
- package/packageBck.json +13 -8
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
const http = require('http');
|
|
2
|
+
const https = require('https');
|
|
3
|
+
const url = require('url');
|
|
4
|
+
const HttpsProxyAgent = require('https-proxy-agent');
|
|
5
|
+
|
|
6
|
+
const LibraryMetadata = require('./library_metadata').LibraryMetadata;
|
|
7
|
+
const MessageSender = require('../libagent/message-sender').MessageSender;
|
|
8
|
+
|
|
9
|
+
const AUTH_PATH = "/auth/v1/oauth/token";
|
|
10
|
+
const EVENT_PATH = "/argento-agent/v1/report";
|
|
11
|
+
const REGISTER_PATH = "/argento-agent/v1/management";
|
|
12
|
+
|
|
13
|
+
const MIN_TIMER = 60 * 1000;
|
|
14
|
+
const DAY_TIMER = 24 * 60 * 60 * 1000;
|
|
15
|
+
|
|
16
|
+
exports.SecureApp = SecureApp;
|
|
17
|
+
function SecureApp() {
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
SecureApp.prototype.init = function(agent) {
|
|
21
|
+
var self = this;
|
|
22
|
+
self.agent = agent;
|
|
23
|
+
self.libraryMetadata = new LibraryMetadata(agent);
|
|
24
|
+
if(!process.env.SKIP_AUTH_FOR_TESTS) {
|
|
25
|
+
self.authTimerId = new MessageSender(self.agent, 10 * 1000, MIN_TIMER * 9, function () {
|
|
26
|
+
self.authToken();
|
|
27
|
+
});
|
|
28
|
+
} else {
|
|
29
|
+
self.agent.logger.debug('Secure App skipping auth as SKIP_AUTH_FOR_TESTS is ' + process.env.SKIP_AUTH_FOR_TESTS);
|
|
30
|
+
self.regTimerId = new MessageSender(self.agent, 10 * 1000, MIN_TIMER, function () {
|
|
31
|
+
self.register();
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
self.httpModule = (self.agent.opts.controllerSslEnabled) ? https : http;
|
|
35
|
+
self.libraryMetadata.init();
|
|
36
|
+
self.agent.logger.debug('Secure App module initialized');
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
SecureApp.prototype._sendRequest = function(options, data, cb) {
|
|
40
|
+
var self = this;
|
|
41
|
+
self.agent.logger.trace('SecureApp._sendRequest: ' + options.path + " Data: " + ((options.headers['Content-Type'] != 'application/json') ?
|
|
42
|
+
data.length.toString() : JSON.stringify(data).length.toString()));
|
|
43
|
+
|
|
44
|
+
var request = self.httpModule.request(options, function(response) {
|
|
45
|
+
cb(request, response);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
request.on('error', function(error) {
|
|
49
|
+
self.agent.logger.info('Secure app http request error : ' + error);
|
|
50
|
+
});
|
|
51
|
+
request.end(data);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
SecureApp.prototype._requestHeaders = function(requestOptions) {
|
|
55
|
+
var self = this;
|
|
56
|
+
requestOptions.headers['Authorization'] = `Bearer ${self.accessToken}`;
|
|
57
|
+
requestOptions.headers['User-Agent'] = "NodeJs";
|
|
58
|
+
requestOptions.headers['appdynamics-agent-applicationName'] = self.agent.opts.applicationName;
|
|
59
|
+
requestOptions.headers['appdynamics-agent-tierName'] = self.agent.opts.tierName;
|
|
60
|
+
requestOptions.headers['appdynamics-agent-nodeName'] = self.agent.opts.nodeName;
|
|
61
|
+
requestOptions.headers['appdynamics-agent-accountName'] = 'singularity-agent@' + self.agent.opts.accountName;
|
|
62
|
+
if (self.uuid) {
|
|
63
|
+
requestOptions.headers['appdynamics-agent-nodeUUID'] = self.uuid;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
SecureApp.prototype._requestOptions = function(path, length, type) {
|
|
68
|
+
var self = this;
|
|
69
|
+
var requestOptions = {
|
|
70
|
+
'method': 'POST',
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
requestOptions.headers = {
|
|
74
|
+
'Content-Length': length,
|
|
75
|
+
'Content-Type': type
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
if (self.agent.opts.certificateFile) {
|
|
79
|
+
requestOptions['ca'] = self.agent.opts.certificateFile;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if(process.env.CONTROLLER_HOST_TEST) {
|
|
83
|
+
self.agent.logger.debug('Secure App using controller hostname CONTROLLER_HOST_TEST: ' + process.env.CONTROLLER_HOST_TEST);
|
|
84
|
+
requestOptions['hostname'] = process.env.CONTROLLER_HOST_TEST;
|
|
85
|
+
} else {
|
|
86
|
+
requestOptions['hostname'] = self.agent.opts.controllerHostName;
|
|
87
|
+
}
|
|
88
|
+
if(process.env.CONTROLLER_PORT_TEST) {
|
|
89
|
+
self.agent.logger.debug('Secure App using controller port CONTROLLER_PORT_TEST: ' + process.env.CONTROLLER_PORT_TEST);
|
|
90
|
+
requestOptions['port'] = process.env.CONTROLLER_PORT_TEST;
|
|
91
|
+
} else {
|
|
92
|
+
requestOptions['port'] = self.agent.opts.controllerPort;
|
|
93
|
+
}
|
|
94
|
+
requestOptions['path'] = path;
|
|
95
|
+
|
|
96
|
+
var proxy = {
|
|
97
|
+
hostName: self.agent.opts.proxyHost,
|
|
98
|
+
port: self.agent.opts.proxyPort,
|
|
99
|
+
userName: self.agent.opts.proxyUser,
|
|
100
|
+
password: ""
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
if (self.agent.opts.proxyPasswordFile) {
|
|
104
|
+
var fs = require('fs');
|
|
105
|
+
proxy.password = (fs.readFileSync(self.agent.opts.proxyPasswordFile, 'utf-8')).trim();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (proxy.hostName) {
|
|
109
|
+
self.agent.logger.debug('Secure App using proxy');
|
|
110
|
+
var ro = requestOptions;
|
|
111
|
+
var proxyAuth = proxy.userName && proxy.password && Buffer.from(`${proxy.userName}:${proxy.password}`).toString('base64');
|
|
112
|
+
|
|
113
|
+
if (self.agent.opts.controllerSslEnabled) {
|
|
114
|
+
var proxyUrl = `http://${proxy.hostName}:${proxy.port}`;
|
|
115
|
+
var proxyOpts = url.parse(proxyUrl);
|
|
116
|
+
if (proxyAuth) {
|
|
117
|
+
proxyOpts.headers = {
|
|
118
|
+
'Proxy-Authentication': `Basic ${proxyAuth}`
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
var agent = new HttpsProxyAgent(proxyOpts);
|
|
122
|
+
ro['agent'] = agent;
|
|
123
|
+
} else {
|
|
124
|
+
ro['path'] = `http://${ro.hostname}:${ro.port}${ro.path}`;
|
|
125
|
+
ro['headers']['Host'] = `${ro.hostname}:${ro.port}`;
|
|
126
|
+
ro['hostname'] = proxy.hostName;
|
|
127
|
+
ro['port'] = proxy.port;
|
|
128
|
+
if (proxyAuth) {
|
|
129
|
+
ro['headers']['Proxy-Authorization'] = `Basic ${proxyAuth}`;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return requestOptions;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
SecureApp.prototype._initializeTimers = function() {
|
|
137
|
+
var self = this;
|
|
138
|
+
if (self.timersInitialized) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
self.timersInitialized = true;
|
|
142
|
+
|
|
143
|
+
self.reportEventTimerId = new MessageSender(self.agent, 10 * 1000, DAY_TIMER, function () {
|
|
144
|
+
self.reportEvents();
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
SecureApp.prototype.authenticate = function(grantType) {
|
|
149
|
+
var self = this;
|
|
150
|
+
var postData = "password=" + self.agent.opts.accountAccessKey +
|
|
151
|
+
"&username=" + 'singularity-agent@' + self.agent.opts.accountName +
|
|
152
|
+
"&grant_type=" + grantType;
|
|
153
|
+
|
|
154
|
+
if(grantType == 'refresh_token') {
|
|
155
|
+
postData += '&refresh_token=' + self.refreshToken;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
var requestOptions = self._requestOptions(AUTH_PATH, postData.length.toString(),
|
|
159
|
+
"application/x-www-form-urlencoded; charset=utf-8");
|
|
160
|
+
|
|
161
|
+
self._sendRequest(requestOptions, postData, function(request, response) {
|
|
162
|
+
var statusCode = response.statusCode | 0;
|
|
163
|
+
if (statusCode != 200 || response.is_error) {
|
|
164
|
+
self.agent.logger.info('Secure App authentication failed');
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const chunks = [];
|
|
169
|
+
response.on('data', data => chunks.push(data));
|
|
170
|
+
response.on('end', () => {
|
|
171
|
+
let body = Buffer.concat(chunks);
|
|
172
|
+
body = JSON.parse(body);
|
|
173
|
+
if (!self.accessToken) {
|
|
174
|
+
self.regTimerId = new MessageSender(self.agent, 10 * 1000, MIN_TIMER, function () {
|
|
175
|
+
self.register();
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
self.accessToken = body.access_token;
|
|
180
|
+
self.refreshToken = body.refresh_token;
|
|
181
|
+
|
|
182
|
+
self.agent.logger.debug('Secure App module authenticated');
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
SecureApp.prototype.authToken = function() {
|
|
188
|
+
var self = this;
|
|
189
|
+
if(!self.accessToken) {
|
|
190
|
+
self.authenticate("password");
|
|
191
|
+
} else {
|
|
192
|
+
self.authenticate("refresh_token");
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
SecureApp.prototype.register = function() {
|
|
197
|
+
var self = this;
|
|
198
|
+
var postData = JSON.stringify({
|
|
199
|
+
"message_type": 0,
|
|
200
|
+
"app": self.agent.opts.applicationName,
|
|
201
|
+
"tier": self.agent.opts.tierName,
|
|
202
|
+
"node": self.agent.opts.nodeName,
|
|
203
|
+
"access_key": self.agent.opts.accountAccessKey,
|
|
204
|
+
"account_name": self.agent.opts.accountName,
|
|
205
|
+
"file_name": "",
|
|
206
|
+
"epoch_msec": 0,
|
|
207
|
+
"force": false,
|
|
208
|
+
"version": 1,
|
|
209
|
+
"is_started": true,
|
|
210
|
+
"is_enabled": true,
|
|
211
|
+
"agent_type": "NodeJs",
|
|
212
|
+
"agent_build_version": ""
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
var requestOptions = self._requestOptions(REGISTER_PATH, postData.length.toString(), "application/json");
|
|
216
|
+
self._requestHeaders(requestOptions);
|
|
217
|
+
|
|
218
|
+
self._sendRequest(requestOptions, postData, function(request, response) {
|
|
219
|
+
var statusCode = response.statusCode | 0;
|
|
220
|
+
if (statusCode != 200 || response.is_error) {
|
|
221
|
+
self.agent.logger.info('Secure App module registeration failed');
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const chunks = [];
|
|
225
|
+
response.on('data', data => chunks.push(data));
|
|
226
|
+
response.on('end', () => {
|
|
227
|
+
let body = Buffer.concat(chunks);
|
|
228
|
+
body = JSON.parse(body);
|
|
229
|
+
self.uuid = body.node_uuid;
|
|
230
|
+
self._initializeTimers();
|
|
231
|
+
self.agent.logger.debug('Secure App module registered');
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
SecureApp.prototype.sendVulnerabilityEvent = function() {
|
|
237
|
+
var self = this;
|
|
238
|
+
if(!self.vulnerabilityEvent) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
self.vulnerabilityEvent.forEach((data, index) => {
|
|
243
|
+
var isDone = index == self.vulnerabilityEvent.length - 1 ? true : false;
|
|
244
|
+
var postData = JSON.stringify({
|
|
245
|
+
"id": 0,
|
|
246
|
+
"is_done": isDone,
|
|
247
|
+
"fragment_index": index,
|
|
248
|
+
"max_fragments": self.vulnerabilityEvent.length,
|
|
249
|
+
"nodejs_report_component_vulnerability_list": data
|
|
250
|
+
});
|
|
251
|
+
var requestOptions = self._requestOptions(EVENT_PATH, postData.length.toString(), "application/json");
|
|
252
|
+
self._requestHeaders(requestOptions);
|
|
253
|
+
|
|
254
|
+
self._sendRequest(requestOptions, postData, function(request, response) {
|
|
255
|
+
var statusCode = response.statusCode | 0;
|
|
256
|
+
if (statusCode != 200 || response.is_error) {
|
|
257
|
+
self.agent.logger.info('Secure App module vulnerability event failed');
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const chunks = [];
|
|
262
|
+
response.on('data', data => chunks.push(data));
|
|
263
|
+
response.on('end', () => {
|
|
264
|
+
self.agent.logger.info('Secure App module vulnerability event sent fragment');
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
SecureApp.prototype.reportEvents = function() {
|
|
271
|
+
var self = this;
|
|
272
|
+
if(!self.vulnerabilityEvent) {
|
|
273
|
+
self.vulnerabilityEvent = self.libraryMetadata.getMetadata();
|
|
274
|
+
}
|
|
275
|
+
self.sendVulnerabilityEvent();
|
|
276
|
+
};
|
package/lib/utility.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
var url = require('url');
|
|
2
|
+
|
|
3
|
+
|
|
1
4
|
function filterSensitiveDataFromObject(objIns) {
|
|
2
5
|
if (objIns && Object.prototype.toString.call(objIns) == "[object Object]") {
|
|
3
6
|
Object.keys(objIns).forEach(function (key) {
|
|
@@ -21,5 +24,21 @@ function deepCopy(origObject) {
|
|
|
21
24
|
return cpObj;
|
|
22
25
|
}
|
|
23
26
|
|
|
27
|
+
function createBtNamingWrapper(req) {
|
|
28
|
+
// TODO: replace these with boost::regex in libagent bindings
|
|
29
|
+
if (req.url) {
|
|
30
|
+
var parsedUrl = url.parse(req.url);
|
|
31
|
+
req.parsedPathName = parsedUrl.pathname;
|
|
32
|
+
req.parsedParameterString = parsedUrl.query;
|
|
33
|
+
}
|
|
34
|
+
return req;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const constants = {
|
|
38
|
+
GRAPHQL_QUERY_TYPE: "gql"
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
module.exports.createBtNamingWrapper = createBtNamingWrapper;
|
|
24
42
|
module.exports.filterSensitiveDataFromObject = filterSensitiveDataFromObject;
|
|
25
|
-
module.exports.deepCopy = deepCopy;
|
|
43
|
+
module.exports.deepCopy = deepCopy;
|
|
44
|
+
module.exports.constants = constants;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appdynamics",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "22.5.0",
|
|
4
4
|
"description": "Performance Profiler and Monitor",
|
|
5
5
|
"author": "AppDynamics, Inc.",
|
|
6
6
|
"homepage": "https://www.appdynamics.com",
|
|
@@ -34,15 +34,20 @@
|
|
|
34
34
|
"n": "^6.7.0"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
+
"@opentelemetry/api": "~1.0.3",
|
|
38
|
+
"@opentelemetry/context-async-hooks": "~1.0.1",
|
|
39
|
+
"@opentelemetry/core": "~1.0.1",
|
|
40
|
+
"@opentelemetry/exporter-trace-otlp-proto": "~0.27.0",
|
|
41
|
+
"@opentelemetry/resources": "~1.0.1",
|
|
42
|
+
"@opentelemetry/sdk-trace-base": "~1.0.1",
|
|
43
|
+
"@opentelemetry/semantic-conventions": "~1.0.1",
|
|
37
44
|
"cls-hooked": "4.2.2",
|
|
38
|
-
"
|
|
39
|
-
"n": "^6.7.0",
|
|
40
|
-
"set-immediate": "0.1.1",
|
|
41
|
-
"shelljs": "^0.8.4",
|
|
45
|
+
"https-proxy-agent": "^5.0.0",
|
|
42
46
|
"uuid": "^8.3.2",
|
|
43
|
-
"
|
|
44
|
-
"appdynamics-
|
|
45
|
-
"appdynamics-
|
|
47
|
+
"y18n": "^5.0.8",
|
|
48
|
+
"appdynamics-libagent-napi": "https://cdn.appdynamics.com/packages/nodejs/22.5.0.0/appdynamics-libagent-napi-node.tgz",
|
|
49
|
+
"appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/22.5.0.0/appdynamics-native-node.tgz",
|
|
50
|
+
"appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/22.5.0.0/appdynamics-protobuf-node.tgz"
|
|
46
51
|
},
|
|
47
52
|
"engines": {
|
|
48
53
|
"node": ">=12 <=v16.*"
|
package/packageBck.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appdynamics",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "22.5.0",
|
|
4
4
|
"description": "Performance Profiler and Monitor",
|
|
5
5
|
"author": "AppDynamics, Inc.",
|
|
6
6
|
"homepage": "https://www.appdynamics.com",
|
|
@@ -34,15 +34,20 @@
|
|
|
34
34
|
"n": "^6.7.0"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
+
"@opentelemetry/api": "~1.0.3",
|
|
38
|
+
"@opentelemetry/context-async-hooks": "~1.0.1",
|
|
39
|
+
"@opentelemetry/core": "~1.0.1",
|
|
40
|
+
"@opentelemetry/exporter-trace-otlp-proto": "~0.27.0",
|
|
41
|
+
"@opentelemetry/resources": "~1.0.1",
|
|
42
|
+
"@opentelemetry/sdk-trace-base": "~1.0.1",
|
|
43
|
+
"@opentelemetry/semantic-conventions": "~1.0.1",
|
|
37
44
|
"cls-hooked": "4.2.2",
|
|
38
|
-
"
|
|
39
|
-
"n": "^6.7.0",
|
|
40
|
-
"set-immediate": "0.1.1",
|
|
41
|
-
"shelljs": "^0.8.4",
|
|
45
|
+
"https-proxy-agent": "^5.0.0",
|
|
42
46
|
"uuid": "^8.3.2",
|
|
43
|
-
"
|
|
44
|
-
"appdynamics-
|
|
45
|
-
"appdynamics-
|
|
47
|
+
"y18n": "^5.0.8",
|
|
48
|
+
"appdynamics-libagent-napi": "https://cdn.appdynamics.com/packages/nodejs/22.5.0.0/appdynamics-libagent-napi-node.tgz",
|
|
49
|
+
"appdynamics-native": "https://cdn.appdynamics.com/packages/nodejs/22.5.0.0/appdynamics-native-node.tgz",
|
|
50
|
+
"appdynamics-protobuf": "https://cdn.appdynamics.com/packages/nodejs/22.5.0.0/appdynamics-protobuf-node.tgz"
|
|
46
51
|
},
|
|
47
52
|
"engines": {
|
|
48
53
|
"node": ">=12 <=v16.*"
|