From 4c73e6310d3df15680dc722fdf8b2e0880ee6619 Mon Sep 17 00:00:00 2001 From: Girish Ramakrishnan Date: Thu, 30 Mar 2017 16:31:22 -0700 Subject: [PATCH] add ratelimit tests --- cloudron.js | 35 +++++++++++++++++++++++++++++++++++ test/app-flow-test.js | 4 ++++ test/new-user-test.js | 14 ++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/cloudron.js b/cloudron.js index fba8fc6..3170a17 100644 --- a/cloudron.js +++ b/cloudron.js @@ -3,6 +3,7 @@ 'use strict'; var assert = require('assert'), + async = require('async'), common = require('./common.js'), debug = require('debug')('e2e:cloudron'), dns = require('dns'), @@ -643,6 +644,15 @@ Cloudron.prototype.checkAddons = function (domain, owner) { throw lastError; }; +Cloudron.prototype.checkAppRateLimit = function (domain) { + var res = request.post('https://' + domain + '/ratelimit').end(); + + assert.strictEqual(res.statusCode, 200); + for (var addon in res.body) { + assert.strictEqual(res.body[addon], 'OK'); + } +}; + Cloudron.prototype.checkDnsbl = function (domain) { var res = request.post('https://' + domain + '/check_dnsbl').end(); common.verifyResponse2xx(res, 'Could not query dnsbl'); @@ -760,3 +770,28 @@ Cloudron.prototype.checkMail = function (account, callback) { body: common.regexp('This release depends on you') }, callback); }; + +Cloudron.prototype.checkTcpRateLimit = function (port, times, callback) { + tcpBomb(this._adminFqdn, port, times, 900 /* timeout */, function (error, result) { + if (error) return callback(new Error(host + ':' + port + ':' + error.message)); + + if (result.timeout) return callback(null, { status: 'OK' }); // something timedout, this is good enough + + return callback(new Error(host + ':' + port + ':' + JSON.stringify(result, null, 4))); + }); +}; + +Cloudron.prototype.checkNginxRateLimit = function (times, callback) { + var ok = 0; + + async.times(times, function (n, done) { + var client = new net.Socket(); + + var res = request.post('https://' + this._box.ip + '/api/v1/developer/login').send({ username: owner.username, password: owner.password }).end(); + + if (res.statusCode === 200) ++ok; + }); + + callback(ok == times ? new Error('All requests succeeded') : null); +}; + diff --git a/test/app-flow-test.js b/test/app-flow-test.js index ef3f9f4..d77ec37 100644 --- a/test/app-flow-test.js +++ b/test/app-flow-test.js @@ -71,6 +71,10 @@ describe('Application flow test', function () { cloudron.checkAddons(cloudron.appFqdn(location), owner); }); + it('can check the app ratelimit', function () { + cloudron.checkAppRateLimit(cloudron.appFqdn(location)); + }); + it('can check dnsbl', function () { cloudron.checkDnsbl(cloudron.appFqdn(location)); }); diff --git a/test/new-user-test.js b/test/new-user-test.js index 5056e81..83c0a67 100644 --- a/test/new-user-test.js +++ b/test/new-user-test.js @@ -132,6 +132,20 @@ describe('Appstore new user flow', function () { ], done); }); + it('does TCP ratelimiting', function (done) { + async.series([ + cloudron.checkTcpRateLimit.bind(cloudron, 202, 5), // ssh + cloudron.checkTcpRateLimit.bind(cloudron, 25, 50), // mail + cloudron.checkTcpRateLimit.bind(cloudron, 587, 50), // msa + cloudron.checkTcpRateLimit.bind(cloudron, 993, 50), // imap + cloudron.checkTcpRateLimit.bind(cloudron, 4190, 50), // sieve + ], done); + }); + + it('does nginx ratelimiting', function (done) { + cloudron.checkNginxRateLimit(10, done); + }); + it('can delete the cloudron', function () { appStore.deleteCloudron(box); });