Skip to content

Commit

Permalink
Basic authentication - #14
Browse files Browse the repository at this point in the history
  • Loading branch information
sv2 committed Nov 1, 2017
1 parent f7eaf75 commit 8c741f7
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 8 deletions.
7 changes: 7 additions & 0 deletions examples/spectest/spectest.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ parser.validate(specLocation,function(err, api) {
requestSizeBuckets: [10, 25, 50, 100, 200],
responseSizeBuckets: [10, 25, 50, 100, 200],
apdexThreshold: 100
/*
authentication: true,
onAuthenticate: function(req,username,password){
// simple check for username and password
return((username==='prometheus') && (password==='prometheus') );
}
*/
}));

// Implement mock API
Expand Down
49 changes: 46 additions & 3 deletions lib/swsInterface.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
* Created by sv2 on 2/16/17.
*/

// TODO Validate requests per swagger definition. Enable validation only for specific subset of URIs, i.e. "/api"

'use strict';

var fs = require('fs');
var path = require('path');
var debug = require('debug')('sws:interface');
var promClient = require("prom-client");
var basicAuth = require("basic-auth");

var swsUtil = require('./swsUtil');
var swsProcessor = require('./swsProcessor');
Expand All @@ -26,7 +25,9 @@ var swsOptions = {
requestSizeBuckets: [5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000],
responseSizeBuckets: [5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000],
apdexThreshold: 50,
onResponseFinish: null
onResponseFinish: null,
authentication: false,
onAuthenticate: function(req,username,password) {return false;}
};

var uiMarkup = swsUtil.swsEmbeddedUIMarkup;
Expand Down Expand Up @@ -77,17 +78,59 @@ function processOptions(options){
pathMetrics = swsOptions.uriPath+'/metrics';
}


function processAuth(req,res,useWWWAuth) {

if( !swsOptions.authentication ){
return true;
}

var authInfo = basicAuth(req);

var authenticated = false;

if( (authInfo !== undefined) && (authInfo!==null) && ('name' in authInfo) && ('pass' in authInfo)){
if(typeof swsOptions.onAuthenticate === 'function'){
if( swsOptions.onAuthenticate(req, authInfo.name, authInfo.pass) ){
authenticated = true;
}
}
}

if( !authenticated ){
if(useWWWAuth){
res.setHeader('WWW-Authenticate', 'Basic realm="swagger-stats"');
}
// TODO Reconsider 401 response. Should it be 403 or 500, to prevent browser Basic Auth pop-up in UI ?
res.status(401).end('Access denied');
return false;
}

return true;
}


// Process /swagger-stats/stats request
// Return statistics according to request parameters
// Query parameters (fields, path, method) defines which stat fields to return
function processGetStats(req,res){

if(!processAuth(req,res,true)) {
return;
}

res.status(200).json( processor.getStats( req.query ) );
}


// Process /swagger-stats/metrics request
// Return all metrics for Prometheus
function processGetMetrics(req,res){

if(!processAuth(req,res,false)) {
return;
}

res.status(200).set('Content-Type', 'text/plain');
res.end(promClient.register.metrics());
}
Expand Down
19 changes: 17 additions & 2 deletions lib/swsUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,26 @@ module.exports.supportedOptions = {
// Callback to invoke when response is finished - https://github.com/slanatech/swagger-stats/issues/5
// Application may implement it to trace Request Response Record (RRR), which is passed as parameter
// the following parameters are passed to this callback:
// OnResponseFinish(req,res,rrr)
// onResponseFinish(req,res,rrr)
// - req - request
// - res - response
// - rrr - Request Response Record (RRR)
onResponseFinish : "onResponseFinish"
onResponseFinish : "onResponseFinish",

// Enable Basic authentication: true or false. Default false.
// Only Basic authentication is supported
authentication : "authentication",

// Callback to invoke to authenticate request to /swagger-stats/stats and /swagger-stats/metrics
// If authentication is enabled (option authentication=true),
// Application must implement onAuthenticate to validate user credentials
// the following parameters are passed to this callback:
// onAuthenticate(req,username,password)
// - req - request
// - username - username
// - password - password
// callback must return true if user authenticated, false if not
onAuthenticate : "onAuthenticate"

};

Expand Down
11 changes: 9 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
},
"license": "MIT",
"dependencies": {
"basic-auth": "^2.0.0",
"debug": "^3.1.0",
"moment": "^2.19.1",
"path-to-regexp": "^2.1.0",
Expand Down
2 changes: 1 addition & 1 deletion test/randomtest/randomtest.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ parser.validate(swaggerSpecUrl, function (err, api) {
supertest(swsTestFixture.SWS_SPECTEST_DEFAULT_URL).get(swsTestFixture.SWS_TEST_STATS_API)
.expect(200)
.end(function (err, res) {
if (err) {
if (err && (res.status !== 401)) { // support case when authorization is enabled
process.env.SWS_SPECTEST_URL = swaggerSpecUrl;
appRandomTest = require('../../examples/spectest/spectest');
apiRandomTest = supertest('http://localhost:' + appRandomTest.app.get("port"));
Expand Down

0 comments on commit 8c741f7

Please sign in to comment.