fedora-intune: minimal GNOME workstation with Intune and Defender #1

Merged
Misthios merged 6 commits from misthios/fedora-intune AGit into main 2026-10-19 11:58:29 +00:00
13 changed files with 270 additions and 8 deletions
Showing only changes of commit 809bdc3bcb - Show all commits

No files matched your search

+25 -3
View File
@@ -18,6 +18,7 @@ jobs:
outputs: outputs:
cosmic: ${{ steps.changes.outputs.cosmic }} cosmic: ${{ steps.changes.outputs.cosmic }}
remote: ${{ steps.changes.outputs.remote }} remote: ${{ steps.changes.outputs.remote }}
intune: ${{ steps.changes.outputs.intune }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -40,6 +41,7 @@ jobs:
eval "$(printf '%s\n' "${changed}" | ./ci-changes.sh)" eval "$(printf '%s\n' "${changed}" | ./ci-changes.sh)"
echo "cosmic=${cosmic}" >> "$GITHUB_OUTPUT" echo "cosmic=${cosmic}" >> "$GITHUB_OUTPUT"
echo "remote=${remote}" >> "$GITHUB_OUTPUT" echo "remote=${remote}" >> "$GITHUB_OUTPUT"
echo "intune=${intune}" >> "$GITHUB_OUTPUT"
build-cosmic: build-cosmic:
name: ${{ matrix.image }} (${{ matrix.distro }}) name: ${{ matrix.image }} (${{ matrix.distro }})
@@ -170,10 +172,30 @@ jobs:
steps: *build_steps steps: *build_steps
build-intune:
name: fedora-intune (44)
needs: changes
if: needs.changes.outputs.intune == 'true'
runs-on: job-v2
container:
image: "quay.io/fedora-ostree-desktops/buildroot:44"
options: "--security-opt=label=disable --privileged --user 0:0 --device=/dev/fuse --volume /:/run/host:rw"
env:
IMAGE: fedora-intune
DISTRO: "44"
ARCH: x86_64
REGISTRY: git.plabble.org/misthios
GITEA_URL: https://git.plabble.org
GITEA_REPO: Misthios/bootc-images
steps: *build_steps
prune: prune:
name: Prune old releases and tags name: Prune old releases and tags
runs-on: job-v2 runs-on: job-v2
needs: [changes, build-cosmic, build-remote] needs: [changes, build-cosmic, build-remote, build-intune]
# Run even if some builds were skipped or failed. # Run even if some builds were skipped or failed.
if: ${{ always() && github.event_name != 'pull_request' }} if: ${{ always() && github.event_name != 'pull_request' }}
container: container:
@@ -191,7 +213,7 @@ jobs:
env: env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
run: | run: |
for image in fedora-cosmic fedora-remote; do for image in fedora-cosmic fedora-remote fedora-intune; do
./prune-releases.sh "${image}" ./prune-releases.sh "${image}"
done done
- name: Prune old registry tags - name: Prune old registry tags
@@ -203,6 +225,6 @@ jobs:
authfile=/tmp/prune-auth.json authfile=/tmp/prune-auth.json
echo "${REGISTRY_TOKEN}" | skopeo login -u "${REGISTRY_USERNAME}" \ echo "${REGISTRY_TOKEN}" | skopeo login -u "${REGISTRY_USERNAME}" \
--password-stdin --authfile "${authfile}" git.plabble.org --password-stdin --authfile "${authfile}" git.plabble.org
for image in fedora-cosmic fedora-remote; do for image in fedora-cosmic fedora-remote fedora-intune; do
AUTHFILE="${authfile}" ./prune-registry.sh "${image}" Misthios 44 rawhide AUTHFILE="${authfile}" ./prune-registry.sh "${image}" Misthios 44 rawhide
done done
+1 -2
View File
@@ -191,8 +191,7 @@ case "${BUILD_MODE}" in
# Overlay our manifests/support files into the upstream tree so that # Overlay our manifests/support files into the upstream tree so that
# relative includes and *.repo discovery keep working. # relative includes and *.repo discovery keep working.
cp "${IMAGE_DIR}/manifest.yaml" "${BUILD_DIR}/upstream/" cp "${IMAGE_DIR}"/*.yaml "${BUILD_DIR}/upstream/"
cp "${IMAGE_DIR}/custom.yaml" "${BUILD_DIR}/upstream/"
if compgen -G "${IMAGE_DIR}/repos/*.repo" >/dev/null; then if compgen -G "${IMAGE_DIR}/repos/*.repo" >/dev/null; then
cp "${IMAGE_DIR}"/repos/*.repo "${BUILD_DIR}/upstream/" cp "${IMAGE_DIR}"/repos/*.repo "${BUILD_DIR}/upstream/"
fi fi
+8 -3
View File
@@ -1,7 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Given changed paths on stdin, print `cosmic=<bool>` and `remote=<bool>` so the # Given changed paths on stdin, print `cosmic=<bool>`, `remote=<bool>` and
# workflow can skip images that didn't change. Shared files or build tooling # `intune=<bool>` so the workflow can skip images that didn't change. Shared
# changes rebuild everything; empty input (schedule/manual) rebuilds everything. # files or build tooling changes rebuild everything; empty input
# (schedule/manual) rebuilds everything.
set -euo pipefail set -euo pipefail
changed="$(cat || true)" changed="$(cat || true)"
@@ -13,12 +14,16 @@ grep -qE '^images/shared/' <<< "${changed}" && all=1
cosmic=false cosmic=false
remote=false remote=false
intune=false
if [[ "${all}" == 1 ]]; then if [[ "${all}" == 1 ]]; then
cosmic=true cosmic=true
remote=true remote=true
intune=true
fi fi
grep -qE '^images/fedora-cosmic/' <<< "${changed}" && cosmic=true grep -qE '^images/fedora-cosmic/' <<< "${changed}" && cosmic=true
grep -qE '^images/fedora-remote/' <<< "${changed}" && remote=true grep -qE '^images/fedora-remote/' <<< "${changed}" && remote=true
grep -qE '^images/fedora-intune/' <<< "${changed}" && intune=true
echo "cosmic=${cosmic}" echo "cosmic=${cosmic}"
echo "remote=${remote}" echo "remote=${remote}"
echo "intune=${intune}"
+10
View File
@@ -0,0 +1,10 @@
# Build configuration for images/fedora-intune. Sourced by build.sh.
BUILD_MODE=upstream
UPSTREAM_REPO="https://gitlab.com/fedora/ostree/ci-test.git"
# Stable only; Microsoft builds the Intune app against RHEL, not rawhide.
declare -A UPSTREAM_REFS=(
[44]=f44
)
+55
View File
@@ -0,0 +1,55 @@
# Minimal GNOME workstation.
packages:
# Fedora integration normally provided by the upstream fedora.yaml (which we
# opt out of to avoid the Firefox RPM).
- fedora-release
- fedora-release-ostree-desktop
- fedora-flathub-remote
# GNOME desktop: gdm pulls gnome-session, gnome-settings-daemon,
# accountsservice, dconf and gnome-keyring-pam. gnome-initial-setup creates
# the first local user on first boot.
- gdm
- gnome-shell
- gnome-control-center
- gnome-initial-setup
- nautilus
- ptyxis
- pipewire
- pipewire-pulseaudio
- wireplumber
- xdg-desktop-portal-gnome
- xdg-user-dirs-gtk
- flatpak
# Session infrastructure base-atomic lacks with recommends off; see
# fedora-remote/custom.yaml.
- dbus-daemon
- systemd-pam
- mesa-dri-drivers
- mesa-libEGL
# The upstream initramfs config adds dracut's tpm2-tss module, which needs the
# tpm2 binary. fedora-remote gets it through Kanidm; list it explicitly here.
- tpm2-tools
# Proxmox guest integration (agent, console clipboard and resizing).
- qemu-guest-agent
- spice-vdagent
# Microsoft Edge is the browser (Conditional Access needs it).
exclude-packages:
- firefox
add-files:
- ["50-workstation.preset", "/usr/lib/systemd/system-preset/50-workstation.preset"]
# Key-only SSH for local accounts.
- ["10-intune-sshd.conf", "/etc/ssh/sshd_config.d/10-intune-sshd.conf"]
postprocess:
# uresourced breaks the GDM greeter's user manager; see fedora-remote.
- |
#!/usr/bin/env bash
set -xeuo pipefail
ln -sf /dev/null /etc/systemd/system/uresourced.service
+39
View File
@@ -0,0 +1,39 @@
# Microsoft Defender for Endpoint on Linux (mdatp), RHEL 10 build.
#
# mdatp's %post does the real install: it writes mdatp.service and the
# mde_netfilter_v2 units, loads its SELinux module and creates a machine GUID
# and state under /var/opt/microsoft/mdatp. In a compose the daemon cannot
# start and /var is not shipped, so the units and SELinux module are handled
# here and the per-machine state is left to the first start on the device.
#
# Onboarding is per tenant and not part of the image: run the onboarding script
# from the Defender portal on the device (see the Intune test doc).
repo-packages:
- repo: microsoft-rhel10
packages:
- mdatp
packages:
# Used by the Defender TVM/inventory scripts and the onboarding script.
- python3
add-files:
- ["50-defender.preset", "/usr/lib/systemd/system-preset/50-defender.preset"]
postprocess:
- |
#!/usr/bin/env bash
set -xeuo pipefail
conf=/opt/microsoft/mdatp/conf
# Units the %post copies into place; install them if it did not get there.
for unit in mdatp.service mde_netfilter_v2.service mde_netfilter_v2.socket; do
if [[ ! -f "/usr/lib/systemd/system/${unit}" ]]; then
install -m 0644 "${conf}/${unit}" "/usr/lib/systemd/system/${unit}"
fi
done
semodule -n -i "${conf}/selinux_policies/out/mdatp_service.pp"
# Never ship a machine GUID or onboarding state baked in at build time.
ls -laR /etc/opt/microsoft /var/opt/microsoft 2>/dev/null || true
rm -rf /var/opt/microsoft/mdatp
rm -f /etc/opt/microsoft/mdatp/mdatp_onboard.json
@@ -0,0 +1,6 @@
# Key-only SSH for local accounts (add keys to ~/.ssh/authorized_keys).
PubkeyAuthentication yes
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
KbdInteractiveAuthentication no
@@ -0,0 +1,3 @@
# Defender daemon and its network filter (socket-activated).
enable mdatp.service
enable mde_netfilter_v2.socket
@@ -0,0 +1,3 @@
# Intune daemon (socket-activated) and the device identity broker.
enable intune-daemon.socket
enable microsoft-identity-device-broker.service
@@ -0,0 +1,3 @@
enable gdm.service
enable qemu-guest-agent.service
enable sshd.service
+76
View File
@@ -0,0 +1,76 @@
# Microsoft Intune app for Linux (intune-portal), the Microsoft identity broker
# and Microsoft Edge (needed for Conditional Access to Microsoft 365 web apps).
#
# Fedora is not a supported Intune distribution. The RHEL 10 builds are used
# because they link against the same library generation as Fedora 44. The
# repos are limited to these packages with includepkgs (repos/microsoft.repo),
# so nothing else from the RHEL repo can replace a Fedora package.
repos:
- microsoft-rhel10
- microsoft-edge
repo-packages:
- repo: microsoft-rhel10
packages:
- intune-portal
- microsoft-identity-broker
- repo: microsoft-edge
packages:
- microsoft-edge-stable
packages:
# intune-portal scriptlet dependencies (authselect profile + SELinux module)
# and the sssd base its authselect profile is derived from.
- authselect
- checkpolicy
- policycoreutils
- sssd-client
# Secret storage for the identity broker tokens.
- gnome-keyring
- libsecret
add-files:
- ["50-intune.preset", "/usr/lib/systemd/system-preset/50-intune.preset"]
postprocess:
# The intune-portal %post builds an authselect profile with pam_intune.so and
# an SELinux module, but neither reliably survives a compose (no running
# SELinux, authselect state under /etc). Redo both here so the image is
# deterministic either way.
- |
#!/usr/bin/env bash
set -xeuo pipefail
profile=/etc/authselect/custom/intune-profile
if [[ ! -d "${profile}" ]]; then
authselect create-profile intune-profile -b sssd --symlink-meta --symlink-pam
fi
for f in system-auth password-auth; do
grep -q pam_intune.so "${profile}/${f}" && continue
sed -i \
-e 's/^\(auth[[:space:]]\+\)sufficient\([[:space:]]\+pam_unix.so\)/\1required \2/' \
-e 's/^\(password[[:space:]]\+\)sufficient\([[:space:]]\+pam_unix.so\)/\1required \2/' \
"${profile}/${f}"
sed -i \
-e '/^auth[[:space:]]\+required[[:space:]]\+pam_unix.so/a auth sufficient pam_intune.so' \
-e '/^password[[:space:]]\+required[[:space:]]\+pam_unix.so/a password sufficient pam_intune.so' \
-e '/^session[[:space:]]\+required[[:space:]]\+pam_unix.so/a session optional pam_intune.so' \
"${profile}/${f}"
done
authselect select custom/intune-profile --force --nobackup
- |
#!/usr/bin/env bash
set -xeuo pipefail
cd /usr/share/selinux/packages/intune
tmp="$(mktemp -d)"
checkmodule -M -m -o "${tmp}/intune.mod" intune.te
semodule_package -o "${tmp}/intune.pp" -m "${tmp}/intune.mod"
semodule -n -i "${tmp}/intune.pp"
rm -rf "${tmp}"
# intune-agent (user timer) reports compliance; enable it for every user.
- |
#!/usr/bin/env bash
set -xeuo pipefail
systemctl --user --global preset-all
+25
View File
@@ -0,0 +1,25 @@
# Minimal GNOME workstation with the Microsoft Intune app, Microsoft Edge and
# Microsoft Defender for Endpoint, for testing Intune enrollment and Linux
# compliance policies. Local accounts only: no Kanidm, because the Intune app
# needs its own authselect profile (pam_intune) for the password checks.
metadata:
summary: Fedora minimal GNOME workstation with Microsoft Intune and Defender
variables:
# Opt out of the upstream fedora.yaml so we don't pull the Firefox RPM.
distro: "fedora-intune"
variant: "intune"
# Keep it small: no weak/optional dependencies.
recommends: false
default_target: graphical.target
ref: fedora-intune/${releasever_ref}/${basearch}/intune
include:
- base-atomic.yaml
- custom.yaml
- intune.yaml
- defender.yaml
+16
View File
@@ -0,0 +1,16 @@
[microsoft-rhel10]
name=Microsoft Production (RHEL 10)
baseurl=https://packages.microsoft.com/rhel/10/prod/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.microsoft.com/keys/microsoft-2025.asc
includepkgs=intune-portal microsoft-identity-broker mdatp
[microsoft-edge]
name=Microsoft Edge
baseurl=https://packages.microsoft.com/yumrepos/edge/
enabled=1
gpgcheck=1
gpgkey=https://packages.microsoft.com/keys/microsoft.asc
includepkgs=microsoft-edge-stable