From 560eab96f0604fcac0e2d78fae350f120d7cc05b Mon Sep 17 00:00:00 2001 From: Patrick Schratz Date: Sat, 2 Nov 2024 18:07:27 +0100 Subject: [PATCH] Kubernetes | Docker: Add support for rootless images (#4151) --- pipeline/backend/common/script.go | 2 - pipeline/backend/common/script_posix.go | 2 + pipeline/backend/common/script_posix_test.go | 2 + pipeline/backend/common/script_test.go | 6 +- pipeline/backend/common/script_win.go | 5 +- pipeline/backend/common/script_win_test.go | 5 +- pipeline/backend/docker/convert_test.go | 13 +- pipeline/backend/kubernetes/kubernetes.go | 2 + pipeline/backend/kubernetes/pod.go | 15 +- pipeline/backend/kubernetes/pod_test.go | 31 ++-- pipeline/backend/types/step.go | 1 + .../frontend/yaml/compiler/compiler_test.go | 164 +++++++++--------- pipeline/frontend/yaml/compiler/convert.go | 1 + 13 files changed, 135 insertions(+), 114 deletions(-) diff --git a/pipeline/backend/common/script.go b/pipeline/backend/common/script.go index 5ad13a477..c98a19393 100644 --- a/pipeline/backend/common/script.go +++ b/pipeline/backend/common/script.go @@ -22,13 +22,11 @@ func GenerateContainerConf(commands []string, goos string) (env map[string]strin env = make(map[string]string) if goos == "windows" { env["CI_SCRIPT"] = base64.StdEncoding.EncodeToString([]byte(generateScriptWindows(commands))) - env["HOME"] = "c:\\root" env["SHELL"] = "powershell.exe" // cspell:disable-next-line entry = []string{"powershell", "-noprofile", "-noninteractive", "-command", "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Env:CI_SCRIPT)) | iex"} } else { env["CI_SCRIPT"] = base64.StdEncoding.EncodeToString([]byte(generateScriptPosix(commands))) - env["HOME"] = "/root" env["SHELL"] = "/bin/sh" entry = []string{"/bin/sh", "-c", "echo $CI_SCRIPT | base64 -d | /bin/sh -e"} } diff --git a/pipeline/backend/common/script_posix.go b/pipeline/backend/common/script_posix.go index d22ac78ed..1a0a78bcd 100644 --- a/pipeline/backend/common/script_posix.go +++ b/pipeline/backend/common/script_posix.go @@ -53,6 +53,8 @@ fi unset CI_NETRC_USERNAME unset CI_NETRC_PASSWORD unset CI_SCRIPT +mkdir -p "$CI_WORKSPACE" +cd "$CI_WORKSPACE" ` // traceScript is a helper script that is added to the step script diff --git a/pipeline/backend/common/script_posix_test.go b/pipeline/backend/common/script_posix_test.go index 497932ed8..ff0dd6e0d 100644 --- a/pipeline/backend/common/script_posix_test.go +++ b/pipeline/backend/common/script_posix_test.go @@ -39,6 +39,8 @@ fi unset CI_NETRC_USERNAME unset CI_NETRC_PASSWORD unset CI_SCRIPT +mkdir -p "$CI_WORKSPACE" +cd "$CI_WORKSPACE" echo + 'echo ${PATH}' echo ${PATH} diff --git a/pipeline/backend/common/script_test.go b/pipeline/backend/common/script_test.go index b532f7451..1d3722241 100644 --- a/pipeline/backend/common/script_test.go +++ b/pipeline/backend/common/script_test.go @@ -21,19 +21,17 @@ import ( ) const ( - windowsScriptBase64 = "CiRFcnJvckFjdGlvblByZWZlcmVuY2UgPSAnU3RvcCc7CiZjbWQgL2MgIm1rZGlyIGM6XHJvb3QiOwppZiAoJEVudjpDSV9ORVRSQ19NQUNISU5FKSB7CiRuZXRyYz1bc3RyaW5nXTo6Rm9ybWF0KCJ7MH1cX25ldHJjIiwkRW52OkhPTUUpOwoibWFjaGluZSAkRW52OkNJX05FVFJDX01BQ0hJTkUiID4+ICRuZXRyYzsKImxvZ2luICRFbnY6Q0lfTkVUUkNfVVNFUk5BTUUiID4+ICRuZXRyYzsKInBhc3N3b3JkICRFbnY6Q0lfTkVUUkNfUEFTU1dPUkQiID4+ICRuZXRyYzsKfTsKW0Vudmlyb25tZW50XTo6U2V0RW52aXJvbm1lbnRWYXJpYWJsZSgiQ0lfTkVUUkNfUEFTU1dPUkQiLCRudWxsKTsKW0Vudmlyb25tZW50XTo6U2V0RW52aXJvbm1lbnRWYXJpYWJsZSgiQ0lfU0NSSVBUIiwkbnVsbCk7CgpXcml0ZS1PdXRwdXQgKCcrICJlY2hvIGhlbGxvIHdvcmxkIicpOwomIGVjaG8gaGVsbG8gd29ybGQ7IGlmICgkTEFTVEVYSVRDT0RFIC1uZSAwKSB7ZXhpdCAkTEFTVEVYSVRDT0RFfQoK" - posixScriptBase64 = "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVAoKZWNobyArICdlY2hvIGhlbGxvIHdvcmxkJwplY2hvIGhlbGxvIHdvcmxkCg==" + windowsScriptBase64 = "CiRFcnJvckFjdGlvblByZWZlcmVuY2UgPSAnU3RvcCc7CmlmIChbRW52aXJvbm1lbnRdOjpHZXRFbnZpcm9ubWVudFZhcmlhYmxlKCdDSV9XT1JLU1BBQ0UnKSkgeyBpZiAoLW5vdCAoVGVzdC1QYXRoICIkZW52OkNJX1dPUktTUEFDRSIpKSB7IE5ldy1JdGVtIC1QYXRoICIkZW52OkNJX1dPUktTUEFDRSIgLUl0ZW1UeXBlIERpcmVjdG9yeSAtRm9yY2UgfX07CmlmICgtbm90IFtFbnZpcm9ubWVudF06OkdldEVudmlyb25tZW50VmFyaWFibGUoJ0hPTUUnKSkgeyBbRW52aXJvbm1lbnRdOjpTZXRFbnZpcm9ubWVudFZhcmlhYmxlKCdIT01FJywgJ2M6XHJvb3QnKSB9OwppZiAoLW5vdCAoVGVzdC1QYXRoICIkZW52OkhPTUUiKSkgeyBOZXctSXRlbSAtUGF0aCAiJGVudjpIT01FIiAtSXRlbVR5cGUgRGlyZWN0b3J5IC1Gb3JjZSB9OwppZiAoJEVudjpDSV9ORVRSQ19NQUNISU5FKSB7CiRuZXRyYz1bc3RyaW5nXTo6Rm9ybWF0KCJ7MH1cX25ldHJjIiwkRW52OkhPTUUpOwoibWFjaGluZSAkRW52OkNJX05FVFJDX01BQ0hJTkUiID4+ICRuZXRyYzsKImxvZ2luICRFbnY6Q0lfTkVUUkNfVVNFUk5BTUUiID4+ICRuZXRyYzsKInBhc3N3b3JkICRFbnY6Q0lfTkVUUkNfUEFTU1dPUkQiID4+ICRuZXRyYzsKfTsKW0Vudmlyb25tZW50XTo6U2V0RW52aXJvbm1lbnRWYXJpYWJsZSgiQ0lfTkVUUkNfUEFTU1dPUkQiLCRudWxsKTsKW0Vudmlyb25tZW50XTo6U2V0RW52aXJvbm1lbnRWYXJpYWJsZSgiQ0lfU0NSSVBUIiwkbnVsbCk7CmlmIChbRW52aXJvbm1lbnRdOjpHZXRFbnZpcm9ubWVudFZhcmlhYmxlKCdDSV9XT1JLU1BBQ0UnKSkgeyBjZCAiJGVudjpDSV9XT1JLU1BBQ0UiIH07CgpXcml0ZS1PdXRwdXQgKCcrICJlY2hvIGhlbGxvIHdvcmxkIicpOwomIGVjaG8gaGVsbG8gd29ybGQ7IGlmICgkTEFTVEVYSVRDT0RFIC1uZSAwKSB7ZXhpdCAkTEFTVEVYSVRDT0RFfQoK" + posixScriptBase64 = "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiJENJX1dPUktTUEFDRSIKY2QgIiRDSV9XT1JLU1BBQ0UiCgplY2hvICsgJ2VjaG8gaGVsbG8gd29ybGQnCmVjaG8gaGVsbG8gd29ybGQK" ) func TestGenerateContainerConf(t *testing.T) { gotEnv, gotEntry := GenerateContainerConf([]string{"echo hello world"}, "windows") assert.Equal(t, windowsScriptBase64, gotEnv["CI_SCRIPT"]) - assert.Equal(t, "c:\\root", gotEnv["HOME"]) assert.Equal(t, "powershell.exe", gotEnv["SHELL"]) assert.Equal(t, []string{"powershell", "-noprofile", "-noninteractive", "-command", "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Env:CI_SCRIPT)) | iex"}, gotEntry) gotEnv, gotEntry = GenerateContainerConf([]string{"echo hello world"}, "linux") assert.Equal(t, posixScriptBase64, gotEnv["CI_SCRIPT"]) - assert.Equal(t, "/root", gotEnv["HOME"]) assert.Equal(t, "/bin/sh", gotEnv["SHELL"]) assert.Equal(t, []string{"/bin/sh", "-c", "echo $CI_SCRIPT | base64 -d | /bin/sh -e"}, gotEntry) } diff --git a/pipeline/backend/common/script_win.go b/pipeline/backend/common/script_win.go index 17d3b8279..5bf220f9c 100644 --- a/pipeline/backend/common/script_win.go +++ b/pipeline/backend/common/script_win.go @@ -40,7 +40,9 @@ func generateScriptWindows(commands []string) string { const setupScriptWin = ` $ErrorActionPreference = 'Stop'; -&cmd /c "mkdir c:\root"; +if ([Environment]::GetEnvironmentVariable('CI_WORKSPACE')) { if (-not (Test-Path "$env:CI_WORKSPACE")) { New-Item -Path "$env:CI_WORKSPACE" -ItemType Directory -Force }}; +if (-not [Environment]::GetEnvironmentVariable('HOME')) { [Environment]::SetEnvironmentVariable('HOME', 'c:\root') }; +if (-not (Test-Path "$env:HOME")) { New-Item -Path "$env:HOME" -ItemType Directory -Force }; if ($Env:CI_NETRC_MACHINE) { $netrc=[string]::Format("{0}\_netrc",$Env:HOME); "machine $Env:CI_NETRC_MACHINE" >> $netrc; @@ -49,6 +51,7 @@ $netrc=[string]::Format("{0}\_netrc",$Env:HOME); }; [Environment]::SetEnvironmentVariable("CI_NETRC_PASSWORD",$null); [Environment]::SetEnvironmentVariable("CI_SCRIPT",$null); +if ([Environment]::GetEnvironmentVariable('CI_WORKSPACE')) { cd "$env:CI_WORKSPACE" }; %s ` diff --git a/pipeline/backend/common/script_win_test.go b/pipeline/backend/common/script_win_test.go index bbd1bfb41..d7755b478 100644 --- a/pipeline/backend/common/script_win_test.go +++ b/pipeline/backend/common/script_win_test.go @@ -29,7 +29,9 @@ func TestGenerateScriptWin(t *testing.T) { from: []string{"echo %PATH%", "go build", "go test"}, want: ` $ErrorActionPreference = 'Stop'; -&cmd /c "mkdir c:\root"; +if ([Environment]::GetEnvironmentVariable('CI_WORKSPACE')) { if (-not (Test-Path "$env:CI_WORKSPACE")) { New-Item -Path "$env:CI_WORKSPACE" -ItemType Directory -Force }}; +if (-not [Environment]::GetEnvironmentVariable('HOME')) { [Environment]::SetEnvironmentVariable('HOME', 'c:\root') }; +if (-not (Test-Path "$env:HOME")) { New-Item -Path "$env:HOME" -ItemType Directory -Force }; if ($Env:CI_NETRC_MACHINE) { $netrc=[string]::Format("{0}\_netrc",$Env:HOME); "machine $Env:CI_NETRC_MACHINE" >> $netrc; @@ -38,6 +40,7 @@ $netrc=[string]::Format("{0}\_netrc",$Env:HOME); }; [Environment]::SetEnvironmentVariable("CI_NETRC_PASSWORD",$null); [Environment]::SetEnvironmentVariable("CI_SCRIPT",$null); +if ([Environment]::GetEnvironmentVariable('CI_WORKSPACE')) { cd "$env:CI_WORKSPACE" }; Write-Output ('+ "echo %PATH%"'); & echo %PATH%; if ($LASTEXITCODE -ne 0) {exit $LASTEXITCODE} diff --git a/pipeline/backend/docker/convert_test.go b/pipeline/backend/docker/convert_test.go index 4d419b559..dbda92341 100644 --- a/pipeline/backend/docker/convert_test.go +++ b/pipeline/backend/docker/convert_test.go @@ -185,11 +185,7 @@ func TestToConfigSmall(t *testing.T) { "wp_uuid": "09238932", }, Env: []string{ - "CI_SCRIPT=CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW" + - "5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9" + - "GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JE" + - "CnVuc2V0IENJX1NDUklQVAoKZWNobyArICdnbyB0ZXN0JwpnbyB0ZXN0Cg==", - "HOME=/root", + "CI_SCRIPT=CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiJENJX1dPUktTUEFDRSIKY2QgIiRDSV9XT1JLU1BBQ0UiCgplY2hvICsgJ2dvIHRlc3QnCmdvIHRlc3QK", "SHELL=/bin/sh", }, }, conf) @@ -249,12 +245,7 @@ func TestToConfigFull(t *testing.T) { "wp_uuid": "09238932", }, Env: []string{ - "CI_SCRIPT=CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW" + - "5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU" + - "9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1" + - "JECnVuc2V0IENJX1NDUklQVAoKZWNobyArICdnbyB0ZXN0JwpnbyB0ZXN0CgplY2hvICsgJ2dvIHZldCAuLy4uLicKZ28gdmV0IC" + - "4vLi4uCg==", - "HOME=/root", + "CI_SCRIPT=CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiJENJX1dPUktTUEFDRSIKY2QgIiRDSV9XT1JLU1BBQ0UiCgplY2hvICsgJ2dvIHRlc3QnCmdvIHRlc3QKCmVjaG8gKyAnZ28gdmV0IC4vLi4uJwpnbyB2ZXQgLi8uLi4K", "SHELL=/bin/sh", "TAGS=sqlite", }, diff --git a/pipeline/backend/kubernetes/kubernetes.go b/pipeline/backend/kubernetes/kubernetes.go index 0e1a399f8..ed6f19d06 100644 --- a/pipeline/backend/kubernetes/kubernetes.go +++ b/pipeline/backend/kubernetes/kubernetes.go @@ -70,6 +70,7 @@ type config struct { } type SecurityContextConfig struct { RunAsNonRoot bool + FSGroup *int64 } func newDefaultDeleteOptions() meta_v1.DeleteOptions { @@ -98,6 +99,7 @@ func configFromCliContext(ctx context.Context) (*config, error) { ImagePullSecretNames: c.StringSlice("backend-k8s-pod-image-pull-secret-names"), SecurityContext: SecurityContextConfig{ RunAsNonRoot: c.Bool("backend-k8s-secctx-nonroot"), // cspell:words secctx nonroot + FSGroup: newInt64(defaultFSGroup), }, NativeSecretsAllowFromStep: c.Bool("backend-k8s-allow-native-secrets"), } diff --git a/pipeline/backend/kubernetes/pod.go b/pipeline/backend/kubernetes/pod.go index 50ae55dcd..3420ef3b5 100644 --- a/pipeline/backend/kubernetes/pod.go +++ b/pipeline/backend/kubernetes/pod.go @@ -31,8 +31,9 @@ import ( ) const ( - StepLabel = "step" - podPrefix = "wp-" + StepLabel = "step" + podPrefix = "wp-" + defaultFSGroup int64 = 1000 ) func mkPod(step *types.Step, config *config, podName, goos string, options BackendOptions) (*v1.Pod, error) { @@ -182,7 +183,7 @@ func podContainer(step *types.Step, podName, goos string, options BackendOptions container := v1.Container{ Name: podName, Image: step.Image, - WorkingDir: step.WorkingDir, + WorkingDir: step.WorkspaceBase, Ports: containerPorts(step.Ports), SecurityContext: containerSecurityContext(options.SecurityContext, step.Privileged), } @@ -389,6 +390,9 @@ func podSecurityContext(sc *SecurityContext, secCtxConf SecurityContextConfig, s if secCtxConf.RunAsNonRoot { nonRoot = newBool(true) } + if secCtxConf.FSGroup != nil { + fsGroup = secCtxConf.FSGroup + } if sc != nil { // only allow to set user if its not root or step is privileged @@ -406,6 +410,11 @@ func podSecurityContext(sc *SecurityContext, secCtxConf SecurityContextConfig, s fsGroup = sc.FSGroup } + // if unset, set fsGroup to 1000 by default to support non-root images + if sc.FSGroup != nil { + fsGroup = sc.FSGroup + } + // only allow to set nonRoot if it's not set globally already if nonRoot == nil && sc.RunAsNonRoot != nil { nonRoot = sc.RunAsNonRoot diff --git a/pipeline/backend/kubernetes/pod_test.go b/pipeline/backend/kubernetes/pod_test.go index 575b6047a..821571fdf 100644 --- a/pipeline/backend/kubernetes/pod_test.go +++ b/pipeline/backend/kubernetes/pod_test.go @@ -93,24 +93,19 @@ func TestTinyPod(t *testing.T) { "-c", "echo $CI_SCRIPT | base64 -d | /bin/sh -e" ], - "workingDir": "/woodpecker/src", "env": [ "<>", { "name": "CI", "value": "woodpecker" }, - { - "name": "HOME", - "value": "/root" - }, { "name": "SHELL", "value": "/bin/sh" }, { "name": "CI_SCRIPT", - "value": "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVAoKZWNobyArICdncmFkbGUgYnVpbGQnCmdyYWRsZSBidWlsZAo=" + "value": "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiJENJX1dPUktTUEFDRSIKY2QgIiRDSV9XT1JLU1BBQ0UiCgplY2hvICsgJ2dyYWRsZSBidWlsZCcKZ3JhZGxlIGJ1aWxkCg==" } ], "resources": {}, @@ -182,7 +177,6 @@ func TestFullPod(t *testing.T) { "/bin/sh", "-c" ], - "workingDir": "/woodpecker/src", "ports": [ { "containerPort": 1234 @@ -204,11 +198,7 @@ func TestFullPod(t *testing.T) { }, { "name": "CI_SCRIPT", - "value": "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVAoKZWNobyArICdnbyBnZXQnCmdvIGdldAoKZWNobyArICdnbyB0ZXN0JwpnbyB0ZXN0Cg==" - }, - { - "name": "HOME", - "value": "/root" + "value": "CmlmIFsgLW4gIiRDSV9ORVRSQ19NQUNISU5FIiBdOyB0aGVuCmNhdCA8PEVPRiA+ICRIT01FLy5uZXRyYwptYWNoaW5lICRDSV9ORVRSQ19NQUNISU5FCmxvZ2luICRDSV9ORVRSQ19VU0VSTkFNRQpwYXNzd29yZCAkQ0lfTkVUUkNfUEFTU1dPUkQKRU9GCmNobW9kIDA2MDAgJEhPTUUvLm5ldHJjCmZpCnVuc2V0IENJX05FVFJDX1VTRVJOQU1FCnVuc2V0IENJX05FVFJDX1BBU1NXT1JECnVuc2V0IENJX1NDUklQVApta2RpciAtcCAiJENJX1dPUktTUEFDRSIKY2QgIiRDSV9XT1JLU1BBQ0UiCgplY2hvICsgJ2dvIGdldCcKZ28gZ2V0CgplY2hvICsgJ2dvIHRlc3QnCmdvIHRlc3QK" }, { "name": "SHELL", @@ -401,7 +391,20 @@ func TestPodPrivilege(t *testing.T) { } pod, err = createTestPod(false, false, secCtx) assert.NoError(t, err) - assert.Nil(t, pod.Spec.SecurityContext) + assert.Equal(t, &v1.PodSecurityContext{ + SELinuxOptions: (*v1.SELinuxOptions)(nil), + WindowsOptions: (*v1.WindowsSecurityContextOptions)(nil), + RunAsUser: (*int64)(nil), + RunAsGroup: (*int64)(nil), + RunAsNonRoot: (*bool)(nil), + SupplementalGroups: []int64(nil), + SupplementalGroupsPolicy: (*v1.SupplementalGroupsPolicy)(nil), + FSGroup: newInt64(0), + Sysctls: []v1.Sysctl(nil), + FSGroupChangePolicy: (*v1.PodFSGroupChangePolicy)(nil), + SeccompProfile: (*v1.SeccompProfile)(nil), + AppArmorProfile: (*v1.AppArmorProfile)(nil), + }, pod.Spec.SecurityContext) assert.Nil(t, pod.Spec.Containers[0].SecurityContext) // step is not privileged, but security context is requesting privileged @@ -411,7 +414,7 @@ func TestPodPrivilege(t *testing.T) { pod, err = createTestPod(false, false, secCtx) assert.NoError(t, err) assert.Nil(t, pod.Spec.SecurityContext) - assert.Nil(t, pod.Spec.Containers[0].SecurityContext) + assert.Equal(t, (*v1.PodSecurityContext)(nil), pod.Spec.SecurityContext) // step is privileged and security context is requesting privileged secCtx = SecurityContext{ diff --git a/pipeline/backend/types/step.go b/pipeline/backend/types/step.go index 122cc6359..2f86be172 100644 --- a/pipeline/backend/types/step.go +++ b/pipeline/backend/types/step.go @@ -24,6 +24,7 @@ type Step struct { Detached bool `json:"detach,omitempty"` Privileged bool `json:"privileged,omitempty"` WorkingDir string `json:"working_dir,omitempty"` + WorkspaceBase string `json:"workspace_base,omitempty"` Environment map[string]string `json:"environment,omitempty"` Entrypoint []string `json:"entrypoint,omitempty"` Commands []string `json:"commands,omitempty"` diff --git a/pipeline/frontend/yaml/compiler/compiler_test.go b/pipeline/frontend/yaml/compiler/compiler_test.go index 82c68b9db..dadbcd5dd 100644 --- a/pipeline/frontend/yaml/compiler/compiler_test.go +++ b/pipeline/frontend/yaml/compiler/compiler_test.go @@ -90,15 +90,16 @@ func TestCompilerCompile(t *testing.T) { defaultCloneStage := &backend_types.Stage{ Steps: []*backend_types.Step{{ - Name: "clone", - Type: backend_types.StepTypeClone, - Image: constant.DefaultClonePlugin, - OnSuccess: true, - Failure: "fail", - Volumes: []string{defaultVolumes[0].Name + ":/woodpecker"}, - WorkingDir: "/woodpecker/src/github.com/octocat/hello-world", - Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"clone"}}}, - ExtraHosts: []backend_types.HostAlias{}, + Name: "clone", + Type: backend_types.StepTypeClone, + Image: constant.DefaultClonePlugin, + OnSuccess: true, + Failure: "fail", + Volumes: []string{defaultVolumes[0].Name + ":/woodpecker"}, + WorkingDir: "/woodpecker/src/github.com/octocat/hello-world", + WorkspaceBase: "/woodpecker", + Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"clone"}}}, + ExtraHosts: []backend_types.HostAlias{}, }}, } @@ -136,15 +137,16 @@ func TestCompilerCompile(t *testing.T) { Volumes: defaultVolumes, Stages: []*backend_types.Stage{defaultCloneStage, { Steps: []*backend_types.Step{{ - Name: "dummy", - Type: backend_types.StepTypePlugin, - Image: "dummy_img", - OnSuccess: true, - Failure: "fail", - Volumes: []string{defaultVolumes[0].Name + ":/woodpecker"}, - WorkingDir: "/woodpecker/src/github.com/octocat/hello-world", - Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"dummy"}}}, - ExtraHosts: []backend_types.HostAlias{}, + Name: "dummy", + Type: backend_types.StepTypePlugin, + Image: "dummy_img", + OnSuccess: true, + Failure: "fail", + Volumes: []string{defaultVolumes[0].Name + ":/woodpecker"}, + WorkingDir: "/woodpecker/src/github.com/octocat/hello-world", + WorkspaceBase: "/woodpecker", + Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"dummy"}}}, + ExtraHosts: []backend_types.HostAlias{}, }}, }}, }, @@ -170,42 +172,45 @@ func TestCompilerCompile(t *testing.T) { Stages: []*backend_types.Stage{ defaultCloneStage, { Steps: []*backend_types.Step{{ - Name: "echo env", - Type: backend_types.StepTypeCommands, - Image: "bash", - Commands: []string{"env"}, - OnSuccess: true, - Failure: "fail", - Volumes: []string{defaultVolumes[0].Name + ":/test"}, - WorkingDir: "/test/src/github.com/octocat/hello-world", - Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"echo env"}}}, - ExtraHosts: []backend_types.HostAlias{}, + Name: "echo env", + Type: backend_types.StepTypeCommands, + Image: "bash", + Commands: []string{"env"}, + OnSuccess: true, + Failure: "fail", + Volumes: []string{defaultVolumes[0].Name + ":/test"}, + WorkingDir: "/test/src/github.com/octocat/hello-world", + WorkspaceBase: "/test", + Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"echo env"}}}, + ExtraHosts: []backend_types.HostAlias{}, }}, }, { Steps: []*backend_types.Step{{ - Name: "parallel echo 1", - Type: backend_types.StepTypeCommands, - Image: "bash", - Commands: []string{"echo 1"}, - OnSuccess: true, - Failure: "fail", - Volumes: []string{defaultVolumes[0].Name + ":/test"}, - WorkingDir: "/test/src/github.com/octocat/hello-world", - Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"parallel echo 1"}}}, - ExtraHosts: []backend_types.HostAlias{}, + Name: "parallel echo 1", + Type: backend_types.StepTypeCommands, + Image: "bash", + Commands: []string{"echo 1"}, + OnSuccess: true, + Failure: "fail", + Volumes: []string{defaultVolumes[0].Name + ":/test"}, + WorkingDir: "/test/src/github.com/octocat/hello-world", + WorkspaceBase: "/test", + Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"parallel echo 1"}}}, + ExtraHosts: []backend_types.HostAlias{}, }}, }, { Steps: []*backend_types.Step{{ - Name: "parallel echo 2", - Type: backend_types.StepTypeCommands, - Image: "bash", - Commands: []string{"echo 2"}, - OnSuccess: true, - Failure: "fail", - Volumes: []string{defaultVolumes[0].Name + ":/test"}, - WorkingDir: "/test/src/github.com/octocat/hello-world", - Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"parallel echo 2"}}}, - ExtraHosts: []backend_types.HostAlias{}, + Name: "parallel echo 2", + Type: backend_types.StepTypeCommands, + Image: "bash", + Commands: []string{"echo 2"}, + OnSuccess: true, + Failure: "fail", + Volumes: []string{defaultVolumes[0].Name + ":/test"}, + WorkingDir: "/test/src/github.com/octocat/hello-world", + WorkspaceBase: "/test", + Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"parallel echo 2"}}}, + ExtraHosts: []backend_types.HostAlias{}, }}, }, }, @@ -232,40 +237,43 @@ func TestCompilerCompile(t *testing.T) { Volumes: defaultVolumes, Stages: []*backend_types.Stage{defaultCloneStage, { Steps: []*backend_types.Step{{ - Name: "echo env", - Type: backend_types.StepTypeCommands, - Image: "bash", - Commands: []string{"env"}, - OnSuccess: true, - Failure: "fail", - Volumes: []string{defaultVolumes[0].Name + ":/test"}, - WorkingDir: "/test/src/github.com/octocat/hello-world", - Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"echo env"}}}, - ExtraHosts: []backend_types.HostAlias{}, + Name: "echo env", + Type: backend_types.StepTypeCommands, + Image: "bash", + Commands: []string{"env"}, + OnSuccess: true, + Failure: "fail", + Volumes: []string{defaultVolumes[0].Name + ":/test"}, + WorkingDir: "/test/src/github.com/octocat/hello-world", + WorkspaceBase: "/test", + Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"echo env"}}}, + ExtraHosts: []backend_types.HostAlias{}, }, { - Name: "echo 2", - Type: backend_types.StepTypeCommands, - Image: "bash", - Commands: []string{"echo 2"}, - OnSuccess: true, - Failure: "fail", - Volumes: []string{defaultVolumes[0].Name + ":/test"}, - WorkingDir: "/test/src/github.com/octocat/hello-world", - Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"echo 2"}}}, - ExtraHosts: []backend_types.HostAlias{}, + Name: "echo 2", + Type: backend_types.StepTypeCommands, + Image: "bash", + Commands: []string{"echo 2"}, + OnSuccess: true, + Failure: "fail", + Volumes: []string{defaultVolumes[0].Name + ":/test"}, + WorkingDir: "/test/src/github.com/octocat/hello-world", + WorkspaceBase: "/test", + Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"echo 2"}}}, + ExtraHosts: []backend_types.HostAlias{}, }}, }, { Steps: []*backend_types.Step{{ - Name: "echo 1", - Type: backend_types.StepTypeCommands, - Image: "bash", - Commands: []string{"echo 1"}, - OnSuccess: true, - Failure: "fail", - Volumes: []string{defaultVolumes[0].Name + ":/test"}, - WorkingDir: "/test/src/github.com/octocat/hello-world", - Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"echo 1"}}}, - ExtraHosts: []backend_types.HostAlias{}, + Name: "echo 1", + Type: backend_types.StepTypeCommands, + Image: "bash", + Commands: []string{"echo 1"}, + OnSuccess: true, + Failure: "fail", + Volumes: []string{defaultVolumes[0].Name + ":/test"}, + WorkingDir: "/test/src/github.com/octocat/hello-world", + WorkspaceBase: "/test", + Networks: []backend_types.Conn{{Name: "test_default", Aliases: []string{"echo 1"}}}, + ExtraHosts: []backend_types.HostAlias{}, }}, }}, }, diff --git a/pipeline/frontend/yaml/compiler/convert.go b/pipeline/frontend/yaml/compiler/convert.go index 792e35505..b31747aa1 100644 --- a/pipeline/frontend/yaml/compiler/convert.go +++ b/pipeline/frontend/yaml/compiler/convert.go @@ -179,6 +179,7 @@ func (c *Compiler) createProcess(container *yaml_types.Container, stepType backe Detached: detached, Privileged: privileged, WorkingDir: workingDir, + WorkspaceBase: workspaceBase, Environment: environment, Commands: container.Commands, Entrypoint: container.Entrypoint,