packages/fxa-profile-server/lib/config.js (377 lines of code) (raw):

/* 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/. */ const fs = require('fs'); const path = require('path'); const tracing = require('fxa-shared/tracing/config'); const convict = require('convict'); const convict_format_with_validator = require('convict-format-with-validator'); const convict_format_with_moment = require('convict-format-with-moment'); convict.addFormats(convict_format_with_validator); convict.addFormats(convict_format_with_moment); const tracingConfig = tracing.tracingConfig; const conf = convict({ api: { version: { doc: 'Version number prepended to API routes', default: 1, }, }, authServer: { url: { doc: 'URL of fxa-auth-server', env: 'AUTH_SERVER_URL', default: 'http://localhost:9000/v1', }, }, clientAddressDepth: { doc: 'location of the client ip address in the remote address chain', format: Number, env: 'CLIENT_ADDRESS_DEPTH', default: 3, }, corsOrigin: { doc: 'Value for the Access-Control-Allow-Origin response header', format: Array, env: 'CORS_ORIGIN', default: ['*'], }, db: { driver: { env: 'DB', format: ['mysql', 'memory'], default: 'memory', }, }, env: { arg: 'node-env', doc: 'The current node.js environment', env: 'NODE_ENV', format: ['development', 'test', 'stage', 'production'], default: 'production', }, events: { enabled: { doc: 'Whether or not config.events has to be properly set in production', format: Boolean, default: true, env: 'EVENTS_ENABLED', }, region: { doc: 'AWS Region of fxa account events', format: String, default: '', env: 'EVENTS_REGION', }, queueUrl: { doc: 'SQS queue url for fxa account events', format: String, default: '', env: 'EVENTS_QUEUE_URL', }, }, img: { driver: { env: 'IMG', format: ['local', 'aws'], default: 'aws', }, providers: { gravatar: { doc: 'Patterns to match a URL to ensure we only accept Gravatar URLs.', default: '^https://secure\\.gravatar\\.com' + '/avatar/[0-9a-f]{32}(\\?s=\\d+)?$', }, fxa: { doc: 'Patterns to match a URL to ensure we only accept certain URLs.', default: '^http://localhost:1112/a/[0-9a-f]{32}$', env: 'IMG_PROVIDERS_FXA', }, }, uploads: { cacheControlSeconds: { doc: 'Number of seconds in Cache-Control: max-age=seconds header', default: '31536000', // One year env: 'IMG_UPLOADS_CACHE_CONTROL_SECONDS', }, dest: { public: { doc: 'Path or bucket name for images to be served publicly.', default: 'BUCKET_NAME', env: 'IMG_UPLOADS_DEST_PUBLIC', }, }, maxSize: { doc: 'Maximum bytes allow for uploads', default: 1024 * 1024 * 2, // 2MB env: 'IMG_UPLOADS_DEST_MAX_SIZE', }, types: { doc: 'A mapping of allowed mime types and their file signatures', format: Object, default: { // see https://en.wikipedia.org/wiki/List_of_file_signatures 'image/jpeg': [ [0xff, 0xd8, 0xff, 0xdb], [0xff, 0xd8, 0xff, 0xe0], [0xff, 0xd8, 0xff, 0xe1], ], 'image/png': [[0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]], }, }, }, compute: { maxBacklog: { default: 500, }, maxRequestTime: { doc: 'seconds we will let the user wait before returning a 503', format: 'duration', default: 10, }, maxProcesses: { doc: 'max child processes for compute-cluster', default: Math.ceil(require('os').cpus().length * 1.25), env: 'IMG_COMPUTE_MAX_PROCESSES', }, }, url: { doc: 'Pattern to generate FxA avatar URLs. {id} will be replaced.', default: 'http://localhost:1112/a/{id}', env: 'IMG_URL', }, defaultAvatarId: { default: '00000000000000000000000000000000', doc: 'Default avatar id', env: 'DEFAULT_AVATAR_ID', format: String, }, }, logging: { app: { default: 'fxa-profile-server', }, fmt: { format: ['heka', 'pretty'], default: 'heka', }, level: { env: 'LOG_LEVEL', default: 'info', }, debug: { env: 'LOG_DEBUG', default: false, }, }, mysql: { createSchema: { env: 'CREATE_MYSQL_SCHEMA', default: true, }, user: { default: 'root', env: 'MYSQL_USERNAME', }, password: { default: '', sensitive: true, env: 'MYSQL_PASSWORD', }, database: { default: 'fxa_profile', env: 'MYSQL_DATABASE', }, host: { default: 'localhost', env: 'MYSQL_HOST', }, port: { default: '3306', env: 'MYSQL_PORT', }, connectionLimit: { default: 10, env: 'MYSQL_CONNECTION_LIMIT', }, queueLimit: { default: 0, env: 'MYSQL_QUEUE_LIMIT', }, }, oauth: { url: { doc: 'URL of fxa-oauth-server', env: 'OAUTH_SERVER_URL', default: 'http://localhost:9000/v1', }, }, customsUrl: { doc: 'fraud / abuse server url', default: 'none', env: 'CUSTOMS_SERVER_URL', }, publicUrl: { format: 'url', env: 'PUBLIC_URL', default: 'http://localhost:1111', }, server: { host: { env: 'HOST', default: 'localhost', }, port: { env: 'PORT', format: 'port', default: 1111, }, }, worker: { host: { env: 'WORKER_HOST', default: 'localhost', }, port: { env: 'WORKER_PORT', format: 'port', default: 1113, }, url: { default: 'http://localhost:1113', env: 'WORKER_URL', }, headers_exclude: { doc: 'HTTP headers to not pass through to the worker requests (in lower case)', format: Array, env: 'WORKER_HEADERS_EXCLUDE', default: ['host'], }, }, authServerMessaging: { region: { doc: 'The region where the queues live', format: String, env: 'AUTH_SERVER_MESSAGING_REGION', default: '', }, profileUpdatesQueueUrl: { doc: 'The queue URL to use (should include https://sqs.<region>.amazonaws.com/<account-id>/<queue-name>)', format: String, env: 'PROFILE_UPDATES_QUEUE_URL', default: '', }, }, serverCache: { redis: { host: { default: 'localhost', env: 'REDIS_HOST', format: String, doc: 'Url for redis host', }, keyPrefix: { default: 'fxa-profile', env: 'REDIS_KEY_PREFIX', format: String, doc: 'which redis key prefix to use for hapi server cache', }, port: { default: 6379, env: 'REDIS_PORT', format: 'port', doc: 'port for redis server', }, password: { default: '', env: 'REDIS_PASSWORD', format: String, sensitive: true, doc: 'Redis password', }, }, useRedis: { default: true, doc: 'Enable redis cache', format: Boolean, env: 'USE_REDIS', }, expiresIn: { default: '1 hour', format: 'duration', env: 'CACHE_EXPIRES_IN', doc: 'how long before cached resources expire', }, generateTimeout: { default: '11 seconds', format: 'duration', env: 'CACHE_GENERATE_TIMEOUT', doc: 'how long catbox will wait for a value from db to cache before timing out', }, }, sentry: { dsn: { doc: 'Sentry DSN for error and log reporting', default: '', format: 'String', env: 'SENTRY_DSN', }, env: { doc: 'Environment name to report to sentry', default: 'local', format: ['local', 'ci', 'dev', 'stage', 'prod'], env: 'SENTRY_ENV', }, serverName: { doc: 'Name used by sentry to identify the server.', default: 'fxa-profile-server', format: 'String', env: 'SENTRY_SERVER_NAME', }, sampleRate: { doc: 'Rate at which sentry errors are captured', default: 1.0, format: 'Number', env: 'SENTRY_SAMPLE_RATE', }, tracesSampleRate: { doc: 'Rate at which sentry traces are captured', default: 0, format: 'Number', env: 'SENTRY_TRACES_SAMPLE_RATE', }, }, secretBearerToken: { default: 'supersecret', doc: 'Secret for server-to-server bearer token auth', env: 'AUTH_SECRET_BEARER_TOKEN', format: 'String', }, tracing: tracingConfig, }); var envConfig = path.join(__dirname, '..', 'config', conf.get('env') + '.json'); var files = (envConfig + ',' + process.env.CONFIG_FILES) .split(',') .filter(fs.existsSync); conf.loadFile(files); if ( conf.get('img.driver') === 'local' && conf.get('img.uploads.dest.public') === 'BUCKET_NAME' ) { conf.set( 'img.uploads.dest.public', path.join(__dirname, '..', 'var', 'public') ); } if (conf.get('env') === 'test') { process.env.AWS_ACCESS_KEY_ID = 'TESTME'; process.env.AWS_SECRET_ACCESS_KEY = 'TESTME'; } process.env.NODE_ENV = conf.get('env'); var options = { allowed: 'strict', }; conf.validate(options); conf.toString = function () { // RegExp instances serialise to empty objects, display regex strings instead. return JSON.stringify(conf.getProperties(), (k, v) => v && v.constructor === RegExp ? v.toString() : v ); }; module.exports = conf;