mirror of
https://github.com/jdx/mise-action.git
synced 2026-05-14 22:00:34 +00:00
fix: redact secret values from env (#252)
This commit is contained in:
parent
8a7168b4f6
commit
5e785b73cb
6 changed files with 228 additions and 5 deletions
72
.github/workflows/test-redacted-env.yml
vendored
Normal file
72
.github/workflows/test-redacted-env.yml
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
name: Test Redacted Environment Variables
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test-redacted-env:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Create test mise config with sensitive values
|
||||
run: |
|
||||
cat > .mise.toml << 'EOF'
|
||||
[env]
|
||||
PUBLIC_VAR = "this-is-public"
|
||||
API_KEY = {value = "secret-api-key-12345", redact = true}
|
||||
SECRET_TOKEN = {value = "supersecret-token-xyz", redact = true}
|
||||
DATABASE_PASSWORD = {value = "db-pass-789", redact = true}
|
||||
EOF
|
||||
|
||||
- name: Setup mise
|
||||
uses: ./
|
||||
|
||||
- name: Verify environment variables are exported
|
||||
run: |
|
||||
echo "Checking if environment variables are set..."
|
||||
|
||||
# Check that public var is set
|
||||
if [ "$PUBLIC_VAR" != "this-is-public" ]; then
|
||||
echo "ERROR: PUBLIC_VAR not set correctly"
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ PUBLIC_VAR is set correctly"
|
||||
|
||||
# Check that sensitive vars are set (but their values should be masked in logs)
|
||||
if [ -z "$API_KEY" ]; then
|
||||
echo "ERROR: API_KEY not set"
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ API_KEY is set"
|
||||
|
||||
if [ -z "$SECRET_TOKEN" ]; then
|
||||
echo "ERROR: SECRET_TOKEN not set"
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ SECRET_TOKEN is set"
|
||||
|
||||
if [ -z "$DATABASE_PASSWORD" ]; then
|
||||
echo "ERROR: DATABASE_PASSWORD not set"
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ DATABASE_PASSWORD is set"
|
||||
|
||||
- name: Test that sensitive values are masked (will show *** if properly masked)
|
||||
run: |
|
||||
echo "Testing value masking..."
|
||||
echo "API_KEY value: $API_KEY"
|
||||
echo "SECRET_TOKEN value: $SECRET_TOKEN"
|
||||
echo "DATABASE_PASSWORD value: $DATABASE_PASSWORD"
|
||||
echo "PUBLIC_VAR value: $PUBLIC_VAR"
|
||||
|
||||
# This should show the actual values in the step output,
|
||||
# but GitHub Actions should mask them if core.setSecret was called
|
||||
|
||||
- name: Verify mise version
|
||||
run: mise --version
|
||||
69
dist/index.js
generated
vendored
69
dist/index.js
generated
vendored
|
|
@ -50028,8 +50028,7 @@ async function run() {
|
|||
await miseLs();
|
||||
const loadEnv = core.getBooleanInput('env');
|
||||
if (loadEnv) {
|
||||
const output = await exec.getExecOutput('mise', ['env', '--dotenv']);
|
||||
fs.appendFileSync(process.env.GITHUB_ENV, output.stdout);
|
||||
await exportMiseEnv();
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
|
|
@ -50039,6 +50038,72 @@ async function run() {
|
|||
throw err;
|
||||
}
|
||||
}
|
||||
async function exportMiseEnv() {
|
||||
core.startGroup('Exporting mise environment variables');
|
||||
// Check if mise supports --redacted flags based on version input
|
||||
const supportsRedacted = checkMiseSupportsRedacted();
|
||||
if (supportsRedacted) {
|
||||
try {
|
||||
// First, get the redacted values to identify what needs masking
|
||||
const redactedOutput = await exec.getExecOutput('mise', ['env', '--redacted', '--json'], { silent: true });
|
||||
const redactedVars = JSON.parse(redactedOutput.stdout);
|
||||
// Mask sensitive values in GitHub Actions
|
||||
for (const [key, actualValue] of Object.entries(redactedVars)) {
|
||||
core.setSecret(actualValue);
|
||||
core.info(`Masked sensitive value for: ${key}`);
|
||||
}
|
||||
// Then get the actual values
|
||||
const actualOutput = await exec.getExecOutput('mise', ['env', '--json']);
|
||||
const actualVars = JSON.parse(actualOutput.stdout);
|
||||
// Export all environment variables
|
||||
for (const [key, value] of Object.entries(actualVars)) {
|
||||
if (typeof value === 'string') {
|
||||
core.exportVariable(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// Fall back to dotenv format if the redacted command fails
|
||||
core.info('Falling back to dotenv format');
|
||||
const output = await exec.getExecOutput('mise', ['env', '--dotenv']);
|
||||
fs.appendFileSync(process.env.GITHUB_ENV, output.stdout);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Fall back to the old --dotenv format for older versions
|
||||
const output = await exec.getExecOutput('mise', ['env', '--dotenv']);
|
||||
fs.appendFileSync(process.env.GITHUB_ENV, output.stdout);
|
||||
}
|
||||
core.endGroup();
|
||||
}
|
||||
function checkMiseSupportsRedacted() {
|
||||
const version = core.getInput('version');
|
||||
// If no version is specified, assume latest which supports redacted
|
||||
if (!version) {
|
||||
return true;
|
||||
}
|
||||
// Parse the version string (remove 'v' prefix if present)
|
||||
const cleanVersion = version.replace(/^v/, '');
|
||||
const versionMatch = cleanVersion.match(/^(\d+)\.(\d+)\.(\d+)/);
|
||||
if (!versionMatch) {
|
||||
// If we can't parse the version, assume it supports redacted
|
||||
return true;
|
||||
}
|
||||
const [, year, month, patch] = versionMatch;
|
||||
const yearNum = parseInt(year, 10);
|
||||
const monthNum = parseInt(month, 10);
|
||||
const patchNum = parseInt(patch, 10);
|
||||
// Check if version is >= 2025.8.17
|
||||
if (yearNum > 2025)
|
||||
return true;
|
||||
if (yearNum === 2025) {
|
||||
if (monthNum > 8)
|
||||
return true;
|
||||
if (monthNum === 8 && patchNum >= 17)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
async function setEnvVars() {
|
||||
core.startGroup('Setting env vars');
|
||||
const set = (k, v) => {
|
||||
|
|
|
|||
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
7
package-lock.json
generated
7
package-lock.json
generated
|
|
@ -13,6 +13,7 @@
|
|||
"@actions/core": "^1.11.1",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/glob": "^0.5.0",
|
||||
"@types/handlebars": "^4.0.40",
|
||||
"handlebars": "^4.7.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -1912,6 +1913,12 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/handlebars": {
|
||||
"version": "4.0.40",
|
||||
"resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.40.tgz",
|
||||
"integrity": "sha512-sGWNtsjNrLOdKha2RV1UeF8+UbQnPSG7qbe5wwbni0mw4h2gHXyPFUMOC+xwGirIiiydM/HSqjDO4rk6NFB18w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/istanbul-lib-coverage": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
"@actions/core": "^1.11.1",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/glob": "^0.5.0",
|
||||
"@types/handlebars": "^4.0.40",
|
||||
"handlebars": "^4.7.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
82
src/index.ts
82
src/index.ts
|
|
@ -71,8 +71,7 @@ async function run(): Promise<void> {
|
|||
await miseLs()
|
||||
const loadEnv = core.getBooleanInput('env')
|
||||
if (loadEnv) {
|
||||
const output = await exec.getExecOutput('mise', ['env', '--dotenv'])
|
||||
fs.appendFileSync(process.env.GITHUB_ENV!, output.stdout)
|
||||
await exportMiseEnv()
|
||||
}
|
||||
} catch (err) {
|
||||
if (err instanceof Error) core.setFailed(err.message)
|
||||
|
|
@ -80,6 +79,85 @@ async function run(): Promise<void> {
|
|||
}
|
||||
}
|
||||
|
||||
async function exportMiseEnv(): Promise<void> {
|
||||
core.startGroup('Exporting mise environment variables')
|
||||
|
||||
// Check if mise supports --redacted flags based on version input
|
||||
const supportsRedacted = checkMiseSupportsRedacted()
|
||||
|
||||
if (supportsRedacted) {
|
||||
try {
|
||||
// First, get the redacted values to identify what needs masking
|
||||
const redactedOutput = await exec.getExecOutput(
|
||||
'mise',
|
||||
['env', '--redacted', '--json'],
|
||||
{ silent: true }
|
||||
)
|
||||
const redactedVars = JSON.parse(redactedOutput.stdout)
|
||||
|
||||
// Mask sensitive values in GitHub Actions
|
||||
for (const [key, actualValue] of Object.entries(redactedVars)) {
|
||||
core.setSecret(actualValue as string)
|
||||
core.info(`Masked sensitive value for: ${key}`)
|
||||
}
|
||||
|
||||
// Then get the actual values
|
||||
const actualOutput = await exec.getExecOutput('mise', ['env', '--json'])
|
||||
const actualVars = JSON.parse(actualOutput.stdout)
|
||||
|
||||
// Export all environment variables
|
||||
for (const [key, value] of Object.entries(actualVars)) {
|
||||
if (typeof value === 'string') {
|
||||
core.exportVariable(key, value)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Fall back to dotenv format if the redacted command fails
|
||||
core.info('Falling back to dotenv format')
|
||||
const output = await exec.getExecOutput('mise', ['env', '--dotenv'])
|
||||
fs.appendFileSync(process.env.GITHUB_ENV!, output.stdout)
|
||||
}
|
||||
} else {
|
||||
// Fall back to the old --dotenv format for older versions
|
||||
const output = await exec.getExecOutput('mise', ['env', '--dotenv'])
|
||||
fs.appendFileSync(process.env.GITHUB_ENV!, output.stdout)
|
||||
}
|
||||
|
||||
core.endGroup()
|
||||
}
|
||||
|
||||
function checkMiseSupportsRedacted(): boolean {
|
||||
const version = core.getInput('version')
|
||||
|
||||
// If no version is specified, assume latest which supports redacted
|
||||
if (!version) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Parse the version string (remove 'v' prefix if present)
|
||||
const cleanVersion = version.replace(/^v/, '')
|
||||
const versionMatch = cleanVersion.match(/^(\d+)\.(\d+)\.(\d+)/)
|
||||
|
||||
if (!versionMatch) {
|
||||
// If we can't parse the version, assume it supports redacted
|
||||
return true
|
||||
}
|
||||
|
||||
const [, year, month, patch] = versionMatch
|
||||
const yearNum = parseInt(year, 10)
|
||||
const monthNum = parseInt(month, 10)
|
||||
const patchNum = parseInt(patch, 10)
|
||||
|
||||
// Check if version is >= 2025.8.17
|
||||
if (yearNum > 2025) return true
|
||||
if (yearNum === 2025) {
|
||||
if (monthNum > 8) return true
|
||||
if (monthNum === 8 && patchNum >= 17) return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
async function setEnvVars(): Promise<void> {
|
||||
core.startGroup('Setting env vars')
|
||||
const set = (k: string, v: string): void => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue