Skip to content

Commit

Permalink
feat: report relative path of Dockerfile (#426)
Browse files Browse the repository at this point in the history
* feat: report relative path of Dockerfile

A Dockerfile's path relative to the version control systems's root is reported
under the `DOCKERFILE_PATH_WITHIN_VCTL` key

* refactor: gitInit no longer returns `Plugin` type

- remove `discard`s from `gitInit`'s call sites
- remove `gitInit` return
  • Loading branch information
mbaltrusitis authored Oct 10, 2024
1 parent 9e567de commit 633ce10
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 13 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
subnet IPs even when running inside docker network-namespaced
(not using `--network=host`) container
([#425](https://github.com/crashappsec/chalk/pull/425))
- `DOCKERFILE_PATH_WITHIN_VCTL` key reports the path of a
`Dockerfile` relative to the VCS' project root.
([#426](https://github.com/crashappsec/chalk/pull/426))

## 0.4.12

Expand Down
16 changes: 16 additions & 0 deletions src/configs/base_keyspecs.c4m
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,22 @@ Platform passed when performing `docker build`, if any.
"""
}

keyspec DOCKERFILE_PATH_WITHIN_VCTL {
kind: ChalkTimeArtifact
type: string
standard: true
system: false
since: "0.4.13"
shortdoc: "Relative path of the Dockerfile to the VCS' root."
doc: """
The path of the Dockerfile used during `docker build` relative to the version
control system's project root. Defaults to an empty string in the case of:

* Dockerfile content was passed from `stdin` or process substitution
* the relative path is outside the project (e.g., `../../Dockerfile`)
"""
}

keyspec DOCKER_PLATFORM {
kind: ChalkTimeArtifact
type: string
Expand Down
4 changes: 2 additions & 2 deletions src/configs/base_plugins.c4m
Original file line number Diff line number Diff line change
Expand Up @@ -521,8 +521,8 @@ plugin docker {
enabled: true
pre_chalk_keys: ["ARTIFACT_TYPE",
"DOCKER_FILE", "DOCKER_FILE_CHALKED", "DOCKERFILE_PATH",
"DOCKER_PLATFORM", "DOCKER_PLATFORMS",
"DOCKER_LABELS", "DOCKER_TAGS",
"DOCKERFILE_PATH_WITHIN_VCTL", "DOCKER_PLATFORM",
"DOCKER_PLATFORMS", "DOCKER_LABELS", "DOCKER_TAGS",
"DOCKER_BASE_IMAGE", "DOCKER_BASE_IMAGE_REPO",
"DOCKER_BASE_IMAGE_TAG", "DOCKER_BASE_IMAGE_DIGEST",
"DOCKER_CONTEXT", "DOCKER_ADDITIONAL_CONTEXTS",
Expand Down
6 changes: 6 additions & 0 deletions src/configs/base_report_templates.c4m
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ report and subtract from it.
key.DOCKER_FILE.use = true
key.DOCKER_FILE_CHALKED.use = true
key.DOCKERFILE_PATH.use = true
key.DOCKERFILE_PATH_WITHIN_VCTL.use = true
key.DOCKER_PLATFORM.use = true
key.DOCKER_PLATFORMS.use = true
key.DOCKER_LABELS.use = true
Expand Down Expand Up @@ -695,6 +696,7 @@ doc: """
key.DOCKER_FILE.use = true
key.DOCKER_FILE_CHALKED.use = true
key.DOCKERFILE_PATH.use = true
key.DOCKERFILE_PATH_WITHIN_VCTL.use = true
key.DOCKER_PLATFORM.use = true
key.DOCKER_PLATFORMS.use = true
key.DOCKER_LABELS.use = true
Expand Down Expand Up @@ -1159,6 +1161,7 @@ container.
key.DOCKER_FILE.use = true
key.DOCKER_FILE_CHALKED.use = true
key.DOCKERFILE_PATH.use = true
key.DOCKERFILE_PATH_WITHIN_VCTL.use = true
key.DOCKER_PLATFORM.use = true
key.DOCKER_PLATFORMS.use = true
key.DOCKER_LABELS.use = true
Expand Down Expand Up @@ -1623,6 +1626,7 @@ and keep the run-time key.
key.DOCKER_FILE.use = true
key.DOCKER_FILE_CHALKED.use = true
key.DOCKERFILE_PATH.use = true
key.DOCKERFILE_PATH_WITHIN_VCTL.use = true
key.DOCKER_PLATFORM.use = true
key.DOCKER_PLATFORMS.use = true
key.DOCKER_LABELS.use = true
Expand Down Expand Up @@ -1963,6 +1967,7 @@ running insert commands.
key.DOCKER_FILE.use = true
key.DOCKER_FILE_CHALKED.use = true
key.DOCKERFILE_PATH.use = true
key.DOCKERFILE_PATH_WITHIN_VCTL.use = true
key.DOCKER_PLATFORM.use = true
key.DOCKER_PLATFORMS.use = true
key.DOCKER_LABELS.use = true
Expand Down Expand Up @@ -2047,6 +2052,7 @@ running commands that do NOT insert chalk marks.
key.DOCKER_FILE.use = true
key.DOCKER_FILE_CHALKED.use = true
key.DOCKERFILE_PATH.use = true
key.DOCKERFILE_PATH_WITHIN_VCTL.use = true
key.DOCKER_PLATFORM.use = true
key.DOCKER_PLATFORMS.use = true
key.DOCKER_LABELS.use = true
Expand Down
1 change: 1 addition & 0 deletions src/configs/crashoverride.c4m
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ This is mostly a copy of insert template however all keys are immutable.
~key.DOCKER_FILE.use = true
~key.DOCKER_FILE_CHALKED.use = true
~key.DOCKERFILE_PATH.use = true
~key.DOCKERFILE_PATH_WITHIN_VCTL.use = true
~key.DOCKER_PLATFORM.use = true
~key.DOCKER_PLATFORMS.use = true
~key.DOCKER_LABELS.use = true
Expand Down
11 changes: 8 additions & 3 deletions src/docker/build.nim
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
## (see https://crashoverride.com/docs/chalk)
##

import ".."/[config, collect, chalkjson, plugin_api, subscan, util]
import ".."/[config, collect, chalkjson, plugin_api, subscan, util, plugins/vctlGit]
import "."/[base, collect, ids, dockerfile, inspect, git, exe, entrypoint, platform, wrap, util]

proc processGitContext(ctx: DockerInvocation) =
Expand Down Expand Up @@ -271,8 +271,12 @@ proc launchDockerSubscan(ctx: DockerInvocation,

proc collectBeforeBuild*(chalk: ChalkObj, ctx: DockerInvocation) =
let
base = ctx.getBaseDockerSection()
dict = chalk.collectedData
base = ctx.getBaseDockerSection()
dict = chalk.collectedData
git = getPluginByName("vctl_git")
projectRootPath = git.gitFirstDir().parentDir()
dockerfileRelPath = getRelativePathBetween(projectRootPath, ctx.dockerFileLoc)

dict.setIfNeeded("DOCKERFILE_PATH", ctx.dockerFileLoc)
dict.setIfNeeded("DOCKER_ADDITIONAL_CONTEXTS", ctx.foundExtraContexts)
dict.setIfNeeded("DOCKER_CHALK_ADDED_TO_DOCKERFILE", ctx.addedInstructions)
Expand All @@ -288,6 +292,7 @@ proc collectBeforeBuild*(chalk: ChalkObj, ctx: DockerInvocation) =
dict.setIfNeeded("DOCKER_BASE_IMAGE_DIGEST", base.image.digest)
dict.setIfNeeded("DOCKER_BASE_IMAGES", ctx.formatBaseImages())
dict.setIfNeeded("DOCKER_COPY_IMAGES", ctx.formatCopyImages())
dict.setIfNeeded("DOCKERFILE_PATH_WITHIN_VCTL", dockerfileRelPath)
# note this key is expected to be empty string for alias-less targets
# hence setIfSubscribed vs setIfNeeded which doesnt allow to set empty strings
dict.setIfSubscribed("DOCKER_TARGET", ctx.getTargetDockerSection().alias)
Expand Down
19 changes: 12 additions & 7 deletions src/plugins/vctlGit.nim
Original file line number Diff line number Diff line change
Expand Up @@ -793,15 +793,21 @@ proc isInRepo(obj: ChalkObj, repo: string): bool =
return false

proc gitInit(self: Plugin) =
let cache = GitInfo(self.internalState)
once:
let cache = GitInfo(self.internalState)
for path in getContextDirectories():
cache.findAndLoad(path.resolvePath())

for path in getContextDirectories():
cache.findAndLoad(path.resolvePath())
proc gitFirstDir*(self: Plugin): string =
self.gitInit()
let cache = GitInfo(self.internalState)
for dir, _ in cache.vcsDirs:
return dir
raise newException(ValueError, "no git folder in any of the contexts")

proc gitGetChalkTimeArtifactInfo(self: Plugin, obj: ChalkObj):
ChalkDict {.cdecl.} =
once:
self.gitInit()
self.gitInit()

result = ChalkDict()
let cache = GitInfo(self.internalState)
Expand All @@ -821,8 +827,7 @@ proc gitGetChalkTimeArtifactInfo(self: Plugin, obj: ChalkObj):

proc gitGetRunTimeHostInfo(self: Plugin, chalks: seq[ChalkObj]):
ChalkDict {.cdecl.} =
once:
self.gitInit()
self.gitInit()

result = ChalkDict()
let cache = GitInfo(self.internalState)
Expand Down
9 changes: 9 additions & 0 deletions src/util.nim
Original file line number Diff line number Diff line change
Expand Up @@ -617,3 +617,12 @@ proc getOrDefault*[T](self: openArray[T], i: int, default: T): T =
if len(self) > i:
return self[i]
return default

proc getRelativePathBetween*(fromPath: string, toPath: string) : string =
## Given the `fromPath`, usually the project root, return the relative
## path of the file's `toPath`. Return nothing if its outside the project root
## or if `toPath` is an empty string.
result = toPath.relativePath(fromPath)
if result.startsWith("..") or result == "":
trace("File is ephemeral or not contained within VCS project")
return ""
10 changes: 9 additions & 1 deletion tests/functional/test_docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
DOCKER_TOKEN_REPO,
MARKS,
REGISTRY,
ROOT,
)
from .utils.dict import ANY, MISSING, Contains
from .utils.docker import Docker
Expand Down Expand Up @@ -716,6 +717,9 @@ def test_virtual_valid(
"_IMAGE_ID": image_hash,
"_REPO_TAGS": Contains({f"{tag}:latest"}),
"DOCKERFILE_PATH": str(dockerfile),
"DOCKERFILE_PATH_WITHIN_VCTL": str(
dockerfile.relative_to(ROOT.parent.parent)
),
# docker tags should be set to tag above
"DOCKER_TAGS": Contains({f"{tag}:latest"}),
},
Expand Down Expand Up @@ -775,8 +779,9 @@ def test_virtual_invalid(
)
def test_nonvirtual_valid(chalk: Chalk, test_file: str, random_hex: str):
tag = f"{test_file}_{random_hex}"
dockerfile = DOCKERFILES / test_file / "Dockerfile"
image_hash, build = chalk.docker_build(
dockerfile=DOCKERFILES / test_file / "Dockerfile",
dockerfile=dockerfile,
tag=tag,
config=CONFIGS / "docker_wrap.c4m",
)
Expand All @@ -790,6 +795,9 @@ def test_nonvirtual_valid(chalk: Chalk, test_file: str, random_hex: str):
"_IMAGE_ID": image_hash,
"_REPO_TAGS": Contains({f"{tag}:latest"}),
"DOCKERFILE_PATH": str(DOCKERFILES / test_file / "Dockerfile"),
"DOCKERFILE_PATH_WITHIN_VCTL": str(
dockerfile.relative_to(ROOT.parent.parent)
),
# docker tags should be set to tag above
"DOCKER_TAGS": Contains({f"{tag}:latest"}),
},
Expand Down

0 comments on commit 633ce10

Please sign in to comment.