Skip to content

Commit 29010f7

Browse files
author
Jami
committed
Download api endpoint added
1 parent 9d7429e commit 29010f7

File tree

6 files changed

+112
-3
lines changed

6 files changed

+112
-3
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,17 @@ This server exposes the following REST API's:
185185
- **[WIP] POST `/config`**
186186

187187
Allows you to edit the ElastAlert configuration from `config.yaml` in `elastalertPath` (from the config). The required body to be send will be edited when the work on this API is done.
188-
188+
189+
- **[WIP] POST `/download`**
190+
191+
Allows you to download .tar archive with rules from HTTP endpoint. Archive will be downloaded,extracted and removed.
192+
Please note, body should contain URL pointing to tar archive, with tar extension.
193+
194+
Usage example:
195+
196+
```curl -X POST localhost:3030/download -d "url=https://artifactory.com:443/artifactory/raw/rules/rules.tar"```
197+
198+
189199
## Contributing
190200
Want to contribute to this project? Great! Please read our [contributing guidelines](CONTRIBUTING.md) before submitting an issue or a pull request.
191201

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@
2929
"mkdirp": "^0.5.1",
3030
"object-resolve-path": "^1.1.1",
3131
"randomstring": "^1.1.5",
32-
"raven": "^2.3.0"
32+
"raven": "^2.3.0",
33+
"tar": "^4.4.1",
34+
"fs-extra": "^5.0.0",
35+
"request-promise-native": "^1.0.5"
3336
},
3437
"devDependencies": {
3538
"eslint": "^4.17.0",

src/common/errors/rule_request_errors.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,13 @@ export class RulesRootFolderNotCreatableError extends RequestError {
4141
super('rulesRootFolderNotCreatable', 'The rules folder wasn\'t found and couldn\'t be created by the file system.', 403);
4242
}
4343
}
44+
export class URLNotSentError extends RequestError {
45+
constructor() {
46+
super('URLNotSentError', 'URL is missing in the body', 400);
47+
}
48+
}
49+
export class URLNotPointingTar extends RequestError {
50+
constructor() {
51+
super('URLNotPointingTar', 'URL is not pointing to .tar file', 400);
52+
}
53+
}

src/controllers/rules/index.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import {join as joinPath, normalize as normalizePath, extname as pathExtension} from 'path';
22
import mkdirp from 'mkdirp';
3+
import tar from 'tar';
4+
import fs from 'fs-extra';
5+
import rq from 'request-promise-native';
36
import FileSystem from '../../common/file_system';
47
import config from '../../common/config';
58
import Logger from '../../common/logger';
9+
import path from 'path';
610
import {RuleNotFoundError, RuleNotReadableError, RuleNotWritableError,
711
RulesFolderNotFoundError, RulesRootFolderNotCreatableError} from '../../common/errors/rule_request_errors';
812

@@ -87,6 +91,10 @@ export default class RulesController {
8791
return this._editRule(id, content);
8892
}
8993

94+
downloadRules(URL) {
95+
return this._downloadRules(URL);
96+
}
97+
9098
_findRule(id) {
9199
let fileName = id + '.yaml';
92100
const self = this;
@@ -125,6 +133,19 @@ export default class RulesController {
125133
return this._fileSystemController.deleteFile(path);
126134
}
127135

136+
_downloadRules(URL){
137+
const options = {
138+
uri: URL,
139+
strictSSL: false
140+
};
141+
const filename = path.basename(URL);
142+
143+
return rq.get(options)
144+
.then(buffer => fs.outputFile(filename, buffer)
145+
.then(() => this._untarFile(this.rulesFolder,filename))
146+
.then(() => fs.remove(filename)));
147+
}
148+
128149
_getErrorPromise(error) {
129150
return new Promise(function (resolve, reject) {
130151
reject(error);
@@ -140,4 +161,13 @@ export default class RulesController {
140161
return ruleFolderSettings.path;
141162
}
142163
}
143-
}
164+
165+
_untarFile(path_to_extract,archive){
166+
return tar.extract(
167+
{
168+
cwd: path_to_extract,
169+
file: archive
170+
}
171+
);
172+
}
173+
}

src/handlers/rules/id/download.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import RouteLogger from '../../../routes/route_logger';
2+
import {sendRequestError} from '../../../common/errors/utils';
3+
import {URLNotSentError,URLNotPointingTar} from '../../../common/errors/rule_request_errors';
4+
import path from 'path';
5+
6+
let logger = new RouteLogger('/download');
7+
8+
9+
export default function downloadRulesHandler(request, response) {
10+
/**
11+
* @type {ElastalertServer}
12+
*/
13+
let server = request.app.get('server');
14+
let body = request.body;
15+
16+
17+
function _test_body(body){
18+
if (!body||!body.url) {
19+
return new URLNotSentError();
20+
}
21+
let filename = path.basename(body.url);
22+
if (!filename.endsWith('.tar')){
23+
return new URLNotPointingTar();
24+
}
25+
return body;
26+
}
27+
28+
body=_test_body(body);
29+
if(body.error){
30+
logger.sendFailed(body.error);
31+
sendRequestError(response, body.error);
32+
return;
33+
}
34+
35+
36+
server.rulesController.downloadRules(body.url)
37+
.then(() => {
38+
logger.sendSuccessful();
39+
return response.send({
40+
downloaded: true,
41+
extracted: true,
42+
url: body.url
43+
});
44+
})
45+
.catch((error) => {
46+
logger.sendFailed(error);
47+
sendRequestError(response, error);
48+
});
49+
50+
}

src/routes/routes.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import controlHandler from '../handlers/status/control';
44
import errorsHandler from '../handlers/status/errors';
55
import rulesHandler from '../handlers/rules';
66
import ruleGetHandler from '../handlers/rules/id/get';
7+
import downloadRulesHandler from '../handlers/rules/id/download';
78
import rulePostHandler from '../handlers/rules/id/post';
89
import ruleDeleteHandler from '../handlers/rules/id/delete';
910
import templatesHandler from '../handlers/templates';
@@ -68,6 +69,11 @@ let routes = [
6869
path: 'config',
6970
method: ['GET', 'POST'],
7071
handler: [configGetHandler, configPostHandler]
72+
},
73+
{
74+
path: 'download',
75+
method: ['POST'],
76+
handler: [downloadRulesHandler]
7177
}
7278
];
7379

0 commit comments

Comments
 (0)