Merge pull request #607 from mozilla/lockdown

Lockdown

Big, green checkbox.

r+, thanks for this @pdehaan!
This commit is contained in:
Shane Tomlinson 2014-02-25 11:45:53 +00:00
Родитель 5d469b702a 6192bcc837
Коммит f598283b07
3 изменённых файлов: 1694 добавлений и 38 удалений

1455
lockdown.json Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -4,7 +4,9 @@
"description": "Firefox Accounts Content Server",
"scripts": {
"start": "grunt server",
"preinstall": "./scripts/lockdown",
"postinstall": "bower install",
"lockdown": "./node_modules/.bin/lockdown-relock",
"test": "intern-runner config=tests/intern",
"test-browser": "intern-runner config=tests/intern_browser",
"test-remote": "intern-runner config=tests/intern_sauce",
@ -27,55 +29,56 @@
"consolidate": "0.10.0",
"convict": "0.4.0",
"express": "3.3.4",
"grunt": "~0.4.1",
"grunt-autoprefixer": "~0.7.0",
"grunt-bower-install": "~0.5.0",
"grunt-bower-requirejs": "~0.7.1",
"grunt": "0.4.2",
"grunt-autoprefixer": "0.7.1",
"grunt-bower-install": "0.5.0",
"grunt-bower-requirejs": "0.7.1",
"grunt-bump": "0.0.13",
"grunt-cli": "0.1.11",
"grunt-concurrent": "~0.3.0",
"grunt-contrib-clean": "~0.5.0",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-copy": "~0.4.1",
"grunt-contrib-csslint": "~0.2.0",
"grunt-contrib-cssmin": "~0.6.0",
"grunt-contrib-htmlmin": "~0.1.3",
"grunt-contrib-imagemin": "~0.5.0",
"grunt-contrib-jshint": "~0.8.0",
"grunt-contrib-uglify": "~0.2.0",
"grunt-contrib-watch": "~0.5.2",
"grunt-conventional-changelog": "~1.1.0",
"grunt-copyright": "~0.1.0",
"grunt-jscs-checker": "~0.3.2",
"grunt-jsonlint": "~1.0.4",
"grunt-mocha": "~0.4.0",
"grunt-modernizr": "~0.4.1",
"grunt-cli": "0.1.13",
"grunt-concurrent": "0.3.0",
"grunt-contrib-clean": "0.5.0",
"grunt-contrib-concat": "0.3.0",
"grunt-contrib-copy": "0.4.1",
"grunt-contrib-csslint": "0.2.0",
"grunt-contrib-cssmin": "0.6.0",
"grunt-contrib-htmlmin": "0.1.3",
"grunt-contrib-imagemin": "0.5.0",
"grunt-contrib-jshint": "0.8.0",
"grunt-contrib-uglify": "0.2.0",
"grunt-contrib-watch": "0.5.2",
"grunt-conventional-changelog": "1.1.0",
"grunt-copyright": "0.1.0",
"grunt-jscs-checker": "0.3.2",
"grunt-jsonlint": "1.0.4",
"grunt-mocha": "0.4.0",
"grunt-modernizr": "0.4.1",
"grunt-po2json": "git://github.com/shane-tomlinson/grunt-po2json.git#c1a7406",
"grunt-preprocess": "~3.0.1",
"grunt-requirejs": "~0.4.0",
"grunt-rev": "~0.1.0",
"grunt-sass": "~0.10.0",
"grunt-svgmin": "~0.2.0",
"grunt-todo": "~0.1.2",
"grunt-usemin": "~0.1.10",
"grunt-z-schema": "~0.1.0",
"handlebars": "~1.3.0",
"grunt-preprocess": "3.0.1",
"grunt-requirejs": "0.4.0",
"grunt-rev": "0.1.0",
"grunt-sass": "0.11.0",
"grunt-svgmin": "0.2.0",
"grunt-todo": "0.1.2",
"grunt-usemin": "0.1.10",
"grunt-z-schema": "0.1.0",
"handlebars": "1.3.0",
"helmet": "0.1.2",
"i18n-abide": "0.0.17",
"intel": "0.4.0",
"intel": "0.5.2",
"jshint": "0.9.1",
"jshint-stylish": "~0.1.4",
"jshint-stylish": "0.1.5",
"jsxgettext-recursive": "0.0.3",
"jwcrypto": "0.4.3",
"load-grunt-tasks": "~0.3.0",
"mkdirp": "~0.3.5",
"time-grunt": "~0.2.9"
"jwcrypto": "0.5.0",
"load-grunt-tasks": "0.3.0",
"lockdown": "0.0.5",
"mkdirp": "0.3.5",
"time-grunt": "0.2.9"
},
"devDependencies": {
"awsbox": "0.6.2",
"fxa-auth-server": "git://github.com/mozilla/fxa-auth-server.git",
"intern-geezer": "1.3.2",
"request": "~2.33.0",
"request": "2.33.0",
"xmlhttprequest": "git://github.com/zaach/node-XMLHttpRequest.git#onerror"
},
"engines": {

198
scripts/lockdown Executable file
Просмотреть файл

@ -0,0 +1,198 @@
#!/usr/bin/env node
if (process.env['NPM_LOCKDOWN_RUNNING']) process.exit(0);
console.log("NPM Lockdown is here to check your dependencies! Never fear!");
var http = require('http'),
crypto = require('crypto'),
exec = require('child_process').exec,
fs = require('fs'),
path = require('path');
try {
var lockdownJson = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'lockdown.json')));
} catch(e) {
console.log("\nERROR: I cannot read lockdown.json! run node_modules/.bin/lockdown-relock to generate!\n");
process.exit(1);
}
var boundPort;
// during execution fatal errors will be appended to this list
var errors = [];
// during execution non-fatal warnings will be appended to this list
var warn = [];
function rewriteURL(u) {
return u.replace('registry.npmjs.org', '127.0.0.1:' + boundPort);
}
function packageOk(name, ver, sha, required) {
if (!lockdownJson[name]) {
if (required) {
errors.push("package '" + name + "' not in lockdown.json!");
}
return false;
}
if (lockdownJson[name][ver] === undefined) {
if (required) {
errors.push("package version " + name + "@" + ver + " not in lockdown.json!");
}
return false;
}
// a '*' shasum is not checked
var wantSHA = lockdownJson[name][ver];
if (wantSHA !== '*' && wantSHA !== sha) {
if (required) {
errors.push("package " + name + "@" + ver + " has a different checksum (" +
wantSHA + " v. " + sha + ")");
}
return false;
}
if (wantSHA === '*') {
warn.push("Lockdown cannot guarantee your saftey! No sha for pkg " + name + "@" + ver +
" in lockdown.json");
}
return true;
}
function rewriteVersionMD(json) {
if (typeof json === 'string') json = JSON.parse(json);
if (!json.error) {
json.dist.tarball = rewriteURL(json.dist.tarball);
// is the name/version/sha in our lockdown.json?
if (!packageOk(json.name, json.version, json.dist.shasum, true)) return null;
}
return JSON.stringify(json);
}
function rewritePackageMD(json) {
if (typeof json === 'string') json = JSON.parse(json);
if (!json.error) {
Object.keys(json.versions).forEach(function(ver) {
var data = json.versions[ver];
var name = data.name;
var sha = data.dist ? data.dist.shasum : undefined;
if (packageOk(name, ver, sha, false)) {
data.dist.tarball = rewriteURL(data.dist.tarball);
} else {
delete json.versions[ver];
}
});
}
return JSON.stringify(json);
}
function copy(from, to) {
for (var k in from) {
to[k] = from[k];
}
return to;
}
var server = http.createServer(function (req, res) {
if (req.method !== 'GET') {
return res.end('non GET requests not supported', 501);
}
// what type of request is this?
// 1. specific version json metadata (when explicit dependency is expressed)
// - for these requests we should verify the name/version/sha advertised is allowed
// 2. package version json metadata (when version range is expressed - including '*')
// XXX: for these requests we should prune all versions that are not allowed
// 3. tarball - actual bits
// XXX: for these requests we should verify the name/version/sha matches something
// allowed, otherwise block the transaction
var arr = req.url.substr(1).split('/');
var type = [ '', 'package_metadata', 'version_metadata', 'tarball' ][arr.length];
// let's extract pkg name and version sensitive to the type of request being performed.
var pkgname, pkgver;
if (type === 'tarball') {
pkgname = arr[0];
var getVer = new RegExp("^" + pkgname + "-(.*)\\.tgz$");
pkgver = getVer.exec(arr[2])[1];
} else if (type === 'version_metadata') {
pkgname = arr[0];
pkgver = arr[1];
} else if (type === 'package_metadata') {
pkgname = arr[0];
}
var hash = crypto.createHash('sha1');
var r = http.request({
host: 'registry.npmjs.org',
port: 80,
method: req.method,
path: req.url,
agent: false
}, function(rres) {
res.setHeader('Content-Type', rres.headers['content-type']);
if (type === 'tarball') res.setHeader('Content-Length', rres.headers['content-length']);
var b = "";
rres.on('data', function(d) {
hash.update(d);
if (type != 'tarball') b += d;
else res.write(d);
});
rres.on('end', function() {
if (type === 'tarball') {
res.end();
} else {
if (type === 'package_metadata') {
b = rewritePackageMD(b);
} else if (type === 'version_metadata') {
b = rewriteVersionMD(b);
}
if (b === null) {
res.writeHead(404);
res.end("package installation disallowed by lockdown");
} else {
res.setHeader('Content-Length', Buffer.byteLength(b));
res.writeHead(rres.statusCode);
res.end(b);
}
}
});
});
r.end();
});
server.listen(process.env['LOCKDOWN_PORT'] || 0, '127.0.0.1', function() {
boundPort = server.address().port;
var env = copy(process.env, {
NPM_CONFIG_REGISTRY: 'http://127.0.0.1:' + boundPort,
NPM_LOCKDOWN_RUNNING: "true"
});
var child = exec('npm install', {
cwd: process.cwd(),
env: env
}, function(e) {
if (warn.length) {
console.log();
console.log("LOCKDOWN WARNINGS:");
warn.forEach(function(e) { console.log(" ", e); });
console.log();
}
if (errors.length) {
console.log();
console.log("LOCKDOWN ERRORS:");
errors.forEach(function(e) { console.log(" ", e); });
console.log();
}
process.exit(e ? 1 : 0);
});
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
});