diff --git a/src/services.js b/src/services.js index ad92f28ec..690a6c018 100644 --- a/src/services.js +++ b/src/services.js @@ -47,6 +47,7 @@ const addonConfigs = require('./addonconfigs.js'), infra = require('./infra_version.js'), logs = require('./logs.js'), mail = require('./mail.js'), + oidc = require('./oidc.js'), os = require('os'), path = require('path'), paths = require('./paths.js'), @@ -173,7 +174,14 @@ const ADDONS = { backup: NOOP, restore: NOOP, clear: NOOP, - } + }, + oidc: { + setup: setupOidc, + teardown: teardownOidc, + backup: NOOP, + restore: setupOidc, + clear: NOOP, + }, }; // services are actual containers that are running. addons are the concepts requested by app @@ -790,9 +798,26 @@ async function getEnvironment(app) { const result = await addonConfigs.getByAppId(app.id); - if (app.manifest.addons['docker']) result.push({ name: 'CLOUDRON_DOCKER_HOST', value: `tcp://172.18.0.1:${constants.DOCKER_PROXY_PORT}` }); + // convert result to object to ensure unique env names if we overwrite static ones from the previously stored value in addonconfigs + const env = {}; + result.forEach(e => { env[e.name] = e.value; }); - return result.map(function (e) { return e.name + '=' + e.value; }); + if (app.manifest.addons['docker']) env['CLOUDRON_DOCKER_HOST'] = `tcp://172.18.0.1:${constants.DOCKER_PROXY_PORT}`; + + if (app.manifest.addons['oidc']) { + env['CLOUDRON_OIDC_DISCOVERY_URL'] = `https://${settings.dashboardFqdn()}/.well-known/openid-configuration`; + env['CLOUDRON_OIDC_AUTH_ENDPOINT'] = `https://${settings.dashboardFqdn()}/openid/auth`; + env['CLOUDRON_OIDC_TOKEN_ENDPOINT'] = `https://${settings.dashboardFqdn()}/openid/token`; + env['CLOUDRON_OIDC_KEYS_ENDPOINT'] = `https://${settings.dashboardFqdn()}/openid/jwks`; + env['CLOUDRON_OIDC_PROFILE_ENDPOINT'] = `https://${settings.dashboardFqdn()}/openid/me`; + env['CLOUDRON_OIDC_LOGOUT_URL'] = `https://${settings.dashboardFqdn()}/openid/session/env`; + + const client = await oidc.clients.get(app.id); + env['CLOUDRON_OIDC_CLIENT_ID'] = client.id; + env['CLOUDRON_OIDC_CLIENT_SECRET'] = client.secret; + } + + return Object.keys(env).map(function (e) { return e + '=' + env[e]; }); } function getContainerNamesSync(app, addons) { @@ -1903,3 +1928,33 @@ async function teardownOauth(app, options) { await addonConfigs.unset(app.id, 'oauth'); } + +async function setupOidc(app, options) { + assert.strictEqual(typeof app, 'object'); + assert.strictEqual(typeof options, 'object'); + + if (!app.sso) return; + + debug('Setting up OpenID connect'); + + const data = { + secret: hat(4 * 128), + loginRedirectUri: options.loginRedirectUri, + logoutRedirectUri: options.logoutRedirectUri || '', + name: '', + appId: app.id + }; + + // openid client_id is appId for now + await oidc.clients.add(app.id, data); +} + +async function teardownOidc(app, options) { + assert.strictEqual(typeof app, 'object'); + assert.strictEqual(typeof options, 'object'); + + debug('Tearing down OpenID connect'); + + const [error] = await safe(oidc.clients.del(app.id)); + if (error && error.reason !== BoxError.NOT_FOUND) throw error; +}