Skip to content

Commit

Permalink
feat: adding support for CHALK_BYPASS environment variable
Browse files Browse the repository at this point in the history
this allows to completely skip chalk when wrapping `docker`.
Whenever its enabled, chalk directly proxies the command
to `docker` without invoking any of the chalk internal machinery
such as loading configs/etc
  • Loading branch information
miki725 committed Sep 6, 2024
1 parent 7330736 commit c3da0e5
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 5 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
- `_OP_CLOUD_SYS_VENDOR` key for reporting sys vendor
file content used to identity cloud provider.
([#418](https://github.com/crashappsec/chalk/pull/418))
- Supporting `CHALK_BYPASS` environment variable which
bypasses chalk altogether when chalk wraps `docker`.
([#419](https://github.com/crashappsec/chalk/pull/419))

## 0.4.12

Expand Down
37 changes: 37 additions & 0 deletions src/bypass.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
##
## Copyright (c) 2024, Crash Override, Inc.
##
## This file is part of Chalk
## (see https://crashoverride.com/docs/chalk)
##

import std/[os, strutils]
import pkg/nimutils/[file]
import "."/[util]

proc bypassChalk*() =
## Bypasses any chalk execution if possible and directly execs the underlying command.
## Note this function explicitly writes to stderr for "logging" to avoid invoking
## any of the con4m machinery.
if getEnv("CHALK_BYPASS").toLower() notin @["1", "true", "on"]:
return

let
(path, exe) = getAppFilename().splitPath()
# setup.sh for example stores chalkless variants of binaries
# in chalkless folder
# we need to account for it as otherwise original binary
# might not be on PATH overwise
# and as we don't load the chalk config here as a precaution
# and so we must mimic disk structure directly
chalklessDir = path.parentDir().joinPath("chalkless")

case exe
of "docker":
let chalkless = file.findExePath(exe, extraPaths = @[chalklessDir])
if chalkless == "":
stderr.writeLine("Could not find " & exe & " to exec while bypassing chalk")
quitChalk(1)
handleExec(@[chalkless], commandLineParams(), log = false)
else:
return
4 changes: 3 additions & 1 deletion src/chalk.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@

# Note that imports cause topics and plugins to register.
{.warning[UnusedImport]: off.}
import "."/[config, confload, commands, norecurse, sinks,
import "."/[bypass, config, confload, commands, norecurse, sinks,
attestation_api, util]

when isMainModule:
bypassChalk()

setupSignalHandlers() # util.nim
setupTerminal() # util.nim
ioSetup() # sinks.nim
Expand Down
5 changes: 3 additions & 2 deletions src/util.nim
Original file line number Diff line number Diff line change
Expand Up @@ -399,10 +399,11 @@ proc findExePath*(cmdName: string,
trace("Found '" & cmdName & "' in PATH: " & foundExes[0])
return some(foundExes[0])

proc handleExec*(prioritizedExes: seq[string], args: seq[string]) {.noreturn.} =
proc handleExec*(prioritizedExes: seq[string], args: seq[string], log = true) {.noreturn.} =
for path in prioritizedExes:
let cargs = allocCStringArray(@[path] & args)
trace("execv: " & path & " " & args.join(" "))
if log:
trace("execv: " & path & " " & args.join(" "))
discard execv(cstring(path), cargs)
# Either execv doesn't return, or something went wrong. No need to check the
# error code.
Expand Down
1 change: 1 addition & 0 deletions tests/functional/data/configs/docker_cmd.c4m
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
default_command: "docker"
error("chalk is wrapping docker")
7 changes: 5 additions & 2 deletions tests/functional/test_docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -1344,14 +1344,17 @@ def test_docker_diff_user(chalk_default: Chalk):
assert result


def test_docker_default_command(chalk_copy: Chalk, tmp_data_dir: Path):
@pytest.mark.parametrize("bypass", [True, False])
def test_docker_default_command(chalk_copy: Chalk, tmp_data_dir: Path, bypass: bool):
assert chalk_copy.load(CONFIGS / "docker_cmd.c4m")
expected = Docker.version()
docker = tmp_data_dir / "docker"
shutil.copy(chalk_copy.binary, docker)
actual = run([str(docker), "--version"])
actual = run([str(docker), "--version"], env={"CHALK_BYPASS": str(bypass)})
assert actual
assert actual.text == expected.text
if bypass:
assert actual.logs == expected.logs


def test_version_bare(chalk_default: Chalk):
Expand Down

0 comments on commit c3da0e5

Please sign in to comment.