mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-03-23 04:25:24 +00:00
Auto-merge for PR #641 via VersionBot
Convert errors and iptables modules to typescript
This commit is contained in:
commit
dab233f04b
@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file
|
||||
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## v7.10.1 - 2018-06-11
|
||||
|
||||
* Convert iptables module to typescript #641 [Cameron Diver]
|
||||
* Convert errors module to typescript #641 [Cameron Diver]
|
||||
|
||||
## v7.10.0 - 2018-06-06
|
||||
|
||||
* Move config backend code out to classes which implement a common base #672 [Cameron Diver]
|
||||
|
10
package.json
10
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "resin-supervisor",
|
||||
"description": "This is resin.io's Supervisor, a program that runs on IoT devices and has the task of running user Apps (which are Docker containers), and updating them as Resin's API informs it to.",
|
||||
"version": "7.10.0",
|
||||
"version": "7.10.1",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -16,16 +16,17 @@
|
||||
"coverage": "istanbul report text && istanbul report html"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/lodash": "^4.14.108",
|
||||
"@types/mz": "0.0.32",
|
||||
"mkfifo": "^0.1.5",
|
||||
"mz": "^2.7.0",
|
||||
"sqlite3": "^3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^6.13.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bluebird": "^3.5.20",
|
||||
"@types/lodash": "^4.14.109",
|
||||
"@types/mz": "0.0.32",
|
||||
"@types/node": "^10.3.1",
|
||||
"JSONStream": "^1.1.2",
|
||||
"blinking": "~0.0.2",
|
||||
"bluebird": "^3.5.0",
|
||||
@ -53,6 +54,7 @@
|
||||
"mkdirp": "^0.5.1",
|
||||
"mocha": "^5.1.1",
|
||||
"mochainon": "^2.0.0",
|
||||
"mz": "^2.7.0",
|
||||
"network-checker": "~0.0.5",
|
||||
"node-loader": "^0.6.0",
|
||||
"null-loader": "^0.1.1",
|
||||
|
@ -1,6 +0,0 @@
|
||||
{ checkInt } = require './validation'
|
||||
|
||||
exports.NotFoundError = (err) -> checkInt(err.statusCode) is 404
|
||||
exports.ENOENT = (err) -> err.code is 'ENOENT'
|
||||
exports.EEXIST = (err) -> err.code is 'EEXIST'
|
||||
exports.UnitNotLoadedError = (err) -> err[0]?.endsWith?('not loaded.')
|
19
src/lib/errors.ts
Normal file
19
src/lib/errors.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { endsWith } from 'lodash';
|
||||
|
||||
import { checkInt } from './validation';
|
||||
|
||||
export function NotFoundError(err: { statusCode?: string }): boolean {
|
||||
return checkInt(err.statusCode) === 404;
|
||||
}
|
||||
|
||||
export function ENOENT(err: { code: string, [key: string]: any }): boolean {
|
||||
return err.code === 'ENOENT';
|
||||
}
|
||||
|
||||
export function EEXISTS(err: { code: string, [key: string]: any }): boolean {
|
||||
return err.code === 'EEXISTS';
|
||||
}
|
||||
|
||||
export function UnitNotLoadedError(err: string[]): boolean {
|
||||
return endsWith(err[0], 'not loaded.');
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
Promise = require 'bluebird'
|
||||
childProcess = Promise.promisifyAll(require('child_process'))
|
||||
|
||||
clearAndAppendIptablesRule = (rule) ->
|
||||
childProcess.execAsync("iptables -D #{rule}")
|
||||
.catchReturn()
|
||||
.then ->
|
||||
childProcess.execAsync("iptables -A #{rule}")
|
||||
|
||||
clearAndInsertIptablesRule = (rule) ->
|
||||
childProcess.execAsync("iptables -D #{rule}")
|
||||
.catchReturn()
|
||||
.then ->
|
||||
childProcess.execAsync("iptables -I #{rule}")
|
||||
|
||||
exports.rejectOnAllInterfacesExcept = (allowedInterfaces, port) ->
|
||||
# We delete each rule and create it again to ensure ordering (all ACCEPTs before the REJECT/DROP).
|
||||
# This is especially important after a supervisor update.
|
||||
Promise.each allowedInterfaces, (iface) ->
|
||||
clearAndInsertIptablesRule("INPUT -p tcp --dport #{port} -i #{iface} -j ACCEPT")
|
||||
.then ->
|
||||
clearAndAppendIptablesRule("INPUT -p tcp --dport #{port} -j REJECT")
|
||||
.catch ->
|
||||
# On systems without REJECT support, fall back to DROP
|
||||
clearAndAppendIptablesRule("INPUT -p tcp --dport #{port} -j DROP")
|
32
src/lib/iptables.ts
Normal file
32
src/lib/iptables.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import * as Promise from 'bluebird';
|
||||
import * as childProcess from 'child_process';
|
||||
|
||||
// The following is exported so that we stub it in the tests
|
||||
export const execAsync = Promise.promisify(childProcess.exec);
|
||||
|
||||
function clearAndAppendIptablesRule(rule: string): Promise<void> {
|
||||
return execAsync(`iptables -D ${rule}`)
|
||||
.catchReturn(null)
|
||||
.then(() => execAsync(`iptables -A ${rule}`))
|
||||
.return();
|
||||
}
|
||||
|
||||
function clearAndInsertIptablesRule(rule: string): Promise<void> {
|
||||
return execAsync(`iptables -D ${rule}`)
|
||||
.catchReturn(null)
|
||||
.then(() => execAsync(`iptables -I ${rule}`))
|
||||
.return();
|
||||
}
|
||||
|
||||
export function rejectOnAllInterfacesExcept(
|
||||
allowedInterfaces: string[],
|
||||
port: number,
|
||||
): Promise<void> {
|
||||
// We delete each rule and create it again to ensure ordering (all ACCEPTs before the REJECT/DROP).
|
||||
// This is especially important after a supervisor update.
|
||||
return Promise.each(allowedInterfaces, (iface) => clearAndInsertIptablesRule(`INPUT -p tcp --dport ${port} -i ${iface} -j ACCEPT`))
|
||||
.then(() => clearAndAppendIptablesRule(`INPUT -p tcp --dport ${port} -j REJECT`))
|
||||
// On systems without REJECT support, fall back to DROP
|
||||
.catch(() => clearAndAppendIptablesRule(`INPUT -p tcp --dport ${port} -j DROP`))
|
||||
.return();
|
||||
}
|
@ -1,43 +1,41 @@
|
||||
Promise = require 'bluebird'
|
||||
iptables = require '../src/lib/iptables'
|
||||
|
||||
childProcess = require('child_process')
|
||||
|
||||
m = require 'mochainon'
|
||||
{ stub } = m.sinon
|
||||
{ expect } = m.chai
|
||||
|
||||
describe 'iptables', ->
|
||||
it 'calls iptables to delete and recreate rules to block a port', ->
|
||||
stub(childProcess, 'execAsync').returns(Promise.resolve())
|
||||
stub(iptables, 'execAsync').returns(Promise.resolve())
|
||||
iptables.rejectOnAllInterfacesExcept(['foo', 'bar'], 42)
|
||||
.then ->
|
||||
expect(childProcess.execAsync.callCount).to.equal(6)
|
||||
expect(childProcess.execAsync).to.be.calledWith('iptables -D INPUT -p tcp --dport 42 -i foo -j ACCEPT')
|
||||
expect(childProcess.execAsync).to.be.calledWith('iptables -I INPUT -p tcp --dport 42 -i foo -j ACCEPT')
|
||||
expect(childProcess.execAsync).to.be.calledWith('iptables -D INPUT -p tcp --dport 42 -i bar -j ACCEPT')
|
||||
expect(childProcess.execAsync).to.be.calledWith('iptables -I INPUT -p tcp --dport 42 -i bar -j ACCEPT')
|
||||
expect(childProcess.execAsync).to.be.calledWith('iptables -D INPUT -p tcp --dport 42 -j REJECT')
|
||||
expect(childProcess.execAsync).to.be.calledWith('iptables -A INPUT -p tcp --dport 42 -j REJECT')
|
||||
expect(iptables.execAsync.callCount).to.equal(6)
|
||||
expect(iptables.execAsync).to.be.calledWith('iptables -D INPUT -p tcp --dport 42 -i foo -j ACCEPT')
|
||||
expect(iptables.execAsync).to.be.calledWith('iptables -I INPUT -p tcp --dport 42 -i foo -j ACCEPT')
|
||||
expect(iptables.execAsync).to.be.calledWith('iptables -D INPUT -p tcp --dport 42 -i bar -j ACCEPT')
|
||||
expect(iptables.execAsync).to.be.calledWith('iptables -I INPUT -p tcp --dport 42 -i bar -j ACCEPT')
|
||||
expect(iptables.execAsync).to.be.calledWith('iptables -D INPUT -p tcp --dport 42 -j REJECT')
|
||||
expect(iptables.execAsync).to.be.calledWith('iptables -A INPUT -p tcp --dport 42 -j REJECT')
|
||||
.then ->
|
||||
childProcess.execAsync.restore()
|
||||
iptables.execAsync.restore()
|
||||
|
||||
it "falls back to blocking the port with DROP if there's no REJECT support", ->
|
||||
stub(childProcess, 'execAsync').callsFake (cmd) ->
|
||||
stub(iptables, 'execAsync').callsFake (cmd) ->
|
||||
if /REJECT$/.test(cmd)
|
||||
Promise.reject()
|
||||
else
|
||||
Promise.resolve()
|
||||
iptables.rejectOnAllInterfacesExcept(['foo', 'bar'], 42)
|
||||
.then ->
|
||||
expect(childProcess.execAsync.callCount).to.equal(8)
|
||||
expect(childProcess.execAsync).to.be.calledWith('iptables -D INPUT -p tcp --dport 42 -i foo -j ACCEPT')
|
||||
expect(childProcess.execAsync).to.be.calledWith('iptables -I INPUT -p tcp --dport 42 -i foo -j ACCEPT')
|
||||
expect(childProcess.execAsync).to.be.calledWith('iptables -D INPUT -p tcp --dport 42 -i bar -j ACCEPT')
|
||||
expect(childProcess.execAsync).to.be.calledWith('iptables -I INPUT -p tcp --dport 42 -i bar -j ACCEPT')
|
||||
expect(childProcess.execAsync).to.be.calledWith('iptables -D INPUT -p tcp --dport 42 -j REJECT')
|
||||
expect(childProcess.execAsync).to.be.calledWith('iptables -A INPUT -p tcp --dport 42 -j REJECT')
|
||||
expect(childProcess.execAsync).to.be.calledWith('iptables -D INPUT -p tcp --dport 42 -j DROP')
|
||||
expect(childProcess.execAsync).to.be.calledWith('iptables -A INPUT -p tcp --dport 42 -j DROP')
|
||||
expect(iptables.execAsync.callCount).to.equal(8)
|
||||
expect(iptables.execAsync).to.be.calledWith('iptables -D INPUT -p tcp --dport 42 -i foo -j ACCEPT')
|
||||
expect(iptables.execAsync).to.be.calledWith('iptables -I INPUT -p tcp --dport 42 -i foo -j ACCEPT')
|
||||
expect(iptables.execAsync).to.be.calledWith('iptables -D INPUT -p tcp --dport 42 -i bar -j ACCEPT')
|
||||
expect(iptables.execAsync).to.be.calledWith('iptables -I INPUT -p tcp --dport 42 -i bar -j ACCEPT')
|
||||
expect(iptables.execAsync).to.be.calledWith('iptables -D INPUT -p tcp --dport 42 -j REJECT')
|
||||
expect(iptables.execAsync).to.be.calledWith('iptables -A INPUT -p tcp --dport 42 -j REJECT')
|
||||
expect(iptables.execAsync).to.be.calledWith('iptables -D INPUT -p tcp --dport 42 -j DROP')
|
||||
expect(iptables.execAsync).to.be.calledWith('iptables -A INPUT -p tcp --dport 42 -j DROP')
|
||||
.then ->
|
||||
childProcess.execAsync.restore()
|
||||
iptables.execAsync.restore()
|
||||
|
Loading…
x
Reference in New Issue
Block a user