mirror of
https://github.com/actions/runner-container-hooks.git
synced 2025-12-17 10:16:44 +00:00
Pass secrets more securely for container action
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { podPrune } from '../k8s'
|
||||
import { pruneSecrets, prunePods } from '../k8s'
|
||||
|
||||
export async function cleanupJob(): Promise<void> {
|
||||
await podPrune()
|
||||
await prunePods()
|
||||
await pruneSecrets()
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export function getJobPodName(): string {
|
||||
export function getStepPodName(): string {
|
||||
return `${getRunnerPodName().substring(
|
||||
0,
|
||||
MAX_POD_NAME_LENGTH - ('-step'.length + STEP_POD_NAME_SUFFIX_LENGTH)
|
||||
MAX_POD_NAME_LENGTH - ('-step-'.length + STEP_POD_NAME_SUFFIX_LENGTH)
|
||||
)}-step-${uuidv4().substring(0, STEP_POD_NAME_SUFFIX_LENGTH)}`
|
||||
}
|
||||
|
||||
@@ -34,6 +34,13 @@ export function getVolumeClaimName(): string {
|
||||
return name
|
||||
}
|
||||
|
||||
export function getSecretName(): string {
|
||||
return `${getRunnerPodName().substring(
|
||||
0,
|
||||
MAX_POD_NAME_LENGTH - ('-secret-'.length + STEP_POD_NAME_SUFFIX_LENGTH)
|
||||
)}-secret-${uuidv4().substring(0, STEP_POD_NAME_SUFFIX_LENGTH)}`
|
||||
}
|
||||
|
||||
const MAX_POD_NAME_LENGTH = 63
|
||||
const STEP_POD_NAME_SUFFIX_LENGTH = 8
|
||||
export const JOB_CONTAINER_NAME = 'job'
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
isAuthPermissionsOK,
|
||||
isPodContainerAlpine,
|
||||
namespace,
|
||||
podPrune,
|
||||
prunePods,
|
||||
requiredPermissions,
|
||||
waitForPodPhases
|
||||
} from '../k8s'
|
||||
@@ -29,7 +29,7 @@ export async function prepareJob(
|
||||
args: prepareJobArgs,
|
||||
responseFile
|
||||
): Promise<void> {
|
||||
await podPrune()
|
||||
await prunePods()
|
||||
if (!(await isAuthPermissionsOK())) {
|
||||
throw new Error(
|
||||
`The Service account needs the following permissions ${JSON.stringify(
|
||||
@@ -58,7 +58,7 @@ export async function prepareJob(
|
||||
try {
|
||||
createdPod = await createPod(container, services, args.registry)
|
||||
} catch (err) {
|
||||
await podPrune()
|
||||
await prunePods()
|
||||
throw new Error(`failed to create job pod: ${JSON.stringify(err)}`)
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ export async function prepareJob(
|
||||
new Set([PodPhase.PENDING])
|
||||
)
|
||||
} catch (err) {
|
||||
await podPrune()
|
||||
await prunePods()
|
||||
throw new Error(`Pod failed to come online with error: ${err}`)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import * as core from '@actions/core'
|
||||
import { PodPhase } from 'hooklib'
|
||||
import {
|
||||
createJob,
|
||||
createSecretForEnvs,
|
||||
getContainerJobPodName,
|
||||
getPodLogs,
|
||||
getPodStatus,
|
||||
@@ -16,7 +17,13 @@ export async function runContainerStep(stepContainer): Promise<number> {
|
||||
if (stepContainer.dockerfile) {
|
||||
throw new Error('Building container actions is not currently supported')
|
||||
}
|
||||
const container = createPodSpec(stepContainer)
|
||||
let secretName: string | undefined = undefined
|
||||
if (stepContainer['environmentVariables']) {
|
||||
secretName = await createSecretForEnvs(
|
||||
stepContainer['environmentVariables']
|
||||
)
|
||||
}
|
||||
const container = createPodSpec(stepContainer, secretName)
|
||||
const job = await createJob(container)
|
||||
if (!job.metadata?.name) {
|
||||
throw new Error(
|
||||
@@ -39,28 +46,28 @@ export async function runContainerStep(stepContainer): Promise<number> {
|
||||
core.warning(`Can't determine container status`)
|
||||
return 0
|
||||
}
|
||||
|
||||
const exitCode =
|
||||
status.containerStatuses[status.containerStatuses.length - 1].state
|
||||
?.terminated?.exitCode
|
||||
return Number(exitCode) || 0
|
||||
}
|
||||
|
||||
function createPodSpec(container): k8s.V1Container {
|
||||
function createPodSpec(container, secretName?: string): k8s.V1Container {
|
||||
const podContainer = new k8s.V1Container()
|
||||
podContainer.name = JOB_CONTAINER_NAME
|
||||
podContainer.image = container.image
|
||||
if (container.entryPoint) {
|
||||
podContainer.command = [container.entryPoint, ...container.entryPointArgs]
|
||||
}
|
||||
|
||||
podContainer.env = []
|
||||
for (const [key, value] of Object.entries(
|
||||
container['environmentVariables']
|
||||
)) {
|
||||
if (value && key !== 'HOME') {
|
||||
podContainer.env.push({ name: key, value: value as string })
|
||||
}
|
||||
if (secretName) {
|
||||
podContainer.envFrom = [
|
||||
{
|
||||
secretRef: {
|
||||
name: secretName,
|
||||
optional: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
podContainer.volumeMounts = containerVolumes()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user