Dalec

repository·main·Indexed 43 days ago

https://github.com/project-dalec/dalec

A declarative tool for building secure system packages and containers with a focus on supply chain security, minimal image sizes, build-time SBOMs, and Provenance attestations. It supports DEB-based (Debian, Ubuntu), RPM-based (Azure Linux, Rocky Linux, Alma Linux), and Windows container targets.

Tokens
54.3K
Snippets
210
Records
267
Agent score
53%

What's inside Dalec

  1. What is Dalec?

    main
    Dalec is a tool designed to provide a declarative format for building system packages and containers. It focuses on supply chain security by enabling the creation of minimal images with a reduced attack surface and providing build-time SBOMs (Software Bill of Materials) and Provenance attestations.
  2. What is Dalec?

    main
    Dalec is a Docker Buildkit frontend that translates declarative YAML specifications into build instructions. It acts as a specialized compiler that takes package configurations and produces packages and containers across multiple Linux distributions (such as Debian, Ubuntu, Azure Linux, and Rocky Linux) and Windows.
  3. Understand the Dalec security posture and assurance case

    main

    Dalec provides a structured assurance case designed to meet OpenSSF Best Practices Silver standards. This document outlines how Dalec's release process mitigates supply-chain risks by mapping high-level security claims to specific evidence (such as CI workflows, governance policies, and architectural designs).

    Key Security Mitigations

    • Declarative Spec Validation: Ensures build specifications are valid.
    • Sandboxed Execution: Uses BuildKit's sandboxing with clearly defined mounts to isolate build processes.
    • Artifact Integrity: Official release artifacts include signatures and SBOM/provenance outputs.
    • Automated Testing: Specs include tests that are executed via the Dalec test runner.
    • Continuous Monitoring: Uses Dependabot, GitHub Dependency Review, and Snyk to monitor and triage dependency vulnerabilities.
  4. What is a Source in Dalec?

    main

    A source is an abstraction used to fetch dependencies for a build. While usually source code, a source can be any data (files, directories, or generated content) fetched over various protocols.

    Key behaviors:

    • Injection: Sources are injected into the root path of the build environment using the name assigned to the source in the configuration.
    • File vs. Directory sources: Some sources are inherently file-based (e.g., http, inline: file), while others are directory-based (e.g., git, context, docker image, build).
    • Wrapper types: Some sources act as wrappers or allow mounting other sources (e.g., docker image, build). Only the output of a top-level source is included in the build environment.
    • Platform Agnosticism: Ideally, source content should be platform-agnostic, as these sources are used to create source packages (like srpm or debian dsc) for target platforms.
  5. What is Dalec and how it works

    main

    Dalec is a Docker Buildkit frontend that translates a YAML specification into build instructions for creating packages (such as RPMs or DEBs) and container images. It requires only Docker to run.

    Dalec builds follow a three-stage lifecycle:

    1. Package Build: Checks out sources and executes defined build steps.
    2. Package Test: Installs and validates the package in a clean environment.
    3. Create Container (optional): Installs the resulting package(s) into a scratch image to produce a container image.
  6. Check file existence and properties

    main

    You can verify the presence and metadata of files within the container using the files key under a test case.

    Available file checks include:

    • Existence: Simply listing a path under files checks if it exists.
    • Non-existence: Use not_exist: true to assert a file is absent.
    • Directory check: Use is_dir: true to assert a path is a directory.
    • Permissions: Use the permissions key (e.g., 0644) to check file mode.
    • Symlinks: Use link_target to verify the destination of a symbolic link.
    tests:
      - name: My Test case
        files:
          /usr/bin/foo: # Checks existence
          /some/nonexistent/path:
            not_exist: true
          /some/path:
            is_dir: true
          /etc/foo.conf:
            permissions: 0644
          /some/symlink:
            link_target: /expected/target
  7. Understand the cleanup policy for Debian/Ubuntu minimal images

    main

    Debian- and Ubuntu-based minimal container targets (e.g., trixie/container, bookworm/container, noble/container) run an aggressive post-install cleanup pass. This policy is all-or-nothing per directory tree:

    • /usr/share/doc, /usr/share/man, /usr/share/info: Preserved only if the spec declares at least one docs, manpages, or licenses artifact. If preserved, all content under these paths (including dependency-owned files) is kept. If pruned, all content is removed.
    • /etc/systemd, /var/lib/systemd: Preserved only if the systemd package is installed or systemctl is on PATH.
    • /var/log: The directory is always preserved, but its contents are emptied.
    • Package manager state/caches: Paths like /etc/apt, /var/cache/apt, /var/lib/apt, /usr/lib/apt, /var/lib/pam, /var/cache/debconf, and /usr/share/{bash-completion,bug,debconf,lintian,locale} are always removed.
  8. Configure the Image field in the DALEC spec

    main

    The image field is an object in the DALEC specification used to customize the properties of the produced container image. Most fields (except base, bases, and post) are merged with the configured or default base image settings.

    Supported properties include:

    • minimization_profile: Optional post-install minimization policy.
    • labels: Optional key-value pairs for image labels.
    • env: Optional environment variables.
    • entrypoint: Optional entrypoint command.
    • cmd: Optional command.
    • workdir: Optional working directory.
    • user: Optional user/group configuration.
    • stop_signal: Optional signal for graceful container shutdown.
    • volumes: Optional volume definitions.
  9. Customize worker images using Named Build Contexts

    main

    If you need a worker image with additional tools not present in the base image, you can target the worker specifically using <target>/worker (e.g., --target=azlinux3/worker).

    To provide a custom worker image, use the Docker buildx --build-context flag. For the azlinux3 target, DALEC looks for a named context called dalec-azlinux3-worker. If you provide a context for the actual base image used by azlinux3, the worker context is ignored.

    Example using a custom worker context:

    docker buildx build --build-context dalec-azlinux3-worker=<new ref> ...
  10. Configure top-level source options

    main

    For all source types, you can apply the following top-level configuration keys to control how the source is processed:

    • path: The specific path to extract from the source type.
    • includes: A list of glob patterns to include from the source.
    • excludes: A list of glob patterns to exclude from the source.
    • generate: Used to trigger a generator (e.g., gomod, pip).

    Example of configuring a context source with path filtering:

    sources:
      someSource:
        path: path/in/source
        includes:
          - "*.txt"
        excludes:
          - "secret.txt"
        context: {}
  11. How Dalec tests are structured

    main

    Dalec uses two distinct testing tiers:

    1. Unit Tests

    • Location: Distributed throughout the codebase (e.g., spec_test.go).
    • Characteristics: Fast (< 1 minute), no Docker/network required, tests functions in isolation.
    • Execution: Use go test --test.short ./... or make test.

    2. Integration Tests

    • Location: The test/ directory.
    • Characteristics: Slow (30-60+ minutes), requires Docker with BuildKit, tests end-to-end scenarios (Linux/Windows packages/containers).
    • Framework: Uses a custom framework in test/testenv/ to manage Docker contexts and parallel execution.
    # Run all unit tests
    go test --test.short ./...
  12. How System Extensions (sysexts) work in Dalec

    main

    Dalec can create system extensions, known as sysexts, which are EROFS filesystem images designed for use with systemd (version 248 or later). These images are overlaid onto a running system.

    Key Characteristics:

    • Dependency Model: Unlike containers, Dalec uses a specific sysext dependency type. This gives you full control over what is included, as packages are extracted directly rather than installed via a package manager. No dependency resolution or package metadata is performed during the build.
    • Merging Behavior: When merged, files in the extension that share a path with the running system will overshadow the existing files. The running system is not modified; original files become visible again once the extension is unmerged.
    • Portability: Extensions can be standalone or rely on the host system. To maximize portability and avoid glibc compatibility issues, consider using statically-linked binaries.
    • Ownership: Dalec automatically changes all file ownership to root:root during creation to prevent UID/GID mismatches with the host system.