akamai-edgegrid 3.1.2
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/.chglog/CHANGELOG.tpl.md +43 -0
- package/.chglog/config.yml +27 -0
- package/.idea/AkamaiOPEN-edgegrid-node.iml +9 -0
- package/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/.idea/jsLibraryMappings.xml +6 -0
- package/.idea/jsLinters/jshint.xml +16 -0
- package/.idea/misc.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/.jshintrc +38 -0
- package/.nyc_output/20cb1872-3da5-4e78-9ee3-a0145437983e.json +1 -0
- package/.nyc_output/6beee4d5-a8f5-4658-8bfc-a65d3b4cb6fa.json +1 -0
- package/.nyc_output/processinfo/20cb1872-3da5-4e78-9ee3-a0145437983e.json +1 -0
- package/.nyc_output/processinfo/6beee4d5-a8f5-4658-8bfc-a65d3b4cb6fa.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -0
- package/.travis.yml +5 -0
- package/CHANGELOG.md +24 -0
- package/LICENSE +191 -0
- package/README.md +210 -0
- package/edgegrid-3.1.0.tgz +0 -0
- package/index.js +2 -0
- package/package.json +36 -0
- package/src/api.js +163 -0
- package/src/auth.js +75 -0
- package/src/edgerc.js +139 -0
- package/src/helpers.js +159 -0
- package/src/logger.js +26 -0
- package/test/src/api_test.js +324 -0
- package/test/src/edgerc_test.js +154 -0
- package/test/src/helpers_test.js +127 -0
- package/test/test.js +189 -0
- package/test/test_body_data.txt +0 -0
- package/test/test_data.json +153 -0
- package/test/test_edgerc +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# EdgeGrid for Node.js
|
|
2
|
+
|
|
3
|
+
[](https://travis-ci.org/akamai/AkamaiOPEN-edgegrid-node)
|
|
4
|
+
|
|
5
|
+
This library implements an Authentication handler for the Akamai EdgeGrid Authentication scheme in Node.js.
|
|
6
|
+
|
|
7
|
+
It’s Akamai’s current and officially supported version of AkamaiOPEN EdgeGrid for Node.js.
|
|
8
|
+
You can find the most up-to-date package in [NPM](https://www.npmjs.com/package/akamai-edgegrid) under `akamai-edgegrid`.
|
|
9
|
+
|
|
10
|
+
> __IMPORTANT:__ Akamai will not maintain the `edgegrid` package in NPM going forward.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
`npm install --save akamai-edgegrid`
|
|
15
|
+
|
|
16
|
+
## Example
|
|
17
|
+
|
|
18
|
+
### Credentials
|
|
19
|
+
|
|
20
|
+
To use Akamai APIs you must first register and authorize a set of credentials through [Control Center](https://control.akamai.com). You can find more information on creating and authorizing credentials at [Authenticate with EdgeGrid](https://developer.akamai.com/getting-started/edgegrid).
|
|
21
|
+
|
|
22
|
+
### .edgerc authentication
|
|
23
|
+
|
|
24
|
+
The preferred method of using the library involves providing the path to an `.edgerc` file. This file contains the authentication credentials used to sign your requests.
|
|
25
|
+
|
|
26
|
+
> __NOTE__: Requests to the API are signed with a timestamp and are executed immediately.
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
var EdgeGrid = require('akamai-edgegrid');
|
|
30
|
+
|
|
31
|
+
var data = 'bodyData';
|
|
32
|
+
|
|
33
|
+
// Supply the path to your .edgerc file and name
|
|
34
|
+
// of the section with authorization to the client
|
|
35
|
+
// you are calling (default section is 'default')
|
|
36
|
+
var eg = new EdgeGrid({
|
|
37
|
+
path: '/path/to/.edgerc',
|
|
38
|
+
section: 'section-name'
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
eg.auth({
|
|
42
|
+
path: '/diagnostic-tools/v1/locations',
|
|
43
|
+
method: 'GET',
|
|
44
|
+
headers: {},
|
|
45
|
+
body: data
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
eg.send(function(error, response, body) {
|
|
49
|
+
console.log(body);
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
An `.edgerc` file contains sections for each of your API client credentials and is usually hosted in your home directory:
|
|
54
|
+
|
|
55
|
+
```plaintext
|
|
56
|
+
[default]
|
|
57
|
+
host = akaa-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.luna.akamaiapis.net/
|
|
58
|
+
client_token = akab-XXXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXX
|
|
59
|
+
client_secret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
60
|
+
access_token = akab-XXXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXX
|
|
61
|
+
max-body = 131072
|
|
62
|
+
|
|
63
|
+
[section-name]
|
|
64
|
+
host = akaa-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.luna.akamaiapis.net/
|
|
65
|
+
client_token = akab-XXXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXX
|
|
66
|
+
client_secret = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
67
|
+
access_token = akab-XXXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXX
|
|
68
|
+
max-body = 131072
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Manual authentication
|
|
72
|
+
|
|
73
|
+
You can also authenticate manually by hard coding your credential values and passing them to the EdgeGrid client:
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
var clientToken = "akab-client-token-xxx-xxxxxxxxxxxxxxxx",
|
|
77
|
+
clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=",
|
|
78
|
+
accessToken = "akab-access-token-xxx-xxxxxxxxxxxxxxxx",
|
|
79
|
+
baseUri = "https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/";
|
|
80
|
+
|
|
81
|
+
var eg = new EdgeGrid(clientToken, clientSecret, accessToken, baseUri);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Chaining
|
|
85
|
+
|
|
86
|
+
You can also chain calls using the `akamai-edgegrid` like in this example:
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
...
|
|
90
|
+
eg.auth({
|
|
91
|
+
path: '/papi/v1/groups',
|
|
92
|
+
method: 'GET',
|
|
93
|
+
headers: {},
|
|
94
|
+
}).send(function (error, response, body) {
|
|
95
|
+
console.log(body);
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
### Headers
|
|
99
|
+
|
|
100
|
+
Headers for the request must be supplied in an object as name-value pairs. You do not need to supply form-data headers or content lengths - that will cause authentication headers on the API.
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
eg.auth({
|
|
104
|
+
path: '/papi/v1/groups',
|
|
105
|
+
method: 'GET',
|
|
106
|
+
headers: {
|
|
107
|
+
'Accept': "application/json"
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Body data
|
|
113
|
+
|
|
114
|
+
The request `body` can be provided as either an object or as a POST data formed string.
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
// Object
|
|
119
|
+
eg.auth({
|
|
120
|
+
path: '/papi/v1/cpcodes?contractId=ctr_1234&groupId=grp_1234',
|
|
121
|
+
method: 'POST',
|
|
122
|
+
body: {
|
|
123
|
+
cpcodeName: "test-cpcode",
|
|
124
|
+
productId: "prd_Site_Accel"
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Query string parameters
|
|
130
|
+
|
|
131
|
+
Query string parameters must be supplied in an object as name-value pairs and
|
|
132
|
+
passed to the `auth` method under the `qs` property.
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
eg.auth({
|
|
136
|
+
path: '/papi/v1/cpcodes',
|
|
137
|
+
method: 'POST',
|
|
138
|
+
headers: {},
|
|
139
|
+
qs: {
|
|
140
|
+
contractId: "ctr_1234",
|
|
141
|
+
groupId: "grp_1234",
|
|
142
|
+
},
|
|
143
|
+
body: data
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
// Produces request URL similar to:
|
|
147
|
+
// https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/papi/v1/cpcodes?contractId=ctr_1234&groupId=grp_1234
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Debug
|
|
151
|
+
|
|
152
|
+
With EdgeGrid you can enable debugging either as part of the EdgeGrid instantiation object
|
|
153
|
+
or by setting the `EG_VERBOSE` environment variable. When enabled, EdgeGrid provides
|
|
154
|
+
additional information about the request that's helpful for debugging.
|
|
155
|
+
|
|
156
|
+
Here's an EdgeGrid example:
|
|
157
|
+
|
|
158
|
+
```javascript
|
|
159
|
+
// Set debug via EdgeGrid property
|
|
160
|
+
var eg = new EdgeGrid({
|
|
161
|
+
path: edgercPath,
|
|
162
|
+
section: sectionName,
|
|
163
|
+
debug: true
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
And here's an example for a command-line argument:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
// Set debug via environment variable
|
|
171
|
+
$ export EG_VERBOSE=true
|
|
172
|
+
$ node src/main.js
|
|
173
|
+
|
|
174
|
+
Starting Request {
|
|
175
|
+
url: 'https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/papi/v1/groups',
|
|
176
|
+
method: 'get',
|
|
177
|
+
data: '',
|
|
178
|
+
headers: {
|
|
179
|
+
common: { Accept: 'application/json, text/plain, */*' },
|
|
180
|
+
delete: {},
|
|
181
|
+
...
|
|
182
|
+
Response: {
|
|
183
|
+
status: 200,
|
|
184
|
+
statusText: 'OK',
|
|
185
|
+
headers: {
|
|
186
|
+
server: 'nginx',
|
|
187
|
+
'content-type': 'application/json;charset=UTF-8',
|
|
188
|
+
...
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Reporting issues
|
|
193
|
+
|
|
194
|
+
To report a problem or make a suggestion, create a new [GitHub issue](https://github.com/akamai/AkamaiOPEN-edgegrid-node/issues).
|
|
195
|
+
|
|
196
|
+
## License
|
|
197
|
+
|
|
198
|
+
Copyright 2021 Akamai Technologies, Inc. All rights reserved.
|
|
199
|
+
|
|
200
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
201
|
+
you may not use this file except in compliance with the License.
|
|
202
|
+
You may obtain a copy of the License at
|
|
203
|
+
|
|
204
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
205
|
+
|
|
206
|
+
Unless required by applicable law or agreed to in writing, software
|
|
207
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
208
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
209
|
+
See the License for the specific language governing permissions and
|
|
210
|
+
limitations under the License.
|
|
Binary file
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "akamai-edgegrid",
|
|
3
|
+
"version": "3.1.2",
|
|
4
|
+
"description": "Authentication handler for the Akamai OPEN EdgeGrid Authentication scheme in Node.js",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "EDGEGRID_ENV=test ./node_modules/.bin/mocha $(find test -name '*.js')"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/akamai-open/AkamaiOPEN-edgegrid-node.git"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"akamai",
|
|
15
|
+
"open",
|
|
16
|
+
"api",
|
|
17
|
+
"edgegrid"
|
|
18
|
+
],
|
|
19
|
+
"author": "Jonathan Bennett",
|
|
20
|
+
"contributors": [
|
|
21
|
+
"Darius Kazemi",
|
|
22
|
+
"Mike Ball",
|
|
23
|
+
"Kyle Tyacke"
|
|
24
|
+
],
|
|
25
|
+
"license": "Apache-2.0",
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"axios": "^0.21.4",
|
|
28
|
+
"log4js": "^0.6.14",
|
|
29
|
+
"moment": "^2.22.2",
|
|
30
|
+
"uuid": "^3.0.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"mocha": "^9.0.1",
|
|
34
|
+
"nock": "^10.0.1"
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/api.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// Copyright 2014 Akamai Technologies, Inc. All Rights Reserved
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
const axios = require('axios'),
|
|
16
|
+
auth = require('./auth'),
|
|
17
|
+
edgerc = require('./edgerc'),
|
|
18
|
+
helpers = require('./helpers'),
|
|
19
|
+
logger = require('./logger');
|
|
20
|
+
|
|
21
|
+
const EdgeGrid = function (client_token, client_secret, access_token, host, debug) {
|
|
22
|
+
// accepting an object containing a path to .edgerc and a config section
|
|
23
|
+
if (typeof arguments[0] === 'object') {
|
|
24
|
+
let edgercPath = arguments[0];
|
|
25
|
+
this._setConfigFromObj(edgercPath);
|
|
26
|
+
} else {
|
|
27
|
+
this._setConfigFromStrings(client_token, client_secret, access_token, host);
|
|
28
|
+
}
|
|
29
|
+
if (process.env.EG_VERBOSE || debug || (typeof arguments[0] === 'object' && arguments[0].debug)) {
|
|
30
|
+
axios.interceptors.request.use(request => {
|
|
31
|
+
console.log('Starting Request', request);
|
|
32
|
+
return request;
|
|
33
|
+
});
|
|
34
|
+
axios.interceptors.response.use(response => {
|
|
35
|
+
console.log('Response:', response);
|
|
36
|
+
return response;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Builds the request using the properties of the local config Object.
|
|
43
|
+
*
|
|
44
|
+
* @param {Object} req The request Object. Can optionally contain a
|
|
45
|
+
* 'headersToSign' property: An ordered list header names
|
|
46
|
+
* that will be included in the signature. This will be
|
|
47
|
+
* provided by specific APIs.
|
|
48
|
+
* @return EdgeGrid object (self)
|
|
49
|
+
*/
|
|
50
|
+
EdgeGrid.prototype.auth = function (req) {
|
|
51
|
+
let headers = {
|
|
52
|
+
'Content-Type': "application/json"
|
|
53
|
+
};
|
|
54
|
+
if (process.env['AKAMAI_CLI'] && process.env['AKAMAI_CLI_VERSION']) {
|
|
55
|
+
headers['User-Agent'] = (headers['User-Agent'] ? headers['User-Agent'] + " " : "") + `AkamaiCLI/${process.env['AKAMAI_CLI_VERSION']}`;
|
|
56
|
+
}
|
|
57
|
+
if (process.env['AKAMAI_CLI_COMMAND'] && process.env['AKAMAI_CLI_COMMAND_VERSION']) {
|
|
58
|
+
headers['User-Agent'] = (headers['User-Agent'] ? headers['User-Agent'] + " " : "") + `AkamaiCLI-${process.env['AKAMAI_CLI_COMMAND']}/${process.env['AKAMAI_CLI_COMMAND_VERSION']}`;
|
|
59
|
+
}
|
|
60
|
+
req = helpers.extend(req, {
|
|
61
|
+
baseURL: this.config.host,
|
|
62
|
+
url: req.path,
|
|
63
|
+
method: 'GET',
|
|
64
|
+
headers: headers,
|
|
65
|
+
maxRedirects: 0,
|
|
66
|
+
body: ''
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
let isTarball = req.body instanceof Uint8Array && req.headers['Content-Type'] === 'application/gzip';
|
|
70
|
+
|
|
71
|
+
// Convert body object to properly formatted string
|
|
72
|
+
if (req.body) {
|
|
73
|
+
if (typeof (req.body) == 'object' && !isTarball) {
|
|
74
|
+
req.body = JSON.stringify(req.body);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// this assignment is done in order to assert backwards compatibility of this library - a `body` field is accepted in this library, whereas axios expects the request body to be in `data` field
|
|
78
|
+
req.data = req.body;
|
|
79
|
+
|
|
80
|
+
this.request = auth.generateAuth(
|
|
81
|
+
req,
|
|
82
|
+
this.config.client_token,
|
|
83
|
+
this.config.client_secret,
|
|
84
|
+
this.config.access_token,
|
|
85
|
+
this.config.host
|
|
86
|
+
);
|
|
87
|
+
return this;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
EdgeGrid.prototype.send = function (callback) {
|
|
91
|
+
axios(this.request).then(response => {
|
|
92
|
+
callback(null, response, JSON.stringify(response.data));
|
|
93
|
+
}).catch(error => {
|
|
94
|
+
// handling redirects has to be handled in catch (with maxRedirects set to 0) because axios does not allow modifying headers between redirects
|
|
95
|
+
if (error.response && helpers.isRedirect(error.response.status)) {
|
|
96
|
+
this._handleRedirect(error.response, callback);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
callback(error);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return this;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
EdgeGrid.prototype._handleRedirect = function (resp, callback) {
|
|
106
|
+
const parsedUrl = new URL(resp.headers['location']);
|
|
107
|
+
|
|
108
|
+
resp.headers['authorization'] = undefined;
|
|
109
|
+
this.request.url = undefined;
|
|
110
|
+
this.request.path = parsedUrl.pathname + parsedUrl.search;
|
|
111
|
+
|
|
112
|
+
this.auth(this.request);
|
|
113
|
+
this.send(callback);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Creates a config object from a set of parameters.
|
|
118
|
+
*
|
|
119
|
+
* @param {String} client_token The client token
|
|
120
|
+
* @param {String} client_secret The client secret
|
|
121
|
+
* @param {String} access_token The access token
|
|
122
|
+
* @param {String} host The host
|
|
123
|
+
*/
|
|
124
|
+
EdgeGrid.prototype._setConfigFromStrings = function (client_token, client_secret, access_token, host) {
|
|
125
|
+
if (!validatedArgs([client_token, client_secret, access_token, host])) {
|
|
126
|
+
throw new Error('Insufficient Akamai credentials');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this.config = {
|
|
130
|
+
client_token: client_token,
|
|
131
|
+
client_secret: client_secret,
|
|
132
|
+
access_token: access_token,
|
|
133
|
+
host: host.indexOf('https://') > -1 ? host : 'https://' + host
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
function validatedArgs(args) {
|
|
138
|
+
const expected = [
|
|
139
|
+
'client_token', 'client_secret', 'access_token', 'host'
|
|
140
|
+
];
|
|
141
|
+
let valid = true;
|
|
142
|
+
|
|
143
|
+
expected.forEach(function (arg, i) {
|
|
144
|
+
if (!args[i]) {
|
|
145
|
+
logger.error('No defined ' + arg);
|
|
146
|
+
valid = false;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
return valid;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Creates a config Object from the section of a defined .edgerc file.
|
|
155
|
+
*
|
|
156
|
+
* @param {Object} obj An Object containing a path and section property that
|
|
157
|
+
* define the .edgerc section to use to create the Object.
|
|
158
|
+
*/
|
|
159
|
+
EdgeGrid.prototype._setConfigFromObj = function (obj) {
|
|
160
|
+
this.config = edgerc(obj.path, obj.section);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
module.exports = EdgeGrid;
|
package/src/auth.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Copyright 2014 Akamai Technologies, Inc. All Rights Reserved
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
const uuid = require('uuid'),
|
|
16
|
+
helpers = require('./helpers'),
|
|
17
|
+
logger = require('./logger'),
|
|
18
|
+
url = require('url');
|
|
19
|
+
|
|
20
|
+
function makeAuthHeader(request, clientToken, accessToken, clientSecret, timestamp, nonce, maxBody) {
|
|
21
|
+
const keyValuePairs = {
|
|
22
|
+
client_token: clientToken,
|
|
23
|
+
access_token: accessToken,
|
|
24
|
+
timestamp: timestamp,
|
|
25
|
+
nonce: nonce
|
|
26
|
+
};
|
|
27
|
+
let joinedPairs = '',
|
|
28
|
+
authHeader,
|
|
29
|
+
signedAuthHeader,
|
|
30
|
+
key;
|
|
31
|
+
|
|
32
|
+
for (key in keyValuePairs) {
|
|
33
|
+
joinedPairs += key + '=' + keyValuePairs[key] + ';';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
authHeader = 'EG1-HMAC-SHA256 ' + joinedPairs;
|
|
37
|
+
|
|
38
|
+
logger.info('Unsigned authorization header: ' + authHeader + '\n');
|
|
39
|
+
|
|
40
|
+
signedAuthHeader = authHeader + 'signature=' + helpers.signRequest(request, timestamp, clientSecret, authHeader, maxBody);
|
|
41
|
+
|
|
42
|
+
logger.info('Signed authorization header: ' + signedAuthHeader + '\n');
|
|
43
|
+
|
|
44
|
+
return signedAuthHeader;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function makeURL(host, path, queryStringObj) {
|
|
48
|
+
const parsed = new URL(path, host);
|
|
49
|
+
if (queryStringObj) {
|
|
50
|
+
const queryFromObject = new url.URLSearchParams();
|
|
51
|
+
for (const key of Object.keys(queryStringObj)) {
|
|
52
|
+
queryFromObject.append(key, queryStringObj[key]);
|
|
53
|
+
}
|
|
54
|
+
parsed.search = queryFromObject.toString();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return url.format(parsed);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = {
|
|
61
|
+
generateAuth: function (request, clientToken, clientSecret, accessToken, host, maxBody, guid, timestamp) {
|
|
62
|
+
maxBody = maxBody || 131072;
|
|
63
|
+
guid = guid || uuid.v4();
|
|
64
|
+
timestamp = timestamp || helpers.createTimestamp();
|
|
65
|
+
|
|
66
|
+
if (!request.hasOwnProperty('headers')) {
|
|
67
|
+
request.headers = {};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
request.url = makeURL(host, request.path, request.qs);
|
|
71
|
+
request.headers.Authorization = makeAuthHeader(request, clientToken, accessToken, clientSecret, timestamp, guid, maxBody);
|
|
72
|
+
|
|
73
|
+
return request;
|
|
74
|
+
}
|
|
75
|
+
};
|
package/src/edgerc.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// Copyright 2014 Akamai Technologies, Inc. All Rights Reserved
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
const fs = require('fs'),
|
|
16
|
+
logger = require('./logger'),
|
|
17
|
+
helpers = require('./helpers');
|
|
18
|
+
|
|
19
|
+
function getSection(lines, sectionName) {
|
|
20
|
+
const match = /^\s*\[(.*)]/,
|
|
21
|
+
section = [];
|
|
22
|
+
|
|
23
|
+
lines.some(function (line, i) {
|
|
24
|
+
const lineMatch = line.match(match),
|
|
25
|
+
isMatch = lineMatch !== null && lineMatch[1] === sectionName;
|
|
26
|
+
|
|
27
|
+
if (isMatch) {
|
|
28
|
+
// go through section until we find a new one
|
|
29
|
+
lines.slice(i + 1, lines.length).some(function (line) {
|
|
30
|
+
const isMatch = line.match(match) !== null;
|
|
31
|
+
if (!isMatch) {
|
|
32
|
+
section.push(line);
|
|
33
|
+
}
|
|
34
|
+
return isMatch;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return isMatch;
|
|
38
|
+
});
|
|
39
|
+
return section;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function validatedConfig(config) {
|
|
43
|
+
|
|
44
|
+
if (!(config.host && config.access_token &&
|
|
45
|
+
config.client_secret && config.client_token)) {
|
|
46
|
+
let errorMessage = "";
|
|
47
|
+
const tokens =
|
|
48
|
+
['client_token', 'client_secret', 'access_token', 'host'];
|
|
49
|
+
tokens.forEach(function (token) {
|
|
50
|
+
if (!config[token]) {
|
|
51
|
+
errorMessage += "\nMissing: " + token;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
console.log('Missing part of the configuration:\n' + errorMessage);
|
|
55
|
+
return {};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (config.host.indexOf('https://') > -1) {
|
|
59
|
+
return config;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
config.host = 'https://' + config.host;
|
|
63
|
+
|
|
64
|
+
return config;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function buildObj(configs) {
|
|
68
|
+
const result = {};
|
|
69
|
+
let index,
|
|
70
|
+
key,
|
|
71
|
+
val,
|
|
72
|
+
parsedValue,
|
|
73
|
+
isComment;
|
|
74
|
+
|
|
75
|
+
configs.forEach(function (config) {
|
|
76
|
+
config = config.trim();
|
|
77
|
+
isComment = config.indexOf(";") === 0;
|
|
78
|
+
index = config.indexOf('=');
|
|
79
|
+
if (index > -1 && !isComment) {
|
|
80
|
+
key = config.substr(0, index);
|
|
81
|
+
val = config.substring(index + 1);
|
|
82
|
+
// remove inline comments
|
|
83
|
+
parsedValue = val.replace(/^\s*(['"])((?:\\\1|.)*?)\1\s*(?:;.*)?$/, "$2");
|
|
84
|
+
if (parsedValue === val) {
|
|
85
|
+
// the value is not contained in matched quotation marks
|
|
86
|
+
parsedValue = val.replace(/\s*([^;]+)\s*;?.*$/, "$1");
|
|
87
|
+
}
|
|
88
|
+
// Remove trailing slash as if often found in the host property
|
|
89
|
+
if (parsedValue.endsWith("/")) {
|
|
90
|
+
parsedValue = parsedValue.substr(0, parsedValue.length - 1);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
result[key.trim()] = parsedValue;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return validatedConfig(result);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function readEnv(section) {
|
|
101
|
+
const requiredKeys = ["HOST", "ACCESS_TOKEN", "CLIENT_TOKEN", "CLIENT_SECRET"],
|
|
102
|
+
prefix = !section || section === "default" ? "AKAMAI_" : "AKAMAI_" + section.toUpperCase() + "_",
|
|
103
|
+
envConfig = {};
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
for (const key of requiredKeys) {
|
|
107
|
+
const varName = prefix + key;
|
|
108
|
+
if (!process.env[varName]) {
|
|
109
|
+
logger.debug("Environment variable not set: " + varName);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
envConfig[key.toLowerCase()] = process.env[prefix + key];
|
|
113
|
+
}
|
|
114
|
+
if (Object.keys(envConfig).length < requiredKeys.length) {
|
|
115
|
+
return {};
|
|
116
|
+
}
|
|
117
|
+
console.log("Using configuration from environment variables");
|
|
118
|
+
return validatedConfig(envConfig);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports = function (path, conf) {
|
|
122
|
+
const confSection = conf || 'default',
|
|
123
|
+
envConf = readEnv(confSection);
|
|
124
|
+
if (envConf['host']) {
|
|
125
|
+
return envConf;
|
|
126
|
+
}
|
|
127
|
+
if (!path) {
|
|
128
|
+
throw new Error("Either path to '.edgerc' or environment variables with edgerc configuration has to be provided.");
|
|
129
|
+
}
|
|
130
|
+
path = helpers.resolveHome(path);
|
|
131
|
+
const edgerc = fs.readFileSync(path).toString().split('\n'),
|
|
132
|
+
confData = getSection(edgerc, confSection);
|
|
133
|
+
|
|
134
|
+
if (!confData.length) {
|
|
135
|
+
throw new Error('An error occurred parsing the .edgerc file. You probably specified an invalid section name.');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return buildObj(confData);
|
|
139
|
+
};
|