Skip to content

Commit

Permalink
Merge 40e1a5d into a9ee0bb
Browse files Browse the repository at this point in the history
  • Loading branch information
davepgreene committed Jul 10, 2018
2 parents a9ee0bb + 40e1a5d commit 277ccae
Show file tree
Hide file tree
Showing 71 changed files with 6,247 additions and 1,398 deletions.
9 changes: 7 additions & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"parser":"babel-eslint",
"extends": "rapid7/base"
"extends": ["rapid7/base"],
"globals": {
"require": true,
"process": true,
"__dirname": true,
"console": true
}
}
30 changes: 23 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
node_modules/
dist/
test/.aws/
*.log
# See https://help.github.com/ignore-files/ for more about ignoring files.

# dependencies
/node_modules

# testing
/coverage
/test/.aws/
/test/data/test.json

# production
/build
/dist

# misc
.DS_Store
test/data/test.json
typings/
coverage/
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
*~
1 change: 0 additions & 1 deletion .nvmrc

This file was deleted.

19 changes: 6 additions & 13 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
language: node_js
env:
- CXX=g++-4.8
sudo: false
node_js:
- "node"
script:
- npm test
- npm run lint
- npm run cover
- yarn test
- yarn lint
- yarn cover
after_success:
npm run report
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
- yarn report
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2015-2016 Frank Mitchell, Rapid7 LLC.
Copyright (c) 2015-2018 Frank Mitchell, Rapid7 LLC.

MIT License
===========
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,31 +195,31 @@ the URL's valid, it will prompt you to login to your identity provider. If the
login's successful, you'll see temporary AWS credentials in the UI.

## Building
Awsaml is built using [Node][] version 7.4.0 and [Yarn][] version 1.3.2, so
Awsaml is built using [Node][] and [Yarn][], so
make sure you've got a compatible versions installed. Then run Yarn to install
dependencies and build Awsaml.

~~~bash
rm -rf node_modules/
yarn install
yarn run build
yarn build
~~~

Those commnds will create a "dist" folder with zipped binaries. If you only want
Those commands will create a "dist" folder with zipped binaries. If you only want
to create binaries for specific platforms, you can set a `PLATFORM` environment
variable before building.

~~~bash
export PLATFORM=linux
yarn run build
yarn build
~~~

Allowed values for `PLATFORM` are `darwin`, `linux` and `win32`. You can build
binaries for multiple platforms by using a comma separated list.

~~~bash
export PLATFORM=darwin,linux
yarn run build
yarn build
~~~

## Setup on OSX with Homebrew
Expand Down
3 changes: 3 additions & 0 deletions api/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["rapid7/node"]
}
12 changes: 5 additions & 7 deletions lib/auth.js → api/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ class Auth {
return done(null, user.nameID);
});

this.passport.deserializeUser((id, done) => {
return done(null, this.users[id]);
});
this.passport.deserializeUser((id, done) => done(null, this.users[id]));

this.guard = function guard(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect(options.entryPoint);
res.json({
redirect: options.entryPoint,
});
};
}

Expand All @@ -36,9 +36,7 @@ class Auth {
}

configure(options) {
const samlCallback = (profile, done) => {
return done(null, profile);
};
const samlCallback = (profile, done) => done(null, profile);

this.passport.use(new SamlStrategy(options, samlCallback));
}
Expand Down
6 changes: 3 additions & 3 deletions lib/aws-credentials.js → api/aws-credentials.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ class AwsCredentials {
static resolveHomePath() {
const env = process.env;

return env.HOME ||
env.USERPROFILE ||
(env.HOMEPATH ? ((env.HOMEDRIVE || 'C:/') + env.HOMEPATH) : null);
return env.HOME
|| env.USERPROFILE
|| (env.HOMEPATH ? ((env.HOMEDRIVE || 'C:/') + env.HOMEPATH) : null);
}
}

Expand Down
File renamed without changes.
4 changes: 1 addition & 3 deletions lib/response.js → api/response.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
'use strict';

