Last active
May 22, 2021 11:19
-
-
Save hilleer/fc122b3f6647f232dc95441a13d04c5e to your computer and use it in GitHub Desktop.
Fuck up story; rotating Heroku app serets using their CLI tool
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const childProcess = require('child_process'); | |
const { promisify } = require('util'); | |
const exec = promisify(childProcess.exec); | |
const DRY_RUN = true; // set to false when you want to execute it | |
const { NEW_SECRET } = process.env; // do not end up committing the new secret :-) | |
(async () => { | |
const { stdout: apps } = await exec('heroku apps -A --json'); | |
const appsWithSecret = []; | |
for (const app of JSON.parse(apps)) { | |
const { name } = app; | |
const { stdout: config } = await exec(`heroku config -a ${name} --json`); | |
const prodAppRegex = /^PROD-FOO/; | |
const isProdApp = (app) => app.name.test(prodAppRegex); // could also use a simple string comparison if fit your needs | |
const match = Object.entries(config).find((isProdApp)); | |
if (!match) { | |
continue; | |
} | |
appsWithSecret.push({ name, envVariable: match, otherPropsYouMightNeed }); | |
} | |
for (const app of appsWithSecret) { | |
const { name, envVariable } = app; | |
const [key, oldSecret] = envVariable; | |
if (DRY_RUN) { | |
const appSecret = await getAppSecret(name, key); | |
// could verify "oldSecret" === "appSecret" | |
} else { | |
const resultOldKey = await setAppSecret(appName, `${key}_old`, oldSecret); | |
const resultNewKey = await setAppSecret(appName, key, NEW_SECRET); | |
} | |
} | |
})(); | |
async function getAppSecret(appName, configVar) { | |
const { stdout: appSecret } = await exec(`heroku config:get ${configVar} -a ${appName}`); | |
// returns a string of the value | |
return appSecret; | |
} | |
async function setAppSecret(appName, configVar, newValue) { | |
const { stdout: result } = await exec(`heroku config:set ${configVar}=${newValue} -a ${appName}`); | |
// return a string like: | |
// Setting <configVar> and restarting ⬢ <appName>... done, <new app version> | |
// <configVar>: newValue | |
return result; | |
} | |
module.exports = { | |
setAppSecret | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const childProcess = require('child_process'); | |
const { promisify } = require('util'); | |
const { setAppSecret } = require('./addNewSecret'); | |
const exec = promisify(childProcess.exec); | |
// same approach as in addNewSecret with the difference that we look for the old key now: | |
// <configVar>_old and unset it using below function | |
async function unsetAppSecret(appName, configVar) { | |
const { stdout: result } = await exec(`heroku config:unset ${configVar} -a ${appName}`); | |
// returns a string like: | |
// Unsetting <configVar and restarting ⬢ <appName>... done, <new app version> | |
return result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment