fedora-intune: minimal GNOME workstation with Intune and Defender #1
No files matched your search
@@ -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 }})
|
||||||
@@ -102,6 +104,8 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Log in to registry
|
- name: Log in to registry
|
||||||
|
# Only the push step needs it, and PR builds get no secrets.
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
env:
|
env:
|
||||||
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
||||||
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
@@ -170,10 +174,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 +215,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 +227,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
|
||||||
@@ -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
@@ -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}"
|
||||||
@@ -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; Defender comes from Microsoft's RHEL 10 repo, not rawhide.
|
||||||
|
declare -A UPSTREAM_REFS=(
|
||||||
|
[44]=f44
|
||||||
|
)
|
||||||
@@ -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-workstation-sshd.conf", "/etc/ssh/sshd_config.d/10-workstation-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
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# Microsoft Defender for Endpoint on Linux (mdatp), RHEL 10 build, from the
|
||||||
|
# microsoft-rhel10 repo (repos/microsoft.repo).
|
||||||
|
#
|
||||||
|
# mdatp's %post does the real install: units, SELinux module, and per-machine
|
||||||
|
# state under /var/opt/microsoft/mdatp (machine GUID, definitions database,
|
||||||
|
# logs). In a compose /var is read-only, and that state must not be shared
|
||||||
|
# between machines anyway, so the %post is saved into the image and run once on
|
||||||
|
# first boot by mdatp-firstboot.service. mdatp.service waits for it.
|
||||||
|
#
|
||||||
|
# Onboarding is per tenant and not part of the image: run the onboarding script
|
||||||
|
# from the Defender portal on the device.
|
||||||
|
|
||||||
|
repo-packages:
|
||||||
|
- repo: microsoft-rhel10
|
||||||
|
packages:
|
||||||
|
- mdatp
|
||||||
|
|
||||||
|
packages:
|
||||||
|
# The %post is a bash script; Defender's inventory scripts and the
|
||||||
|
# onboarding script are Python.
|
||||||
|
- bash
|
||||||
|
- python3
|
||||||
|
|
||||||
|
add-files:
|
||||||
|
- ["mdatp-firstboot", "/usr/libexec/mdatp-firstboot"]
|
||||||
|
- ["mdatp-firstboot.service", "/usr/lib/systemd/system/mdatp-firstboot.service"]
|
||||||
|
- ["mdatp-firstboot.conf", "/usr/lib/systemd/system/mdatp.service.d/10-firstboot.conf"]
|
||||||
|
- ["50-defender.preset", "/usr/lib/systemd/system-preset/50-defender.preset"]
|
||||||
|
|
||||||
|
postprocess:
|
||||||
|
- |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -xeuo pipefail
|
||||||
|
# The %post wrote the units during the compose; fail the build if a newer
|
||||||
|
# mdatp stops doing that, rather than shipping a Defender that never starts.
|
||||||
|
for unit in mdatp.service mde_netfilter_v2.service mde_netfilter_v2.socket; do
|
||||||
|
test -f "/usr/lib/systemd/system/${unit}"
|
||||||
|
done
|
||||||
|
# rpm-ostree keeps /opt content in /usr/lib/opt until the commit.
|
||||||
|
for root in /usr/lib/opt /opt; do
|
||||||
|
pp="${root}/microsoft/mdatp/conf/selinux_policies/out/mdatp_service.pp"
|
||||||
|
[[ -f "${pp}" ]] && break
|
||||||
|
done
|
||||||
|
semodule -n -i "${pp}"
|
||||||
|
rpm -q --qf '%{POSTIN}' mdatp > /usr/libexec/mdatp-postinst
|
||||||
|
chmod 0755 /usr/libexec/mdatp-firstboot /usr/libexec/mdatp-postinst
|
||||||
@@ -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,4 @@
|
|||||||
|
# Defender: first-boot setup, the daemon and its network filter.
|
||||||
|
enable mdatp-firstboot.service
|
||||||
|
enable mdatp.service
|
||||||
|
enable mde_netfilter_v2.socket
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Intune compliance check at login and on a timer, for every user.
|
||||||
|
enable himmelblau-compliance-check.service
|
||||||
|
enable himmelblau-compliance-check.timer
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Himmelblau daemons; they pull in their sockets with Requires=.
|
||||||
|
enable himmelblaud.service
|
||||||
|
enable himmelblaud-tasks.service
|
||||||
|
enable himmelblau-hsm-pin-init.service
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
enable gdm.service
|
||||||
|
enable qemu-guest-agent.service
|
||||||
|
enable sshd.service
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ExtensionInstallForcelist": [
|
||||||
|
"jlnfnnolkbjieggibinobhkjdfbpcohn;https://clients2.google.com/service/update2/crx"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "linux_entra_sso",
|
||||||
|
"description": "Entra ID SSO via Microsoft Identity Broker",
|
||||||
|
"path": "/usr/bin/linux-entra-sso",
|
||||||
|
"type": "stdio",
|
||||||
|
"allowed_origins": [
|
||||||
|
"chrome-extension://jlnfnnolkbjieggibinobhkjdfbpcohn/"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Himmelblau configuration. See himmelblau.conf(5) and
|
||||||
|
# https://himmelblau-idm.org/docs/reference/himmelblau-conf/
|
||||||
|
#
|
||||||
|
# No tenant settings are needed: `domain` defaults to the domain of the first
|
||||||
|
# user who signs in, and that user joins the device to Entra ID. Restrict who
|
||||||
|
# may sign in with pam_allow_groups (group object IDs or UPNs).
|
||||||
|
|
||||||
|
[global]
|
||||||
|
# Enroll the device in Intune and apply/report compliance policies.
|
||||||
|
apply_policy = true
|
||||||
|
# Fedora's admin group; members of sudo_groups (Entra group object IDs) are
|
||||||
|
# added to it.
|
||||||
|
local_sudo_group = wheel
|
||||||
|
# Home directories named after the account (e.g. /home/jdoe), with a UPN alias.
|
||||||
|
home_attr = CN
|
||||||
|
home_alias = SPN
|
||||||
|
use_etc_skel = true
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Finish the Defender (mdatp) install on first boot by running the package's
|
||||||
|
# own %post, saved at build time: it creates the machine GUID, state, logs and
|
||||||
|
# definitions database under /var and then enables and starts mdatp.service.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
MARKER=/var/lib/mdatp-firstboot.done
|
||||||
|
|
||||||
|
[[ -f "${MARKER}" ]] && exit 0
|
||||||
|
|
||||||
|
# mdatp.service only starts once the marker exists (10-firstboot.conf), and the
|
||||||
|
# %post starts it, so create the marker first and drop it again on failure.
|
||||||
|
touch "${MARKER}"
|
||||||
|
if ! bash /usr/libexec/mdatp-postinst 1; then
|
||||||
|
rm -f "${MARKER}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Don't start Defender before mdatp-firstboot.service has created its state.
|
||||||
|
[Unit]
|
||||||
|
ConditionPathExists=/var/lib/mdatp-firstboot.done
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Finish the Microsoft Defender for Endpoint install on first boot
|
||||||
|
Documentation=https://learn.microsoft.com/en-us/defender-endpoint/microsoft-defender-endpoint-linux
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
ConditionPathExists=!/var/lib/mdatp-firstboot.done
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/usr/libexec/mdatp-firstboot
|
||||||
|
RemainAfterExit=yes
|
||||||
|
TimeoutStartSec=15min
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# Himmelblau: Entra ID sign-in (PAM/NSS), Entra join, Hello PIN, Intune
|
||||||
|
# enrollment and compliance, and browser SSO.
|
||||||
|
|
||||||
|
repo-packages:
|
||||||
|
- repo: himmelblau
|
||||||
|
packages:
|
||||||
|
- himmelblau
|
||||||
|
- pam-himmelblau
|
||||||
|
- nss-himmelblau
|
||||||
|
- himmelblau-selinux
|
||||||
|
# Shows a QR code on the login screen for the MFA/device-code prompts.
|
||||||
|
- himmelblau-qr-greeter
|
||||||
|
# Entra SSO in Edge (native messaging host) via the Himmelblau broker.
|
||||||
|
- himmelblau-broker
|
||||||
|
- himmelblau-sso
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- authselect
|
||||||
|
- nss-altfiles
|
||||||
|
# himmelblau-selinux compiles its policy module at install time.
|
||||||
|
- make
|
||||||
|
- selinux-policy-devel
|
||||||
|
|
||||||
|
add-files:
|
||||||
|
- ["himmelblau.conf", "/etc/himmelblau/himmelblau.conf"]
|
||||||
|
- ["50-himmelblau.preset", "/usr/lib/systemd/system-preset/50-himmelblau.preset"]
|
||||||
|
- ["50-himmelblau-user.preset", "/usr/lib/systemd/user-preset/50-himmelblau-user.preset"]
|
||||||
|
|
||||||
|
postprocess:
|
||||||
|
# The package's %post selects its authselect vendor profile but drops
|
||||||
|
# with-altfiles; without it system users (gdm, pipewire, mdatp, ...) in
|
||||||
|
# /usr/lib/passwd do not resolve and the login screen never starts.
|
||||||
|
- |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -xeuo pipefail
|
||||||
|
authselect select himmelblau with-altfiles with-pam-gnome-keyring --force --nobackup
|
||||||
|
for user in gdm mdatp; do
|
||||||
|
getent passwd "${user}" >/dev/null
|
||||||
|
done
|
||||||
|
grep -q pam_himmelblau.so /etc/pam.d/system-auth
|
||||||
|
|
||||||
|
# himmelblau-selinux builds and loads its module in %posttrans, which does
|
||||||
|
# nothing in a compose; do it here.
|
||||||
|
- |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -xeuo pipefail
|
||||||
|
tmp="$(mktemp -d)"
|
||||||
|
cp /usr/share/selinux/packages/himmelblaud/himmelblaud.{te,if,fc} "${tmp}/"
|
||||||
|
make -C "${tmp}" -f /usr/share/selinux/devel/Makefile himmelblaud.pp
|
||||||
|
semodule -n -i "${tmp}/himmelblaud.pp"
|
||||||
|
rm -rf "${tmp}"
|
||||||
|
|
||||||
|
# Show the QR greeter on the GDM login screen, not only in user sessions.
|
||||||
|
- |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -xeuo pipefail
|
||||||
|
install -d /etc/dconf/db/gdm.d
|
||||||
|
cat > /etc/dconf/db/gdm.d/01-himmelblau-qr-greeter <<'CONF'
|
||||||
|
[org/gnome/shell]
|
||||||
|
enabled-extensions=['qr-greeter@himmelblau-idm.org']
|
||||||
|
CONF
|
||||||
|
dconf update
|
||||||
|
|
||||||
|
# Compliance check (user timer) and broker for every user.
|
||||||
|
- |
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -xeuo pipefail
|
||||||
|
systemctl --user --global preset-all
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# Minimal GNOME workstation where users sign in with their Entra ID account
|
||||||
|
# (Himmelblau), with Microsoft Edge and Microsoft Defender for Endpoint.
|
||||||
|
# Himmelblau joins the device to Entra ID at the first sign-in and, with
|
||||||
|
# apply_policy, enrolls it in Intune and reports compliance.
|
||||||
|
|
||||||
|
metadata:
|
||||||
|
summary: Fedora minimal GNOME workstation with Entra ID sign-in and Intune
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# Ship /opt as a plain read-only directory instead of a symlink to /var/opt.
|
||||||
|
# Defender installs to /opt/microsoft/mdatp and keeps its state in
|
||||||
|
# /var/opt/microsoft/mdatp; with the default symlink those are the same,
|
||||||
|
# read-only directory. Needs composefs, which upstream enables. The vendor
|
||||||
|
# directories are linked into /opt by finalize.d/60-opt-links.
|
||||||
|
opt-usrlocal: root
|
||||||
|
|
||||||
|
repos:
|
||||||
|
- himmelblau
|
||||||
|
- microsoft-rhel10
|
||||||
|
- microsoft-edge
|
||||||
|
|
||||||
|
include:
|
||||||
|
- base-atomic.yaml
|
||||||
|
- custom.yaml
|
||||||
|
# Entra ID sign-in and Intune.
|
||||||
|
- himmelblau.yaml
|
||||||
|
- microsoft-edge.yaml
|
||||||
|
- defender.yaml
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Microsoft Edge, from the microsoft-edge repo (repos/microsoft.repo).
|
||||||
|
# Conditional Access to Microsoft 365 web apps on Linux requires Edge.
|
||||||
|
#
|
||||||
|
# Entra SSO in Edge: himmelblau-sso only registers its native messaging host
|
||||||
|
# and force-installs the Linux Entra SSO extension for Chrome, Chromium and
|
||||||
|
# Firefox. Edge reads /etc/opt/edge, so add the same two files there.
|
||||||
|
|
||||||
|
repo-packages:
|
||||||
|
- repo: microsoft-edge
|
||||||
|
packages:
|
||||||
|
- microsoft-edge-stable
|
||||||
|
|
||||||
|
add-files:
|
||||||
|
- ["edge-linux_entra_sso.json", "/etc/opt/edge/native-messaging-hosts/linux_entra_sso.json"]
|
||||||
|
- ["edge-himmelblau-policy.json", "/etc/opt/edge/policies/managed/himmelblau.json"]
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Himmelblau Community Nightly packages (free development builds). The
|
||||||
|
# maintained Stable repositories need a subscription entitlement token:
|
||||||
|
# https://himmelblau-idm.org/stable-repositories/
|
||||||
|
[himmelblau]
|
||||||
|
name=Himmelblau Community Nightly (Fedora 44)
|
||||||
|
baseurl=https://packages.himmelblau-idm.org/nightly/latest/rpm/fedora44
|
||||||
|
enabled=1
|
||||||
|
gpgcheck=1
|
||||||
|
gpgkey=https://packages.himmelblau-idm.org/himmelblau.asc
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# packages.microsoft.com, limited with includepkgs to the packages the image
|
||||||
|
# uses, so nothing else from the RHEL repo can replace a Fedora package.
|
||||||
|
|
||||||
|
[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=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
|
||||||
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Runs in the target root during `rpm-ostree compose image` (edition 2024
|
||||||
|
# finalize.d hook). rpm-ostree relocates RPM content under /opt to
|
||||||
|
# /usr/lib/opt. With `opt-usrlocal: root` /opt is a plain directory in the
|
||||||
|
# image and nothing links it back, so link each vendor directory. Images on the
|
||||||
|
# default (/opt -> /var/opt, linked by tmpfiles.d) are left alone.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
root="${PWD}"
|
||||||
|
|
||||||
|
[[ -d "${root}/usr/lib/opt" ]] || exit 0
|
||||||
|
if [[ -L "${root}/opt" || ! -d "${root}/opt" ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
for dir in "${root}"/usr/lib/opt/*; do
|
||||||
|
name="$(basename "${dir}")"
|
||||||
|
ln -sfn "../usr/lib/opt/${name}" "${root}/opt/${name}"
|
||||||
|
echo "Linked /opt/${name} -> /usr/lib/opt/${name}"
|
||||||
|
done
|
||||||
Reference in new issue
Block a user