module.exports = {
platform: process.platform,
title: 'Rapid7 - Awsaml',
platform: process.platform
};
12 changes: 8 additions & 4 deletions lib/routes/auth.js → api/routes/auth.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use strict';

const url = require('url');
const express = require('express');

const router = express.Router();

module.exports = (app, auth) => {
router.post('/', auth.authenticate('saml', {
failureFlash: true,
failureRedirect: app.get('configureUrl'),
failureFlash: true
}), (req, res) => {
const arns = req.user['https://aws.amazon.com/SAML/Attributes/Role'].split(',');

Expand All @@ -16,7 +16,11 @@ module.exports = (app, auth) => {
req.session.passport.principalArn = arns[1];
req.session.passport.accountId = arns[0].split(':')[4]; // eslint-disable-line rapid7/static-magic-numbers
/* eslint-enable no-param-reassign */
res.redirect('/refresh');
let frontend = process.env.ELECTRON_START_URL || app.get('baseUrl');

frontend = new url.URL(frontend);
frontend.searchParams.set('auth', 'true');
res.redirect(frontend);
});

return router;
Expand Down
102 changes: 65 additions & 37 deletions lib/routes/configure.js → api/routes/configure.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,75 @@
const https = require('https');
const express = require('express');
const router = express.Router();

const xmldom = require('xmldom');
const xpath = require('xpath.js');
const config = require('../../config');
const config = require('../config');

const router = express.Router();
const HTTP_OK = 200;

const Errors = {
invalidMetadataErr: 'The SAML metadata is invalid.',
urlInvalidErr: 'The SAML metadata URL is invalid.',
invalidMetadataErr: 'The SAML metadata is invalid.'
};
const ResponseObj = require('./../response');

module.exports = (app, auth) => {
router.get('/', (req, res) => {
const storedMetadataUrls = Storage.get('metadataUrls') || {};
const storedMetadataUrls = Storage.get('metadataUrls') || [];

// We populate the value of the metadata url field on the following (in order of precedence):
// 1. Use the current session's metadata url (may have been rejected).
// 2. Use the latest validated metadata url.
// 3. Support the <= v1.3.0 storage key.
// 4. Default the metadata url to empty string.
const defaultMetadataUrl =
app.get('metadataUrl') ||
Storage.get('previousMetadataUrl') ||
Storage.get('metadataUrl') ||
Object.keys(storedMetadataUrls)[0] ||
'';

res.render('configure', Object.assign(ResponseObj, {
let defaultMetadataUrl =
app.get('metadataUrl')
|| Storage.get('previousMetadataUrl')
|| Storage.get('metadataUrl')
|| '';

if (!defaultMetadataUrl) {
if (storedMetadataUrls.length > 0 && storedMetadataUrls[0].hasOwnProperty('url')) {
defaultMetadataUrl = storedMetadataUrls[0].url;
}
}

res.json(Object.assign({}, ResponseObj, {
defaultMetadataUrl,
metadataUrls: storedMetadataUrls,
error: Storage.get('metadataUrlError'),
metadataUrlValid: Storage.get('metadataUrlValid'),
error: Storage.get('metadataUrlError')
metadataUrls: storedMetadataUrls,
}));
});

router.post('/', (req, res) => {
const metadataUrl = req.body.metadataUrl;
const metaDataResponseObj = Object.assign(ResponseObj, {defaultMetadataUrl: metadataUrl});

let storedMetadataUrls = Storage.get('metadataUrls') || {},
profileName = req.body.profileName;
if (!metadataUrl) {
Storage.set('metadataUrlValid', false);
Storage.set('metadataUrlError', Errors.urlInvalidErr);

if (profileName === '') {
profileName = metadataUrl;
return res.json(Object.assign({}, ResponseObj, {
error: Errors.urlInvalidErr,
metadataUrlValid: false,
}));
}

if (profileName && storedMetadataUrls[metadataUrl] && storedMetadataUrls[metadataUrl] !== profileName) {
storedMetadataUrls[metadataUrl] = profileName;
Storage.set(storedMetadataUrls);
}
const origin = req.body.origin;
const metaDataResponseObj = Object.assign({}, ResponseObj, {defaultMetadataUrl: metadataUrl});

let storedMetadataUrls = Storage.get('metadataUrls') || [];
const profileName = req.body.profileName === '' ? metadataUrl : req.body.profileName;
const profile = storedMetadataUrls.find((profile) => profile.url === metadataUrl);

storedMetadataUrls = storedMetadataUrls.map((storedMetadataUrl) => {
if (profileName && storedMetadataUrl.url === metadataUrl && storedMetadataUrl.name !== profileName) {
storedMetadataUrl.name = profileName;
}

return storedMetadataUrl;
});
Storage.set('metadataUrls', storedMetadataUrls);
app.set('metadataUrl', metadataUrl);

const xmlReq = https.get(metadataUrl, (xmlRes) => {
Expand All @@ -62,9 +79,9 @@ module.exports = (app, auth) => {
Storage.set('metadataUrlValid', false);
Storage.set('metadataUrlError', Errors.urlInvalidErr);

res.render('configure', Object.assign(metaDataResponseObj, {
res.json(Object.assign({}, metaDataResponseObj, {
error: Errors.urlInvalidErr,
metadataUrlValid: false,
error: Errors.urlInvalidErr
}));

return;
Expand Down Expand Up @@ -108,27 +125,38 @@ module.exports = (app, auth) => {

if (cert && issuer && entryPoint) {
Storage.set('previousMetadataUrl', metadataUrl);
let metadataUrls = Storage.get('metadataUrls') || {};

if (!metadataUrls.hasOwnProperty(metadataUrl)) {
metadataUrls[metadataUrl] = profileName || metadataUrl;
Storage.set('metadataUrls', metadataUrls);
}
const metadataUrls = Storage.get('metadataUrls') || [];

Storage.set(
'metadataUrls',
profile ? metadataUrls : metadataUrls.concat([
{
name: profileName || metadataUrl,
url: metadataUrl,
},
])
);

app.set('entryPointUrl', config.auth.entryPoint);
auth.configure(config.auth);
res.redirect(config.auth.entryPoint);
if (origin === 'electron') {
res.redirect(config.auth.entryPoint);
} else {
res.json({
redirect: config.auth.entryPoint,
});
}
} else {
res.render('configure', Object.assign(metaDataResponseObj, {
error: Errors.invalidMetadataErr
res.json(Object.assign({}, metaDataResponseObj, {
error: Errors.invalidMetadataErr,
}));
}
});
});

xmlReq.on('error', (err) => {
res.render('configure', Object.assign(metaDataResponseObj, {
error: err.message
res.json(Object.assign({}, metaDataResponseObj, {
error: err.message,
}));
});
});
Expand Down
7 changes: 4 additions & 3 deletions lib/routes/logout.js → api/routes/logout.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
'use strict';

const express = require('express');

const router = express.Router();

module.exports = (app) => {
router.get('/', (req, res) => {
app.set('entryPointUrl', null);
req.session.destroy();
res.redirect(app.get('configureUrl'));
res.json({
logout: true,
});
});

return router;
Expand Down
19 changes: 19 additions & 0 deletions api/routes/profile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const express = require('express');
const url = require('url');

const router = express.Router();

module.exports = () => {
router.delete('/', (req, res) => {
let {profile} = url.parse(req.url, true).query;
let idx = parseInt(profile, 10);
let metadataUrls = Storage.get('metadataUrls');

metadataUrls = metadataUrls.map((metadataUrl, i) => (i !== idx) ? metadataUrl : null).filter((el) => !!el);
Storage.set('metadataUrls', metadataUrls);

res.status(200).end();
});

return router;
};
Loading

0 comments on commit 277ccae

Please sign in to comment.