fxa-auth-server/bin/key_server.js

188 строки
5.0 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict'
// This MUST be the first require in the program.
// Only `require()` the newrelic module if explicity enabled.
// If required, modules will be instrumented.
require('../lib/newrelic')()
var jwtool = require('fxa-jwtool')
var P = require('../lib/promise')
function run(config) {
var log = require('../lib/log')(config.log)
var getGeoData = require('../lib/geodb')(log)
// Force the geo to load and run at startup, not waiting for it to run on
// some route later.
const knownIp = '63.245.221.32' // Mozilla MTV
const location = getGeoData(knownIp)
log.info({ op: 'geodb.check', result: location })
// RegExp instances serialise to empty objects, display regex strings instead.
const stringifiedConfig =
JSON.stringify(config, (k, v) =>
v && v.constructor === RegExp ? v.toString() : v
)
if (config.env !== 'prod') {
log.info(stringifiedConfig, 'starting config')
}
var error = require('../lib/error')
var Token = require('../lib/tokens')(log, config)
var Password = require('../lib/crypto/password')(log, config)
var UnblockCode = require('../lib/crypto/random').base32(config.signinUnblock.codeLength)
var signer = require('../lib/signer')(config.secretKeyFile, config.domain)
var serverPublicKeys = {
primary: jwtool.JWK.fromFile(
config.publicKeyFile,
{
algorithm: 'RS',
use: 'sig',
kty: 'RSA'
}
),
secondary: config.oldPublicKeyFile ?
jwtool.JWK.fromFile(
config.oldPublicKeyFile,
{
algorithm: 'RS',
use: 'sig',
kty: 'RSA'
}
)
: null
}
var Customs = require('../lib/customs')(log, error)
var Server = require('../lib/server')
var server = null
var senders = null
var statsInterval = null
var database = null
var customs = null
function logStatInfo() {
log.stat(server.stat())
log.stat(Password.stat())
}
var DB = require('../lib/db')(
config,
log,
Token,
UnblockCode
)
return P.all([
DB.connect(config[config.db.backend]),
require('../lib/senders/translator')(config.i18n.supportedLanguages, config.i18n.defaultLanguage)
])
.spread(
(db, translator) => {
database = db
const bounces = require('../lib/bounces')(config, db)
return require('../lib/senders')(log, config, error, bounces, translator)
.then(result => {
senders = result
customs = new Customs(config.customsUrl)
var routes = require('../lib/routes')(
log,
serverPublicKeys,
signer,
db,
senders.email,
senders.sms,
Password,
config,
customs
)
statsInterval = setInterval(logStatInfo, 15000)
async function init() {
server = await Server.create(log, error, config, routes, db, translator)
try {
await server.start()
log.info({op: 'server.start.1', msg: 'running on ' + server.info.uri})
} catch (err) {
log.error(
{
op: 'server.start.1', msg: 'failed startup with error',
err: {message: err.message}
}
)
}
}
init()
})
},
function (err) {
log.error({ op: 'DB.connect', err: { message: err.message } })
process.exit(1)
}
)
.then(() => {
return {
log: log,
close() {
return new P((resolve) => {
log.info({ op: 'shutdown' })
clearInterval(statsInterval)
server.stop().then(() => {
customs.close()
try {
senders.email.stop()
} catch (e) {
// XXX: simplesmtp module may quit early and set socket to `false`, stopping it may fail
log.warn({op: 'shutdown', message: 'Mailer client already disconnected'})
}
database.close()
resolve()
})
})
}
}
})
}
function main() {
const config = require('../config').getProperties()
run(config).then(server => {
process.on('uncaughtException', (err) => {
server.log.fatal(err)
process.exit(8)
})
process.on('unhandledRejection', (reason, promise) => {
server.log.fatal({
op: 'promise.unhandledRejection',
error: reason
})
})
process.on('SIGINT', shutdown)
server.log.on('error', shutdown)
function shutdown() {
server.close().then(() => {
process.exit() //XXX: because of openid dep ಠ_ಠ
})
}
})
.catch(process.exit.bind(null, 8))
}
if (require.main === module) {
main()
} else {
module.exports = run
}