laurel 0.8.0

Transform Linux Audit logs for SIEM usage
Documentation
on:
  push:
    paths:
      - src/**
      - audit-specs/**
      - syscall-tables/**
      - build.rs
      - Cargo.*
      - .github/workflows/build.yml
      - Containerfile
  pull_request:
    paths:
      - src/**
      - audit-specs/**
      - syscall-tables/**
      - build.rs
      - Cargo.*
      - .github/workflows/build.yml
      - Containerfile

permissions:
  contents: read

jobs:
  check-fmt:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - run: cargo fmt --check

  build-test:
    runs-on: ubuntu-latest
    container: ubuntu:latest
    steps:
      - uses: actions/checkout@v6
      - name: Install dependency
        run: |
          export DEBIAN_FRONTEND=noninteractive
          apt-get -qq update
          apt-get -qqy dist-upgrade
          apt-get -qqy install curl build-essential libclang-dev libacl1-dev libgoogle-perftools-dev
      - uses: dtolnay/rust-toolchain@stable
      - uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: "${{ runner.os }}-test-cargo-${{ hashFiles('**/Cargo.lock') }}"
          restore-keys: ${{ runner.os }}-test-cargo-
      - run: cargo build
      - run: cargo test
      - run: cargo bench --no-run

  build-test-old:
    runs-on: ubuntu-latest
    container: ubuntu:latest
    steps:
      - uses: actions/checkout@v6
      - name: Install dependency
        run: |
          export DEBIAN_FRONTEND=noninteractive
          apt-get -qq update
          apt-get -qqy dist-upgrade
          apt-get -qqy install curl build-essential libclang-dev libacl1-dev libgoogle-perftools-dev
      - uses: dtolnay/rust-toolchain@1.70 # minimum supported Rust version (see Cargo.toml)
      - uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: "${{ runner.os }}-test-cargo-${{ hashFiles('**/Cargo.lock') }}"
          restore-keys: ${{ runner.os }}-test-cargo-
      - run: cargo test --no-default-features
      - run: cargo test

  build-x86_64-gnu:
    needs: [ check-fmt, build-test ]
    runs-on: ubuntu-latest
    container: debian:bullseye
    steps:
      - uses: actions/checkout@v6
      - name: Install dependency
        run: |
          export DEBIAN_FRONTEND=noninteractive
          apt-get -qq update
          apt-get -qqy dist-upgrade
          apt-get -qqy install curl build-essential libclang-dev libacl1-dev
      - uses: dtolnay/rust-toolchain@stable
      - uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: "${{ runner.os }}-x86_64-gnu-cargo-${{ hashFiles('**/Cargo.lock') }}"
          restore-keys: ${{ runner.os }}-cargo-x86_64-gnu-
      - name: Build
        run: cargo build --target=x86_64-unknown-linux-gnu --release
      - uses: actions/upload-artifact@v7
        with:
          name: binaries-x86_64-gnu
          path: |
            target/*/release/laurel*
            !target/*/release/*.*
          if-no-files-found: error

  build-x86_64-musl:
    needs: [ check-fmt, build-test ]
    runs-on: ubuntu-latest
    container: alpine:3.23
    steps:
      - uses: actions/checkout@v6
      - name: Install dependency
        run: |
          apk add git ca-certificates tar rust cargo clang-dev acl-dev acl-static musl-dev linux-headers
          apk add binutils file
      - uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: "${{ runner.os }}-x86_64-musl-cargo-${{ hashFiles('**/Cargo.lock') }}"
          restore-keys: ${{ runner.os }}-cargo-x86_64-musl-
      - name: Build
        run: |
          RUSTFLAGS='-C target-feature=+crt-static -L/usr/lib -l static=acl' \
              cargo build --target x86_64-alpine-linux-musl --release
      - name: Show binary charcteristics
        run: |
          set -x
          file target/x86_64-alpine-linux-musl/release/laurel
          ldd  target/x86_64-alpine-linux-musl/release/laurel
          objdump -x target/x86_64-alpine-linux-musl/release/laurel | grep NEEDED || true
          set +x
          if [ -n "$(objdump -x target/x86_64-alpine-linux-musl/debug/laurel | grep NEEDED)" ]; then
              echo "laurel is linked against shared libraries" >&2
              exit 1
          fi
      - uses: actions/upload-artifact@v7
        with:
          name: binaries-x86_64-musl
          path: |
            target/*/release/laurel*
            !target/*/release/*.*
          if-no-files-found: error

  build-aarch64-gnu:
    needs: [ check-fmt, build-test ]
    runs-on: ubuntu-latest
    container: debian:bullseye
    steps:
      - uses: actions/checkout@v6
      - name: Install dependency
        run: |
          export DEBIAN_FRONTEND=noninteractive
          dpkg --add-architecture arm64
          apt-get -qq update
          apt-get -qqy dist-upgrade
          apt-get -qqy install curl build-essential libclang-dev gcc-aarch64-linux-gnu libacl1-dev:arm64
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: aarch64-unknown-linux-gnu
      - uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: "${{ runner.os }}-aarch64-gnu-cargo-${{ hashFiles('**/Cargo.lock') }}"
          restore-keys: ${{ runner.os }}-cargo-aarch64-gnu-
      - name: Build
        run: cargo build --target=aarch64-unknown-linux-gnu --release
      - uses: actions/upload-artifact@v7
        with:
          name: binaries-aarch64-gnu
          path: |
            target/*/release/laurel*
            !target/*/release/*.*
          if-no-files-found: error

  build-armv7-gnueabihf:
    needs: [ check-fmt, build-test ]
    runs-on: ubuntu-latest
    container: debian:bullseye
    steps:
      - uses: actions/checkout@v6
      - name: Install dependency
        run: |
          export DEBIAN_FRONTEND=noninteractive
          dpkg --add-architecture armhf
          apt-get -qq update
          apt-get -qqy dist-upgrade
          apt-get -qqy install curl build-essential libclang-dev gcc-arm-linux-gnueabihf libacl1-dev:armhf
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: armv7-unknown-linux-gnueabihf
      - uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: "${{ runner.os }}-armv7-gnueabihf-cargo-${{ hashFiles('**/Cargo.lock') }}"
          restore-keys: ${{ runner.os }}-armv7-gnueabihf-cargo-
      - name: Build
        run: cargo build --target=armv7-unknown-linux-gnueabihf --release
      - uses: actions/upload-artifact@v7
        with:
          name: binaries-armv7-gnueabihf
          path: |
            target/*/release/laurel*
            !target/*/release/*.*
          if-no-files-found: error

  build-man:
    runs-on: ubuntu-latest
    container: debian:bullseye
    steps:
      - uses: actions/checkout@v6
      - name: Install dependency
        run: |
          export DEBIAN_FRONTEND=noninteractive
          apt-get -qq update
          apt-get -qqy dist-upgrade
          apt-get -qqy install make pandoc
      - run: make -C man
      - uses: actions/upload-artifact@v7
        with:
          name: manpages
          path: |
            man/*.7
            man/*.8
          if-no-files-found: error

  build-tarballs:
    runs-on: ubuntu-latest
    needs:
      - build-x86_64-gnu
      - build-x86_64-musl
      - build-aarch64-gnu
      - build-armv7-gnueabihf
      - build-man
    steps:
      - uses: actions/checkout@v6
      - uses: actions/download-artifact@v8
        with:
          merge-multiple: true
          path: artifacts
      - name: Collect/Build
        run: |
          version="$(cargo read-manifest | jq -r '.version')"

          find -type f '(' -name laurel2audit -or -name laurel ')'

          for arch in x86_64-glibc x86_64-musl aarch64-glibc armv7-glibc; do

              tgt=${arch/-glibc/-unknown-linux-gnu}
              tgt=${tgt/-musl/-alpine-linux-musl}
              case $tgt in armv7*gnu) tgt=${tgt}eabihf ;; esac

              mkdir -p pack/laurel-$version-$arch/bin \
                       pack/laurel-$version-$arch/etc/{audit/plugins.d,laurel} \
                       pack/laurel-$version-$arch/man/man{7,8} \
                       pack/laurel-$version-$arch/doc

              install -m644 etc/audit/plugins.d/laurel.conf pack/laurel-$version-$arch/etc/audit/plugins.d/
              install -m644 etc/laurel/config.toml          pack/laurel-$version-$arch/etc/laurel/
              install -m644 *.md                            pack/laurel-$version-$arch/doc/

              install -m755 artifacts/$tgt/release/laurel* pack/laurel-$version-$arch/bin
              install -m644 artifacts/*.7                  pack/laurel-$version-$arch/man/man7/
              install -m644 artifacts/*.8                  pack/laurel-$version-$arch/man/man8/
          done

          cd pack
          find -mindepth 1 -maxdepth 1 -type d | xargs -ti tar -czf {}.tar.gz {}

      - uses: actions/upload-artifact@v7
        with:
          name: tarballs
          path: pack/*.tar.gz
          compression-level: 0
          if-no-files-found: error

  release:
    runs-on: ubuntu-latest
    needs: build-tarballs
    if: ${{ startsWith(github.ref, 'refs/tags/') }}
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v6
      - name: Get Version
        id: get_version
        run: |
          version_git=$(echo "$GITHUB_REF" | sed -e 's/refs\/tags\///')
          version_cargo="v$(cargo read-manifest | jq -r '.version')"
          if [ "$version_git" != "$version_cargo" ]; then
              echo "git != cargo: $version_git != $version_cargo" >&2
              exit 1
          fi
          echo "git_version=$version_git" >> $GITHUB_OUTPUT
      - uses: actions/download-artifact@v8
        with:
          name: tarballs
      - uses: softprops/action-gh-release@v2
        with:
          files: laurel-*.tar.gz
          fail_on_unmatched_files: true
          draft: true

  build-container:
    runs-on: ubuntu-latest
    needs:
      - build-x86_64-musl
    permissions:
      packages: write
    steps:
      - uses: actions/checkout@v6
      - uses: actions/download-artifact@v8
        with:
          merge-multiple: true
          path: target
      - name: Edit configuration
        run: |
          sed -e 's#^input = .*#input = "unix:/var/run/audispd_events"#' etc/laurel/config.toml
      - uses: redhat-actions/buildah-build@v2
        id: build-image
        with:
          image: laurel
          tags: "latest ${{ github.sha }} ${{ github.ref_name }}"
          containerfiles: ./Containerfile
      - uses: redhat-actions/podman-login@v1
        if:  ${{ github.ref_type == 'tag' }}
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: redhat-actions/push-to-registry@v2
        if:  ${{ github.ref_type == 'tag' }}
        with:
          registry: ghcr.io/${{ github.repository_owner }}
          image: ${{ steps.build-image.outputs.image }}
          tags: ${{ steps.build-image.outputs.tags }}