Skip to content
This repository was archived by the owner on Nov 15, 2024. It is now read-only.

Commit d28fdc8

Browse files
committed
https://issues.newrelic.com/browse/NR-1007: /no-auth/nr-ingest-key endpoint
1 parent 4fd226a commit d28fdc8

File tree

6 files changed

+138
-1
lines changed

6 files changed

+138
-1
lines changed

api_server/modules/analytics/analytics.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ class Analytics extends APIServerModule {
8686
}
8787
};
8888
}
89-
9089
}
9190

9291
module.exports = Analytics;

api_server/modules/newrelic/newrelic_auth.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,26 @@ const OAUTH_CONFIG = {
1111
needsConfigure: true
1212
};
1313

14+
const ROUTES = [
15+
{
16+
method: 'get',
17+
path: '/no-auth/nr-ingest-key',
18+
func: 'handleNRIngestKey',
19+
describe: 'describeNRIngestKey'
20+
}
21+
];
22+
1423
class NewRelicAuth extends OAuthModule {
1524

1625
constructor (config) {
1726
super(config);
1827
this.oauthConfig = OAUTH_CONFIG;
1928
}
2029

30+
getRoutes () {
31+
return ROUTES;
32+
}
33+
2134
async providerInfoHook (info) {
2235
if (!info.data || !info.data.accessToken || !info.teamId || !info.request) { return; }
2336

@@ -77,6 +90,41 @@ class NewRelicAuth extends OAuthModule {
7790
info.request.warn(`Could not publish company update to channel ${channel}: ${JSON.stringify(error)}`);
7891
}
7992
}
93+
94+
// handle request to fetch ingest key information for New Relic data ingest,
95+
// one level of indirection used to retrieve the keys the client will use for ingest
96+
handleNRIngestKey (request, response) {
97+
if (!request.headers['x-cs-plugin-ide']) {
98+
const error = 'IDE key not present in header';
99+
this.api.warn(error);
100+
return response.status(403).send({ error });
101+
}
102+
103+
const { browserIngestKey, licenseIngestKey, telemetryEndpoint } = this.api.config.integrations.newrelic;
104+
response.send({
105+
browserIngestKey,
106+
licenseIngestKey,
107+
telemetryEndpoint
108+
});
109+
}
110+
111+
describeIngestKey () {
112+
return {
113+
tag: 'nr-ingest-key',
114+
summary: 'Retrieve ingest key for New Relic APM',
115+
description: 'Retrieve ingest key and other info for use with New Relic application monitoring',
116+
access: 'User must provide the secret',
117+
input: 'Specify the secret in the query parameter "secret"',
118+
returns: {
119+
summary: 'The New Relic ingest key to use when initializing client-side New Relic APM',
120+
looksLike: {
121+
browserIngestKey: '<The key for browser ingest>',
122+
licenseIngestKey: '<The key for agent ingest>',
123+
telemetryEndpoint: '<Endpoint hostname for ingest collector>'
124+
}
125+
}
126+
};
127+
}
80128
}
81129

82130
module.exports = NewRelicAuth;
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// base class for all ingest key tests
2+
3+
'use strict';
4+
5+
const CodeStreamAPITest = require(process.env.CSSVC_BACKEND_ROOT + '/api_server/lib/test_base/codestream_api_test');
6+
const Assert = require('assert');
7+
8+
class IngestKeyTest extends CodeStreamAPITest {
9+
10+
constructor (options) {
11+
super(options);
12+
this.userOptions.numRegistered = 0;
13+
delete this.teamOptions.creatorIndex;
14+
}
15+
16+
get description () {
17+
return 'should send the ingest key when requested with the proper secret';
18+
}
19+
20+
get method () {
21+
return 'get';
22+
}
23+
24+
get path () {
25+
return '/no-auth/nr-ingest-key';
26+
}
27+
28+
before (callback) {
29+
super.before(error => {
30+
if (error) { return callback(error); }
31+
this.apiRequestOptions = this.apiRequestOptions || {};
32+
this.apiRequestOptions.headers = this.apiRequestOptions.headers || {};
33+
this.apiRequestOptions.headers = {
34+
'X-CS-Plugin-IDE': 'test'
35+
};
36+
callback();
37+
});
38+
}
39+
40+
// validate the response to the test request
41+
validateResponse (data) {
42+
const { browserIngestKey, licenseIngestKey, telemetryEndpoint } = this.apiConfig.integrations.newrelic;
43+
const expectedResponse = { browserIngestKey, licenseIngestKey, telemetryEndpoint };
44+
Assert.deepStrictEqual(data, expectedResponse, 'incorrect response');
45+
}
46+
}
47+
48+
module.exports = IngestKeyTest;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
'use strict';
2+
3+
const IngestKeyTest = require('./ingest_key_test');
4+
5+
class NoPluginHeaderTest extends IngestKeyTest {
6+
7+
get description () {
8+
return 'should return an error when an attempt is made to fetch the New Relic ingest key without providing the x-cs-plugin-ide header';
9+
}
10+
11+
getExpectedError () {
12+
return {
13+
error: 'IDE key not present in header'
14+
};
15+
}
16+
17+
before (callback) {
18+
super.before (error => {
19+
if (error) { return callback(error); }
20+
delete this.apiRequestOptions.headers['X-CS-Plugin-IDE'];
21+
callback();
22+
});
23+
}
24+
}
25+
26+
module.exports = NoPluginHeaderTest;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// unit tests associated with the New Relic module
2+
3+
'use strict';
4+
5+
// make eslint happy
6+
/* globals describe */
7+
8+
const IngestKeyTest = require('./ingest_key_test');
9+
const NoPluginHeaderTest = require('./no_plugin_header_test');
10+
11+
describe('new relic', function() {
12+
13+
new IngestKeyTest().test();
14+
new NoPluginHeaderTest().test();
15+
});

api_server/modules/test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ describe('modules', () => {
99
require('./authenticator/test/test.js');
1010
require('./versioner/test/test.js');
1111
require('./analytics/test/test.js');
12+
require('./newrelic/test/test.js');
1213
require('./broadcaster/test/test.js');
1314
require('./users/test/test.js');
1415
require('./providers/test/test.js');

0 commit comments

Comments
 (0)