Prepare to archive fleet-gitops repo (#50134)
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
name: fleetctl-gitops
|
||||
description: Runs fleetctl gitops to apply configuration to Fleet
|
||||
# Schema: https://json.schemastore.org/github-action.json
|
||||
|
||||
# This action expects the following env vars to be set:
|
||||
# - FLEET_URL: The URL of the Fleet server to apply configuration to.
|
||||
# - FLEET_API_TOKEN: An API token for a Fleet GitOps user.
|
||||
#
|
||||
# Optional:
|
||||
# - FLEET_GITOPS_DIR: The directory containing the GitOps config (default.yml,
|
||||
# fleets/*.yml). Defaults to the current directory.
|
||||
# - FLEET_CUSTOM_HEADERS: Comma-separated "Header:Value" pairs (e.g. a Cloudflare
|
||||
# Access service token) sent on every request to the Fleet server.
|
||||
|
||||
inputs:
|
||||
working-directory:
|
||||
description: 'The working directory, which should be the root of the repository.'
|
||||
default: './'
|
||||
dry-run-only:
|
||||
description: 'Whether to only run the fleetctl gitops commands in dry-run mode.'
|
||||
default: 'false'
|
||||
delete-other-fleets:
|
||||
description: 'Whether to delete other fleets in Fleet which are not part of the gitops config.'
|
||||
default: 'true'
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Install fleetctl
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
run: |
|
||||
FLEET_URL="${FLEET_URL%/}"
|
||||
|
||||
# Build optional custom request headers from FLEET_CUSTOM_HEADERS, a comma-separated
|
||||
# list of "Header:Value" pairs (e.g. a Cloudflare Access service token). Empty by default.
|
||||
CURL_HEADER_ARGS=()
|
||||
if [[ -n "${FLEET_CUSTOM_HEADERS:-}" ]]; then
|
||||
IFS=',' read -ra _CUSTOM_HEADERS <<< "$FLEET_CUSTOM_HEADERS"
|
||||
for _header in "${_CUSTOM_HEADERS[@]}"; do
|
||||
CURL_HEADER_ARGS+=(--header "$_header")
|
||||
done
|
||||
fi
|
||||
|
||||
FLEET_VERSION="$(curl "$FLEET_URL/api/v1/fleet/version" --header "Authorization: Bearer $FLEET_API_TOKEN" "${CURL_HEADER_ARGS[@]}" --fail --silent | jq --raw-output '.version')"
|
||||
DEFAULT_FLEETCTL_VERSION="latest"
|
||||
|
||||
# Decide which fleetctl version to install:
|
||||
# If the server returns a clean version (e.g. 4.74.0), use that.
|
||||
# If the server returns a snapshot (e.g. 0.0.0-SNAPSHOT-xxxxx) or is empty, pin to DEFAULT_FLEETCTL_VERSION.
|
||||
if [[ -z "$FLEET_VERSION" ]]; then
|
||||
INSTALL_VERSION="$DEFAULT_FLEETCTL_VERSION"
|
||||
elif [[ "$FLEET_VERSION" == 0.0.0-SNAPSHOT* ]]; then
|
||||
INSTALL_VERSION="$DEFAULT_FLEETCTL_VERSION"
|
||||
elif [[ "$FLEET_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
INSTALL_VERSION="$FLEET_VERSION"
|
||||
else
|
||||
# Strip anything after + (e.g. 4.81.0+foobar -> 4.81.0)
|
||||
FLEET_VERSION="${FLEET_VERSION%%\+*}"
|
||||
if [[ "$FLEET_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
INSTALL_VERSION="$FLEET_VERSION"
|
||||
else
|
||||
INSTALL_VERSION="$DEFAULT_FLEETCTL_VERSION"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Installing fleetctl v$INSTALL_VERSION..."
|
||||
npm install -g "fleetctl@$INSTALL_VERSION" || npm install -g fleetctl@latest
|
||||
|
||||
- name: Configure fleetctl
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
run: |
|
||||
# Build optional custom request headers from FLEET_CUSTOM_HEADERS, a comma-separated
|
||||
# list of "Header:Value" pairs. fleetctl persists them and sends them on every request,
|
||||
# so the gitops commands below use them too.
|
||||
CUSTOM_HEADER_ARGS=()
|
||||
if [[ -n "${FLEET_CUSTOM_HEADERS:-}" ]]; then
|
||||
IFS=',' read -ra _CUSTOM_HEADERS <<< "$FLEET_CUSTOM_HEADERS"
|
||||
for _header in "${_CUSTOM_HEADERS[@]}"; do
|
||||
CUSTOM_HEADER_ARGS+=(--custom-header "$_header")
|
||||
done
|
||||
fi
|
||||
fleetctl config set --address "$FLEET_URL" --token "$FLEET_API_TOKEN" "${CUSTOM_HEADER_ARGS[@]}"
|
||||
|
||||
- name: Run fleetctl gitops commands
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
env:
|
||||
FLEET_DRY_RUN_ONLY: ${{ inputs.dry-run-only }}
|
||||
FLEET_DELETE_OTHER_FLEETS: ${{ inputs.delete-other-fleets }}
|
||||
run: bash "$GITHUB_ACTION_PATH/gitops.sh"
|
||||
Executable
+59
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# -e: Immediately exit if any command has a non-zero exit status.
|
||||
# -x: Print all executed commands to the terminal.
|
||||
# -u: Exit if an undefined variable is used.
|
||||
# -o pipefail: Exit if any command in a pipeline fails.
|
||||
set -exuo pipefail
|
||||
|
||||
FLEET_GITOPS_DIR="${FLEET_GITOPS_DIR:-.}"
|
||||
FLEET_GLOBAL_FILE="${FLEET_GLOBAL_FILE:-$FLEET_GITOPS_DIR/default.yml}"
|
||||
FLEETCTL="${FLEETCTL:-fleetctl}"
|
||||
FLEET_DRY_RUN_ONLY="${FLEET_DRY_RUN_ONLY:-false}"
|
||||
FLEET_DELETE_OTHER_FLEETS="${FLEET_DELETE_OTHER_FLEETS:-true}"
|
||||
|
||||
# Check for existence of the global file in case the script is used
|
||||
# on repositories with fleet only yamls.
|
||||
if [ -f "$FLEET_GLOBAL_FILE" ]; then
|
||||
# Validate that global file contains org_settings
|
||||
grep -Exq "^org_settings:.*" "$FLEET_GLOBAL_FILE"
|
||||
else
|
||||
FLEET_DELETE_OTHER_FLEETS=false
|
||||
fi
|
||||
|
||||
# If you are using secrets to manage SSO metadata for Fleet SSO login or MDM SSO login, uncomment the below:
|
||||
|
||||
# FLEET_SSO_METADATA=$( sed '2,$s/^/ /' <<< "${FLEET_MDM_SSO_METADATA}")
|
||||
# FLEET_MDM_SSO_METADATA=$( sed '2,$s/^/ /' <<< "${FLEET_MDM_SSO_METADATA}")
|
||||
|
||||
# Copy/pasting raw SSO metadata into GitHub secrets will result in malformed yaml.
|
||||
# Adds spaces to all but the first line of metadata keeps the multiline string in bounds.
|
||||
|
||||
if compgen -G "$FLEET_GITOPS_DIR"/fleets/*.yml > /dev/null; then
|
||||
# Validate that every fleet has a unique name.
|
||||
# This is a limited check that assumes all fleet files contain the phrase: `name: <fleet_name>`
|
||||
! perl -nle 'print $1 if /^name:\s*(.+)$/' "$FLEET_GITOPS_DIR"/fleets/*.yml | sort | uniq -d | grep . -cq
|
||||
fi
|
||||
|
||||
args=()
|
||||
if [ -f "$FLEET_GLOBAL_FILE" ]; then
|
||||
args=(-f "$FLEET_GLOBAL_FILE")
|
||||
fi
|
||||
|
||||
for fleet_file in "$FLEET_GITOPS_DIR"/fleets/*.yml; do
|
||||
if [ -f "$fleet_file" ]; then
|
||||
args+=(-f "$fleet_file")
|
||||
fi
|
||||
done
|
||||
if [ "$FLEET_DELETE_OTHER_FLEETS" = true ]; then
|
||||
args+=(--delete-other-fleets)
|
||||
fi
|
||||
|
||||
# Dry run
|
||||
$FLEETCTL gitops "${args[@]}" --dry-run
|
||||
if [ "$FLEET_DRY_RUN_ONLY" = true ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Real run
|
||||
$FLEETCTL gitops "${args[@]}"
|
||||
@@ -43,18 +43,9 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Checkout GitOps repository
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
repository: fleetdm/fleet-gitops
|
||||
ref: main
|
||||
path: fleet-gitops
|
||||
persist-credentials: false
|
||||
|
||||
- name: Apply latest configuration to Fleet
|
||||
uses: ./fleet-gitops/.github/gitops-action-fleets
|
||||
uses: ./.github/actions/gitops
|
||||
with:
|
||||
working-directory: ${{ github.workspace }}/fleet-gitops
|
||||
dry-run-only: ${{ github.event_name == 'pull_request' && 'true' || 'false' }}
|
||||
env:
|
||||
FLEET_GITOPS_DIR: ${{ github.workspace }}/it-and-security
|
||||
|
||||
@@ -62,7 +62,7 @@ Fleet has a friendly UI and CLI to support traditional MDM workflows, and both b
|
||||
|
||||
- **Declarative YAML configuration:** Every aspect of Fleet's configuration can be declaratively expressed as YAML. Fleet reconciles its current configuration to match this codified configuration. Defined resources are created, and undefined resources are removed or reset to default values.
|
||||
- **Vendor-agnostic workflow tooling:** The `fleetctl gitops` command deploys configuration to the Fleet instance. Since this is a native CLI command, this approach is supported on any CI/CD tool or workflow engine. The `fleetctl gitops` command also provides a dry-run option for pull or merge requests.
|
||||
- **Starter GitOps repository with CI/CD pipelines:** Fleet provides [a GitOps template repository](https://github.com/fleetdm/fleet-gitops) with everything that you need to get started. The repository contains the necessary CI/CD scripts for GitHub Actions and GitLab CI/CD pipelines. It also ships with a recommended directory structure to enable organized and reusable code. This lets you get started quickly with GitOps best practices.
|
||||
- **Scaffolding you can generate in one command:** The `fleetctl new` command creates a starter GitOps repository with everything you need to get started. It includes the CI/CD scripts for GitHub Actions and GitLab pipelines, along with a recommended directory structure for organized, reusable code. This lets you get started quickly with GitOps best practices.
|
||||
- **Dedicated GitOps user role:** Fleet has a purpose-built GitOps role for API-only users. This role has specific authorization rules that enable configuration management. However, it can't access the Fleet UI. This ensures separation of concerns between human operators and automation.
|
||||
- **GitOps mode:** One of the biggest challenges with GitOps is avoiding configuration drift or manual changes. Fleet's UI can be placed into read-only mode to prevent any changes that don't go through your code repository.
|
||||
- **Migration tooling:** The `fleetctl generate-gitops` command exports your current configuration into GitOps-ready YAML files. This allows you to quickly adopt GitOps without redefining your entire configuration. Migrating an existing Fleet environment involves running a single command.
|
||||
@@ -95,17 +95,18 @@ The steps below assume that you are using GitHub, but the process is largely the
|
||||
|
||||
A key tenet of IaC best practices is a central code repository. This acts as the "single source of truth" for infrastructure configuration. The automation run within this repository must also have access to your Fleet environment. Let's start with this initial configuration, which you only need to do once.
|
||||
|
||||
Fleet provides a starter repository with a directory structure and automation scripts. Clone this repository:
|
||||
The `fleetctl new` command generates a starter repository with a directory structure and automation scripts. Run it and follow the prompts:
|
||||
|
||||
```bash
|
||||
git clone git@github.com:fleetdm/fleet-gitops.git
|
||||
fleetctl new
|
||||
```
|
||||
|
||||
Create a new repository in your GitHub account and update the Git origin to point at your repository:
|
||||
By default, this creates an `it-and-security` directory. Create a new repository in your GitHub account, then point the generated directory at it and push:
|
||||
|
||||
```bash
|
||||
cd fleet-gitops
|
||||
git remote set-url origin git@github.com:my-organization/fleet-test.git
|
||||
cd it-and-security
|
||||
git init -b main
|
||||
git remote add origin git@github.com:my-organization/fleet-config.git
|
||||
```
|
||||
|
||||
Create a service account user to access the Fleet API. The service account user can have global access, or you can scope access to a specific fleet. Both options are shown below:
|
||||
@@ -126,16 +127,16 @@ The GitHub Action must have environment information and credentials to make API
|
||||
* Set `FLEET_URL` to the URL of your Fleet instance. For example, `https://fleet.example.com`
|
||||
* Set `FLEET_API_TOKEN` to the API token for the service account user
|
||||
|
||||
This configuration provides everything needed for a basic GitOps configuration. The template repository provides two default fleets: "Personal mobile devices" and "Workstations". These are defined in `fleets/personal-mobile-devices.yml` and `fleets/workstations.yml`. You can keep these or create your own fleets according to your naming conventions.
|
||||
This configuration provides everything needed for a basic GitOps configuration. The generated repository provides two default fleets: "Personal mobile devices" and "Workstations". These are defined in `fleets/personal-mobile-devices.yml` and `fleets/workstations.yml`. You can keep these or create your own fleets according to your naming conventions.
|
||||
|
||||
The template repository also provides an initial directory structure for configuration. The `lib/` directory tree provides a solid foundation for developing modular configuration as code. Fleet supports referencing YAML files by path. This enables clean code that can be reused across fleets:
|
||||
The generated repository also includes an initial directory structure for configuration. You can define labels in `default.yml` or in files under `labels/`, and per-platform content like policies, scripts, and software lives under `platforms/` (for example, `platforms/linux/`). Fleet supports referencing YAML files by path. This enables clean code that can be reused across fleets:
|
||||
|
||||
```yaml
|
||||
# Partial code snippet from fleets/workstations.yml
|
||||
...
|
||||
controls:
|
||||
scripts:
|
||||
- path: ../lib/linux/scripts/fix-sudoers.sh
|
||||
- path: ../platforms/linux/scripts/fix-sudoers.sh
|
||||
```
|
||||
|
||||
Next, we will build on this structure to deploy changes to Fleet.
|
||||
@@ -147,9 +148,9 @@ Implementing this policy requires labels, a policy definition, and a control. Ea
|
||||
Add or modify each of the files below to implement the policy:
|
||||
|
||||
- `default.yml`: This file contains default settings that apply across fleets. This is where we define labels.
|
||||
- `fleets/workstations.yml`: This file contains configuration for the "Workstations" fleet. This is where we reference the policy and the control script. We can reference these from the `lib/` directory, which allows us to develop clean, reusable code. This code can be reused in other fleets.
|
||||
- `lib/linux/policies/internal-certificate.yml`: This file contains the policy definition and supporting query. The YAML keys will look familiar, since they are nearly identical to the fields in the web interface.
|
||||
- `lib/linux/scripts/install-internal-ca.sh`: This is a simple, distribution-agnostic script to remediate policy violations. It deploys the certificate on a host and updates the host's certificate store.
|
||||
- `fleets/workstations.yml`: This file contains configuration for the "Workstations" fleet. This is where we reference the policy and the control script. We can reference these from the `platforms/` directory, which allows us to develop clean, reusable code. This code can be reused in other fleets.
|
||||
- `platforms/linux/policies/internal-certificate.yml`: This file contains the policy definition and supporting query. The YAML keys will look familiar, since they are nearly identical to the fields in the web interface.
|
||||
- `platforms/linux/scripts/install-internal-ca.sh`: This is a simple, distribution-agnostic script to remediate policy violations. It deploys the certificate on a host and updates the host's certificate store.
|
||||
|
||||
Each configuration file is shown below.
|
||||
|
||||
@@ -181,20 +182,20 @@ labels:
|
||||
# fleets/workstations.yml
|
||||
name: "💻 Workstations"
|
||||
policies:
|
||||
- path: ../lib/linux/policies/internal-certificate.yml
|
||||
- path: ../platforms/linux/policies/internal-certificate.yml
|
||||
reports:
|
||||
agent_options:
|
||||
controls:
|
||||
scripts:
|
||||
- path: ../lib/linux/scripts/install-internal-ca.sh
|
||||
- path: ../platforms/linux/scripts/install-internal-ca.sh
|
||||
software:
|
||||
team_settings:
|
||||
```
|
||||
|
||||
**lib/linux/policies/internal-certificate.yml**
|
||||
**platforms/linux/policies/internal-certificate.yml**
|
||||
|
||||
```yaml
|
||||
# lib/linux/policies/internal-certificate.yml
|
||||
# platforms/linux/policies/internal-certificate.yml
|
||||
- name: Internal CA Certificate
|
||||
description: This policy checks if the internal CA certificate is present on hosts using the SHA1 of the certificate.
|
||||
resolution: The issue should be automatically remediated. Contact the IT helpdesk if you continue to have issues.
|
||||
@@ -211,11 +212,11 @@ team_settings:
|
||||
|
||||
> **Warning:** This configuration installs a specific root CA. Only use this in a lab environment. Never install a CA certificate from the internet onto a production machine unless you own the private key and understand the trust implications.
|
||||
|
||||
**lib/linux/scripts/install-internal-ca.sh**
|
||||
**platforms/linux/scripts/install-internal-ca.sh**
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# lib/linux/scripts/install-internal-ca.sh
|
||||
# platforms/linux/scripts/install-internal-ca.sh
|
||||
set -euo pipefail
|
||||
|
||||
CERT_NAME="internal-ca"
|
||||
@@ -335,7 +336,7 @@ labels:
|
||||
```
|
||||
|
||||
```yaml
|
||||
# lib/linux/policies/internal-certificate.yml
|
||||
# platforms/linux/policies/internal-certificate.yml
|
||||
- name: Internal CA Certificate
|
||||
description: This policy checks if the internal CA certificate is present on hosts using the SHA1 of the certificate.
|
||||
resolution: The issue should be automatically remediated. Contact the IT helpdesk if you continue to have issues.
|
||||
@@ -389,7 +390,7 @@ To learn more about Fleet or to get a demo [contact us](https://fleetdm.com/cont
|
||||
|
||||
## Additional resources
|
||||
|
||||
- [Fleet starter repository](https://github.com/fleetdm/fleet-gitops)
|
||||
- [fleetctl CLI](https://fleetdm.com/guides/fleetctl)
|
||||
- [GitOps landing page](https://fleetdm.com/infrastructure-as-code)
|
||||
- [GitOps YAML file documentation](https://fleetdm.com/docs/configuration/yaml-files)
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ You can require IdP authentication during automatic enrollment (ADE) for Apple (
|
||||
|
||||
3. Make sure your end users' full names are set to one of the following attributes (depends on IdP): `name`, `displayname`, `cn`, `urn:oid:2.5.4.3`, or `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name`. Fleet will automatically populate the macOS local account **Full Name** with any of these.
|
||||
|
||||
4. In Fleet, configure your IdP by heading to **Settings > Integrations > Single sign-on (SSO) > End users**. Then, enable IdP authentication by heading to **Controls > Setup experience > Require IdP authentication**. Alternatively, you can use [Fleet's GitOps workflow](https://github.com/fleetdm/fleet-gitops) to configure your IdP integration and enable IdP authentication.
|
||||
4. In Fleet, configure your IdP by heading to **Settings > Integrations > Single sign-on (SSO) > End users**. Then, enable IdP authentication by heading to **Controls > Setup experience > Require IdP authentication**. Alternatively, you can use [Fleet's GitOps workflow](https://fleetdm.com/docs/configuration/yaml-files) to configure your IdP integration and enable IdP authentication.
|
||||
|
||||
> If you've already configured [single sign-on
|
||||
> (SSO)](https://fleetdm.com/docs/deploy/single-sign-on-sso) in Fleet, you still want to create a
|
||||
@@ -97,7 +97,7 @@ This feature is available for macOS hosts that automatically enroll via Apple Bu
|
||||
|
||||
To enable managed local accounts:
|
||||
|
||||
1. In Fleet, head to **Controls > Setup experience > Users** and check **Managed local account**. Alternatively, you can enable this using [Fleet's REST API](https://fleetdm.com/docs/rest-api/rest-api#update-setup-experience) or [GitOps workflow](https://github.com/fleetdm/fleet-gitops).
|
||||
1. In Fleet, head to **Controls > Setup experience > Users** and check **Managed local account**. Alternatively, you can enable this using [Fleet's REST API](https://fleetdm.com/docs/rest-api/rest-api#update-setup-experience) or [GitOps workflow](https://fleetdm.com/docs/configuration/yaml-files).
|
||||
|
||||
2. Wipe and re-enroll any existing macOS hosts that should receive the account. Hosts enrolled before the feature is turned on won't receive a managed account until they go through Setup Assistant again.
|
||||
|
||||
|
||||
@@ -71,9 +71,9 @@ Wait for build to run, which typically takes about fifteen minutes.
|
||||
|
||||
Wait for publish process to complete.
|
||||
|
||||
**6. Update the fleetdm/terraform and fleetdm/fleet-gitops repos**
|
||||
**6. Update the fleetdm/terraform repo**
|
||||
|
||||
Update all Fleet version references in our [fleetdm/terraform](https://github.com/fleetdm/fleet-terraform) repo and submit a PR. Then update `DEFAULT_FLEETCTL_VERSION` in `.github/gitops-action/action.yml` in [fleetdm/fleet-gitops](https://github.com/fleetdm/fleet-gitops) and submit a PR.
|
||||
Update all Fleet version references in our [fleetdm/terraform](https://github.com/fleetdm/fleet-terraform) repo and submit a PR.
|
||||
|
||||
|
||||
**7. Merge milestone pull requests**
|
||||
@@ -150,9 +150,9 @@ Wait for build to run, which typically takes about fifteen minutes.
|
||||
|
||||
> During the publish process, the release script will attempt to publish `fleetctl` to NPM. If this times out or otherise fails, you need to publish to NPM manually. From the `/tools/fleetctl-npm/` directory, run `npm publish`.
|
||||
|
||||
**7. Update the fleetdm/terraform and fleetdm/fleet-gitops repos**
|
||||
**7. Update the fleetdm/terraform repo**
|
||||
|
||||
Update all Fleet version references in our [fleetdm/terraform](https://github.com/fleetdm/fleet-terraform) repo and submit a PR. Then, if this release is _not_ a backport, update `DEFAULT_FLEETCTL_VERSION` in `.github/gitops-action/action.yml` in [fleetdm/fleet-gitops](https://github.com/fleetdm/fleet-gitops) and submit a PR.
|
||||
Update all Fleet version references in our [fleetdm/terraform](https://github.com/fleetdm/fleet-terraform) repo and submit a PR.
|
||||
|
||||
**8. Announce the release**
|
||||
|
||||
|
||||
Reference in New Issue
Block a user