diff --git a/.github/workflows/build-and-check-fleetctl-docker-and-deps.yml b/.github/workflows/build-and-check-fleetctl-docker-and-deps.yml
index 50f4e58f13..ff20260409 100644
--- a/.github/workflows/build-and-check-fleetctl-docker-and-deps.yml
+++ b/.github/workflows/build-and-check-fleetctl-docker-and-deps.yml
@@ -47,7 +47,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
+ go-version-file: 'go.mod'
- name: Install Go Dependencies
run: make deps-go
diff --git a/.github/workflows/build-binaries.yaml b/.github/workflows/build-binaries.yaml
index ed18437c74..278f958b28 100644
--- a/.github/workflows/build-binaries.yaml
+++ b/.github/workflows/build-binaries.yaml
@@ -29,10 +29,13 @@ jobs:
with:
egress-policy: audit
+ - name: Checkout Code
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
+ go-version-file: 'go.mod'
# Set the Node.js version
- name: Set up Node.js ${{ vars.NODE_VERSION }}
@@ -40,9 +43,6 @@ jobs:
with:
node-version: ${{ vars.NODE_VERSION }}
- - name: Checkout Code
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
-
- name: JS Dependency Cache
id: js-cache
uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 # v2
diff --git a/.github/workflows/build-orbit.yaml b/.github/workflows/build-orbit.yaml
index 09f296aece..002d2657f6 100644
--- a/.github/workflows/build-orbit.yaml
+++ b/.github/workflows/build-orbit.yaml
@@ -59,7 +59,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
+ go-version-file: 'go.mod'
- name: Build, codesign and notarize orbit
run: go run ./orbit/tools/build/build.go
diff --git a/.github/workflows/check-automated-doc.yml b/.github/workflows/check-automated-doc.yml
index c654e7ae4f..d289c55318 100644
--- a/.github/workflows/check-automated-doc.yml
+++ b/.github/workflows/check-automated-doc.yml
@@ -36,15 +36,16 @@ jobs:
with:
egress-policy: audit
- - name: Install Go
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
- with:
- go-version: ${{ vars.GO_VERSION }}
- name: Checkout Code
uses: actions/checkout@629c2de402a417ea7690ca6ce3f33229e27606a5 # v2
with:
fetch-depth: 0
+ - name: Install Go
+ uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
+ with:
+ go-version-file: 'go.mod'
+
- name: Verify golang generated documentation is up-to-date
run: |
make generate-doc
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 246c6418a1..c69888f874 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -56,7 +56,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
+ go-version-file: 'go.mod'
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
diff --git a/.github/workflows/deploy-fleet-website.yml b/.github/workflows/deploy-fleet-website.yml
index 9fc044e13b..371a0014f0 100644
--- a/.github/workflows/deploy-fleet-website.yml
+++ b/.github/workflows/deploy-fleet-website.yml
@@ -64,7 +64,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
+ go-version-file: 'go.mod'
# Download top-level dependencies and build Storybook in the website's assets/ folder
- run: npm install --legacy-peer-deps && npm run build-storybook -- -o ./website/assets/storybook --loglevel verbose
diff --git a/.github/workflows/dogfood-deploy.yml b/.github/workflows/dogfood-deploy.yml
index f9d8cff071..f17768eec7 100644
--- a/.github/workflows/dogfood-deploy.yml
+++ b/.github/workflows/dogfood-deploy.yml
@@ -51,14 +51,17 @@ jobs:
- id: fail-on-main
run: "false"
if: ${{ github.ref == 'main' }}
+
- uses: aws-actions/configure-aws-credentials@67fbcbb121271f7775d2e7715933280b06314838 # v1.7.0
with:
role-to-assume: ${{env.AWS_IAM_ROLE}}
aws-region: ${{ env.AWS_REGION }}
+
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
+ go-version-file: 'go.mod'
+
- uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 # v2.0.3
with:
terraform_version: 1.6.3
diff --git a/.github/workflows/fleet-and-orbit.yml b/.github/workflows/fleet-and-orbit.yml
index 571d59d067..f4dfb2780e 100644
--- a/.github/workflows/fleet-and-orbit.yml
+++ b/.github/workflows/fleet-and-orbit.yml
@@ -62,7 +62,6 @@ jobs:
timeout-minutes: 60
strategy:
matrix:
- go-version: ["${{ vars.GO_VERSION }}"]
mysql: ["mysql:8.0.36"]
runs-on: ubuntu-latest
needs: gen
@@ -72,10 +71,13 @@ jobs:
with:
egress-policy: audit
+ - name: Checkout Code
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ matrix.go-version }}
+ go-version-file: 'go.mod'
# Set the Node.js version
- name: Set up Node.js ${{ vars.NODE_VERSION }}
@@ -83,9 +85,6 @@ jobs:
with:
node-version: ${{ vars.NODE_VERSION }}
- - name: Checkout Code
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
-
- name: Start tunnel
env:
CERT_PEM: ${{ secrets.CLOUDFLARE_TUNNEL_FLEETUEM_CERT_B64 }}
@@ -175,9 +174,6 @@ jobs:
# This job also makes sure the Fleet server is up and running.
set-enroll-secret:
timeout-minutes: 60
- strategy:
- matrix:
- go-version: ["${{ vars.GO_VERSION }}"]
runs-on: ubuntu-latest
needs: gen
steps:
@@ -186,13 +182,13 @@ jobs:
with:
egress-policy: audit
+ - name: Checkout Code
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ matrix.go-version }}
-
- - name: Checkout Code
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ go-version-file: 'go.mod'
- name: Build Fleetctl
run: make fleetctl
@@ -218,9 +214,6 @@ jobs:
# Here we generate the Fleet Desktop and osqueryd targets for
# macOS which can only be generated from a macOS host.
build-macos-targets:
- strategy:
- matrix:
- go-version: ["${{ vars.GO_VERSION }}"]
# Set macOS version to '12' (current equivalent to macos-latest) for
# building the binary. This ensures compatibility with macOS version 13 and
# later, avoiding runtime errors on systems using macOS 13 or newer.
@@ -234,13 +227,13 @@ jobs:
with:
egress-policy: audit
+ - name: Checkout Code
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ matrix.go-version }}
-
- - name: Checkout Code
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ go-version-file: 'go.mod'
- name: Build desktop.app.tar.gz and osqueryd.app.tar.gz
run: |
@@ -269,9 +262,6 @@ jobs:
# installed, and installing it is time consuming and unreliable.
run-tuf-and-gen-pkgs:
timeout-minutes: 60
- strategy:
- matrix:
- go-version: ["${{ vars.GO_VERSION }}"]
runs-on: ubuntu-latest
needs: [gen, build-macos-targets]
steps:
@@ -280,13 +270,13 @@ jobs:
with:
egress-policy: audit
+ - name: Checkout Code
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ matrix.go-version }}
-
- - name: Checkout Code
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ go-version-file: 'go.mod'
- name: Download macos pre-built apps
id: download
diff --git a/.github/workflows/fleetctl-preview-latest.yml b/.github/workflows/fleetctl-preview-latest.yml
index dda4e0f73c..630cfd1dc3 100644
--- a/.github/workflows/fleetctl-preview-latest.yml
+++ b/.github/workflows/fleetctl-preview-latest.yml
@@ -53,7 +53,6 @@ jobs:
# - Unattended installation of Docker on macOS fails. (see
# https://github.com/docker/for-mac/issues/6450)
os: [ubuntu-latest]
- go-version: ['${{ vars.GO_VERSION }}']
runs-on: ${{ matrix.os }}
steps:
@@ -62,13 +61,13 @@ jobs:
with:
egress-policy: audit
+ - name: Checkout Code
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ matrix.go-version }}
-
- - name: Checkout Code
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ go-version-file: 'go.mod'
- name: Build Fleetctl
run: make fleetctl
diff --git a/.github/workflows/fleetd-tuf.yml b/.github/workflows/fleetd-tuf.yml
index ebeca889da..7641589f10 100644
--- a/.github/workflows/fleetd-tuf.yml
+++ b/.github/workflows/fleetd-tuf.yml
@@ -30,16 +30,16 @@ jobs:
with:
egress-policy: audit
- - name: Install Go
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
- with:
- go-version: ${{ vars.GO_VERSION }}
-
- name: Checkout Code
uses: actions/checkout@629c2de402a417ea7690ca6ce3f33229e27606a5 # v2
with:
fetch-depth: 0
+ - name: Install Go
+ uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
+ with:
+ go-version-file: 'go.mod'
+
- name: Update orbit/TUF.md
run: |
make fleetd-tuf
diff --git a/.github/workflows/generate-desktop-targets.yml b/.github/workflows/generate-desktop-targets.yml
index 67313ea762..d7324c9bf0 100644
--- a/.github/workflows/generate-desktop-targets.yml
+++ b/.github/workflows/generate-desktop-targets.yml
@@ -45,13 +45,13 @@ jobs:
with:
egress-policy: audit
+ - name: Checkout
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
-
- - name: Checkout
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ go-version-file: 'go.mod'
- name: Import signing keys
env:
@@ -98,13 +98,13 @@ jobs:
with:
egress-policy: audit
+ - name: Checkout
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
-
- - name: Checkout
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ go-version-file: 'go.mod'
- name: Generate fleet-desktop.exe
run: |
@@ -139,13 +139,13 @@ jobs:
with:
egress-policy: audit
+ - name: Checkout
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
-
- - name: Checkout
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ go-version-file: 'go.mod'
- name: Generate desktop.tar.gz
run: |
@@ -167,13 +167,13 @@ jobs:
with:
egress-policy: audit
+ - name: Checkout
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
-
- - name: Checkout
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ go-version-file: 'go.mod'
- name: Generate desktop.tar.gz
run: |
diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml
index df6b9792b7..3d3e95ed2c 100644
--- a/.github/workflows/golangci-lint.yml
+++ b/.github/workflows/golangci-lint.yml
@@ -38,7 +38,6 @@ jobs:
matrix:
# See #9943, we just need to add windows-latest here once all issues are fixed.
os: [ubuntu-latest, macos-latest]
- go-version: ['${{ vars.GO_VERSION }}']
runs-on: ${{ matrix.os }}
steps:
- name: Harden Runner
@@ -52,7 +51,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ matrix.go-version }}
+ go-version-file: 'go.mod'
- name: Install dependencies (Linux)
if: matrix.os == 'ubuntu-latest'
diff --git a/.github/workflows/goreleaser-fleet.yaml b/.github/workflows/goreleaser-fleet.yaml
index f4224907e0..6ba9aff8f0 100644
--- a/.github/workflows/goreleaser-fleet.yaml
+++ b/.github/workflows/goreleaser-fleet.yaml
@@ -44,7 +44,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
+ go-version-file: 'go.mod'
# Set the Node.js version
- name: Set up Node.js ${{ vars.NODE_VERSION }}
diff --git a/.github/workflows/goreleaser-orbit.yaml b/.github/workflows/goreleaser-orbit.yaml
index 666f281120..54e16752b3 100644
--- a/.github/workflows/goreleaser-orbit.yaml
+++ b/.github/workflows/goreleaser-orbit.yaml
@@ -56,7 +56,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
+ go-version-file: 'go.mod'
- name: Run GoReleaser
run: go run github.com/goreleaser/goreleaser@56c9d09a1b925e2549631c6d180b0a1c2ebfac82 release --debug --rm-dist --skip-publish -f orbit/goreleaser-macos.yml # v1.20.0
@@ -95,7 +95,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
+ go-version-file: 'go.mod'
- name: Run GoReleaser
run: go run github.com/goreleaser/goreleaser@56c9d09a1b925e2549631c6d180b0a1c2ebfac82 release --debug --rm-dist --skip-publish -f orbit/goreleaser-linux.yml # v1.20.0
@@ -128,7 +128,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
+ go-version-file: 'go.mod'
- name: Run GoReleaser
run: go run github.com/goreleaser/goreleaser@56c9d09a1b925e2549631c6d180b0a1c2ebfac82 release --debug --rm-dist --skip-publish -f orbit/goreleaser-linux-arm64.yml # v1.20.0
@@ -161,7 +161,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
+ go-version-file: 'go.mod'
- name: Run GoReleaser
run: go run github.com/goreleaser/goreleaser@56c9d09a1b925e2549631c6d180b0a1c2ebfac82 release --debug --rm-dist --skip-publish -f orbit/goreleaser-windows.yml # v1.20.0
diff --git a/.github/workflows/goreleaser-snapshot-fleet.yaml b/.github/workflows/goreleaser-snapshot-fleet.yaml
index 46c1da4193..927cf31be1 100644
--- a/.github/workflows/goreleaser-snapshot-fleet.yaml
+++ b/.github/workflows/goreleaser-snapshot-fleet.yaml
@@ -57,7 +57,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
+ go-version-file: 'go.mod'
# Set the Node.js version
- name: Set up Node.js ${{ vars.NODE_VERSION }}
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 015a464b4b..98c9cd3a59 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -264,13 +264,13 @@ jobs:
npm install -g fleetctl
fleetctl config set --address ${{ needs.gen.outputs.address }} --token ${{ needs.login.outputs.token }}
+ - name: Checkout Code
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
-
- - name: Checkout Code
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ go-version-file: 'go.mod'
- name: Build Fleetctl
run: make fleetctl
diff --git a/.github/workflows/release-fleetctl-docker-deps.yaml b/.github/workflows/release-fleetctl-docker-deps.yaml
index 8fc698f6ac..c751655d93 100644
--- a/.github/workflows/release-fleetctl-docker-deps.yaml
+++ b/.github/workflows/release-fleetctl-docker-deps.yaml
@@ -36,13 +36,13 @@ jobs:
with:
egress-policy: audit
+ - name: Checkout Code
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ vars.GO_VERSION }}
-
- - name: Checkout Code
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ go-version-file: 'go.mod'
- name: Login to Docker Hub
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
diff --git a/.github/workflows/release-fleetd-base.yml b/.github/workflows/release-fleetd-base.yml
index d7b02cfcf7..9909901964 100644
--- a/.github/workflows/release-fleetd-base.yml
+++ b/.github/workflows/release-fleetd-base.yml
@@ -51,16 +51,16 @@ jobs:
with:
egress-policy: audit
- - name: Install Go
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
- with:
- go-version: ${{ vars.GO_VERSION }}
-
- name: Checkout Code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0
+ - name: Install Go
+ uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
+ with:
+ go-version-file: 'go.mod'
+
- name: Check for fleetd component updates
id: check-for-fleetd-component-updates
run: |
diff --git a/.github/workflows/test-db-changes.yml b/.github/workflows/test-db-changes.yml
index ecfe464072..a5b7dd91e3 100644
--- a/.github/workflows/test-db-changes.yml
+++ b/.github/workflows/test-db-changes.yml
@@ -35,15 +35,16 @@ jobs:
with:
egress-policy: audit
- - name: Install Go
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
- with:
- go-version: ${{ vars.GO_VERSION }}
- name: Checkout Code
uses: actions/checkout@629c2de402a417ea7690ca6ce3f33229e27606a5 # v2
with:
fetch-depth: 0
+ - name: Install Go
+ uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
+ with:
+ go-version-file: 'go.mod'
+
- name: Start Infra Dependencies
# Use & to background this
run: docker compose up -d mysql_test &
diff --git a/.github/workflows/test-fleetd-chrome.yml b/.github/workflows/test-fleetd-chrome.yml
index 47ba496ebb..8cbb0125f9 100644
--- a/.github/workflows/test-fleetd-chrome.yml
+++ b/.github/workflows/test-fleetd-chrome.yml
@@ -66,7 +66,8 @@ jobs:
npm test
- name: Upload to Codecov
- uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1
+ uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
with:
+ token: ${{ secrets.CODECOV_TOKEN }}
directory: ./ee/fleetd-chrome/coverage
flags: fleetd-chrome
diff --git a/.github/workflows/test-go.yaml b/.github/workflows/test-go.yaml
index 9feba50d8e..b5f2b8fe94 100644
--- a/.github/workflows/test-go.yaml
+++ b/.github/workflows/test-go.yaml
@@ -44,7 +44,6 @@ jobs:
matrix:
suite: ["integration", "core"]
os: [ubuntu-latest]
- go-version: ['${{ vars.GO_VERSION }}']
mysql: ["mysql:8.0.36", "mysql:8.4.2"]
continue-on-error: ${{ matrix.suite == 'integration' }} # Since integration tests have a higher chance of failing, often for unrelated reasons, we don't want to fail the whole job if they fail
runs-on: ${{ matrix.os }}
@@ -65,7 +64,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
with:
- go-version: ${{ matrix.go-version }}
+ go-version-file: 'go.mod'
# Pre-starting dependencies here means they are ready to go when we need them.
- name: Start Infra Dependencies
@@ -131,13 +130,17 @@ jobs:
NETWORK_TEST_GITHUB_TOKEN=${{ secrets.FLEET_RELEASE_GITHUB_PAT }} \
make test-go 2>&1 | tee /tmp/gotest.log
- # note: it's fine to upload multiple reports (one per matrix combination)
- # for the same run, see https://docs.codecov.com/docs/merging-reports
- - name: Upload to Codecov
- uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70
+ - name: Create mysql identifier without colon
+ if: always()
+ run: |
+ echo "MATRIX_MYSQL_ID=$(echo ${{ matrix.mysql }} | tr -d ':')" >> $GITHUB_ENV
+
+ - name: Save coverage
+ uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
with:
- files: coverage.txt
- flags: backend
+ name: ${{ matrix.suite }}-${{ env.MATRIX_MYSQL_ID }}-coverage
+ path: ./coverage.txt
+ if-no-files-found: error
- name: Generate summary of errors
if: failure()
@@ -167,14 +170,9 @@ jobs:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_G_HELP_ENGINEERING_WEBHOOK_URL }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
- - name: Create mysql identifier without colon
- if: always()
- run: |
- echo "MATRIX_MYSQL_ID=$(echo ${{ matrix.mysql }} | tr -d ':')" >> $GITHUB_ENV
-
- name: Upload test log
if: always()
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v2
+ uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
with:
name: ${{ matrix.suite }}-${{ env.MATRIX_MYSQL_ID }}-test-log
path: /tmp/gotest.log
@@ -182,7 +180,24 @@ jobs:
- name: Upload summary test log
if: always()
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v2
+ uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
with:
name: ${{ matrix.suite }}-${{ env.MATRIX_MYSQL_ID }}-summary-test-log
path: /tmp/summary.txt
+
+ # We upload all backend coverage in one step so that we're less like to end up in a situation with a partial coverage report.
+ upload-coverage:
+ needs: [test-go]
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ - name: Download artifacts
+ uses: actions/download-artifact@9c19ed7fe5d278cd354c7dfd5d3b88589c7e2395 # v4.1.6
+ with:
+ pattern: '*-coverage'
+ - name: Upload to Codecov
+ uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ flags: backend
diff --git a/.github/workflows/test-js.yml b/.github/workflows/test-js.yml
index 9d63523737..15b4fd05ce 100644
--- a/.github/workflows/test-js.yml
+++ b/.github/workflows/test-js.yml
@@ -69,8 +69,9 @@ jobs:
yarn test:ci
- name: Upload to Codecov
- uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70
+ uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
with:
+ token: ${{ secrets.CODECOV_TOKEN }}
flags: frontend
lint-js:
diff --git a/.github/workflows/test-native-tooling-packaging.yml b/.github/workflows/test-native-tooling-packaging.yml
index 7678e7eeaa..ff0dc4abad 100644
--- a/.github/workflows/test-native-tooling-packaging.yml
+++ b/.github/workflows/test-native-tooling-packaging.yml
@@ -41,7 +41,6 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest]
- go-version: ['${{ vars.GO_VERSION }}']
runs-on: ${{ matrix.os }}
steps:
@@ -50,13 +49,13 @@ jobs:
with:
egress-policy: audit
+ - name: Checkout Code
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ matrix.go-version }}
-
- - name: Checkout Code
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ go-version-file: 'go.mod'
- name: Install Go Dependencies
run: make deps-go
diff --git a/.github/workflows/test-packaging.yml b/.github/workflows/test-packaging.yml
index f9643bd4e9..dbe5a96244 100644
--- a/.github/workflows/test-packaging.yml
+++ b/.github/workflows/test-packaging.yml
@@ -47,7 +47,6 @@ jobs:
# `macos-latest` uses arm64 by default now, so please be careful when
# updating this version.
os: [ubuntu-latest, macos-13]
- go-version: ['${{ vars.GO_VERSION }}']
runs-on: ${{ matrix.os }}
steps:
@@ -83,13 +82,13 @@ jobs:
brew install colima
colima start --mount $TMPDIR:w
+ - name: Checkout Code
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ matrix.go-version }}
-
- - name: Checkout Code
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ go-version-file: 'go.mod'
- name: Install wine and wix
if: startsWith(matrix.os, 'macos')
diff --git a/.github/workflows/test-yml-specs.yml b/.github/workflows/test-yml-specs.yml
index 75e46d6af0..fe8f3ecace 100644
--- a/.github/workflows/test-yml-specs.yml
+++ b/.github/workflows/test-yml-specs.yml
@@ -33,7 +33,6 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
- go-version: ['${{ vars.GO_VERSION }}']
runs-on: ${{ matrix.os }}
steps:
@@ -42,13 +41,13 @@ jobs:
with:
egress-policy: audit
+ - name: Checkout Code
+ uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
- go-version: ${{ matrix.go-version }}
-
- - name: Checkout Code
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ go-version-file: 'go.mod'
- name: Run apply spec tests
run: |
diff --git a/articles/mdm-migration.md b/articles/mdm-migration.md
index 76c6254125..5eb9e8473d 100644
--- a/articles/mdm-migration.md
+++ b/articles/mdm-migration.md
@@ -1,11 +1,15 @@
# MDM migration
-This section provides instructions for migrating your hosts away from your old MDM solution to Fleet.
+This guide provides instructions for migrating devices from your current MDM solution to Fleet.
+
+> For seamless MDM migration, [view this guide](https://fleetdm.com/guides/seamless-mdm-migration).
## Requirements
-1. A [deployed Fleet instance](https://fleetdm.com/docs/deploy/deploy-fleet)
-2. [Fleet connected to Apple](https://fleetdm.com/guides/macos-mdm-setup)
+
+- A [deployed Fleet instance](https://fleetdm.com/docs/deploy/deploy-fleet)
+- Fleet is connected to Apple Push Notification service (APNs) and Apple Business Manager (ABM). [See macOS MDM setup](https://fleetdm.com/guides/macos-mdm-setup)
+
## Migrate manually enrolled hosts
diff --git a/changes/19551-policy-software-automations b/changes/19551-policy-software-automations
new file mode 100644
index 0000000000..4b88cb4c1f
--- /dev/null
+++ b/changes/19551-policy-software-automations
@@ -0,0 +1 @@
+* Implement features allowing automatic installation of software on hosts that fail policies.
diff --git a/changes/21315-vpp-premium-license b/changes/21315-vpp-premium-license
new file mode 100644
index 0000000000..2fd081703e
--- /dev/null
+++ b/changes/21315-vpp-premium-license
@@ -0,0 +1 @@
+- Verify user has premium license before uploading VPP tokens
diff --git a/changes/21757-fix-scheduling-cron-jobs-at-startup b/changes/21757-fix-scheduling-cron-jobs-at-startup
new file mode 100644
index 0000000000..b54ae2c84f
--- /dev/null
+++ b/changes/21757-fix-scheduling-cron-jobs-at-startup
@@ -0,0 +1 @@
+* Fixed an issue with the scheduling of cron jobs at startup if the job has never run, which caused it to be delayed.
diff --git a/changes/apns-errors b/changes/apns-errors
new file mode 100644
index 0000000000..6de48617a1
--- /dev/null
+++ b/changes/apns-errors
@@ -0,0 +1 @@
+* Fixed logic to properly catch and log APNs errors.
diff --git a/cmd/fleet/serve.go b/cmd/fleet/serve.go
index 67ce51f7d0..6c363965a8 100644
--- a/cmd/fleet/serve.go
+++ b/cmd/fleet/serve.go
@@ -633,6 +633,12 @@ the way that the Fleet server works.
appCfg.MDM.AppleBMEnabledAndConfigured = count > 0
}
}
+ if appCfg.MDM.EnabledAndConfigured {
+ level.Info(logger).Log("msg", "Apple MDM enabled")
+ }
+ if appCfg.MDM.AppleBMEnabledAndConfigured {
+ level.Info(logger).Log("msg", "Apple Business Manager enabled")
+ }
// register the Microsoft MDM services
var (
diff --git a/docs/REST API/rest-api.md b/docs/REST API/rest-api.md
index 607ac2f28d..c4ad4e3858 100644
--- a/docs/REST API/rest-api.md
+++ b/docs/REST API/rest-api.md
@@ -1090,7 +1090,7 @@ Modifies the Fleet's configuration with the supplied information.
| integrations | object | body | Includes `jira`, `zendesk`, and `google_calendar` arrays. See [integrations](#integrations) for details. |
| mdm | object | body | See [mdm](#mdm). |
| features | object | body | See [features](#features). |
-| scripts | list | body | A list of script files to add so they can be executed at a later time. |
+| scripts | array | body | A list of script files to add so they can be executed at a later time. |
| force | boolean | query | Whether to force-apply the agent options even if there are validation errors. |
| dry_run | boolean | query | Whether to validate the configuration and return any validation errors **without** applying changes. |
@@ -1518,10 +1518,10 @@ _Available in Fleet Premium._
| Name | Type | Description |
| --------------------- | ----- | ---------------------------------------------------------------------------------------------- |
-| host_status_webhook | list | See [`webhook_settings.host_status_webhook`](#webhook-settings-host-status-webhook). |
-| failing_policies_webhook | list | See [`webhook_settings.failing_policies_webhook`](#webhook-settings-failing-policies-webhook). |
-| vulnerabilities_webhook | list | See [`webhook_settings.vulnerabilities_webhook`](#webhook-settings-vulnerabilities-webhook). |
-| activities_webhook | list | See [`webhook_settings.activities_webhook`](#webhook-settings-activities-webhook). |
+| host_status_webhook | array | See [`webhook_settings.host_status_webhook`](#webhook-settings-host-status-webhook). |
+| failing_policies_webhook | array | See [`webhook_settings.failing_policies_webhook`](#webhook-settings-failing-policies-webhook). |
+| vulnerabilities_webhook | array | See [`webhook_settings.vulnerabilities_webhook`](#webhook-settings-vulnerabilities-webhook). |
+| activities_webhook | array | See [`webhook_settings.activities_webhook`](#webhook-settings-activities-webhook). |
@@ -1614,9 +1614,9 @@ _Available in Fleet Premium._
| Name | Type | Description |
| --------------------- | ----- | -------------------------------------------------------------------- |
-| jira | list | See [`integrations.jira`](#integrations-jira). |
-| zendesk | list | See [`integrations.zendesk`](#integrations-zendesk). |
-| google_calendar | list | See [`integrations.google_calendar`](#integrations-google-calendar). |
+| jira | array | See [`integrations.jira`](#integrations-jira). |
+| zendesk | array | See [`integrations.zendesk`](#integrations-zendesk). |
+| google_calendar | array | See [`integrations.google_calendar`](#integrations-google-calendar). |
> Note that when making changes to the `integrations` object, all integrations must be provided (not just the one being modified). This is because the endpoint will consider missing integrations as deleted.
@@ -1792,7 +1792,7 @@ _Available in Fleet Premium._
| Name | Type | Description |
| --------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| custom_settings | list | macOS hosts that belong to no team will have custom profiles applied. |
+| custom_settings | array | macOS hosts that belong to no team will have custom profiles applied. |
@@ -1802,7 +1802,7 @@ _Available in Fleet Premium._
| Name | Type | Description |
| --------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| custom_settings | list | Windows hosts that belong to no team will have custom profiles applied. |
+| custom_settings | array | Windows hosts that belong to no team will have custom profiles applied. |
@@ -2099,7 +2099,7 @@ Delete all of a team's existing enroll secrets
| email | string | body | **Required.** The email of the invited user. This email will receive the invitation link. |
| name | string | body | **Required.** The name of the invited user. |
| sso_enabled | boolean | body | **Required.** Whether or not SSO will be enabled for the invited user. |
-| teams | list | body | _Available in Fleet Premium_. A list of the teams the user is a member of. Each item includes the team's ID and the user's role in the specified team. |
+| teams | array | body | _Available in Fleet Premium_. A list of the teams the user is a member of. Each item includes the team's ID and the user's role in the specified team. |
#### Example
@@ -2299,7 +2299,7 @@ Verify the specified invite.
| email | string | body | The email of the invited user. Updates on the email won't resend the invitation. |
| name | string | body | The name of the invited user. |
| sso_enabled | boolean | body | Whether or not SSO will be enabled for the invited user. |
-| teams | list | body | _Available in Fleet Premium_. A list of the teams the user is a member of. Each item includes the team's ID and the user's role in the specified team. |
+| teams | array | body | _Available in Fleet Premium_. A list of the teams the user is a member of. Each item includes the team's ID and the user's role in the specified team. |
#### Example
@@ -2489,6 +2489,7 @@ the `software` table.
| mdm_id | integer | query | The ID of the _mobile device management_ (MDM) solution to filter hosts by (that is, filter hosts that use a specific MDM provider and URL). |
| mdm_name | string | query | The name of the _mobile device management_ (MDM) solution to filter hosts by (that is, filter hosts that use a specific MDM provider). |
| mdm_enrollment_status | string | query | The _mobile device management_ (MDM) enrollment status to filter hosts by. Valid options are 'manual', 'automatic', 'enrolled', 'pending', or 'unenrolled'. |
+| connected_to_fleet | boolean | query | Filter hosts that are talking to this Fleet server for MDM features. In rare cases, hosts can be enrolled to one Fleet server but talk to a different Fleet server for MDM features. In this case, the value would be `false`. Always `false` for Linux hosts. |
| macos_settings | string | query | Filters the hosts by the status of the _mobile device management_ (MDM) profiles applied to hosts. Valid options are 'verified', 'verifying', 'pending', or 'failed'. **Note: If this filter is used in Fleet Premium without a team ID filter, the results include only hosts that are not assigned to any team.** |
| munki_issue_id | integer | query | The ID of the _munki issue_ (a Munki-reported error or warning message) to filter hosts by (that is, filter hosts that are affected by that corresponding error or warning message). |
| low_disk_space | integer | query | _Available in Fleet Premium_. Filters the hosts to only include hosts with less GB of disk space available than this value. Must be a number between 1-100. |
@@ -3099,10 +3100,11 @@ Returns the information of the specified host.
"timezone": "America/New_York"
},
"mdm": {
- "encryption_key_available": false,
- "enrollment_status": null,
- "name": "",
- "server_url": null,
+ "encryption_key_available": true,
+ "enrollment_status": "On (manual)",
+ "name": "Fleet",
+ "connected_to_fleet": true,
+ "server_url": "https://acme.com/mdm/apple/mdm",
"device_status": "unlocked",
"pending_action": "",
"macos_settings": {
@@ -3518,10 +3520,11 @@ This is the API route used by the **My device** page in Fleet desktop to display
}
],
"mdm": {
- "encryption_key_available": false,
- "enrollment_status": null,
- "name": "",
- "server_url": null,
+ "encryption_key_available": true,
+ "enrollment_status": "On (manual)",
+ "name": "Fleet",
+ "connected_to_fleet": true,
+ "server_url": "https://acme.com/mdm/apple/mdm",
"macos_settings": {
"disk_encryption": null,
"action_required": null
@@ -3696,7 +3699,7 @@ _Available in Fleet Premium_
| Name | Type | In | Description |
| ------- | ------- | ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| ids | list | body | A list of the host IDs you'd like to delete. If `ids` is specified, `filters` cannot be specified. |
+| ids | array | body | A list of the host IDs you'd like to delete. If `ids` is specified, `filters` cannot be specified. |
| filters | object | body | Contains any of the following four properties: `query` for search query keywords. Searchable fields include `hostname`, `hardware_serial`, `uuid`, and `ipv4`. `status` to indicate the status of the hosts to return. Can either be `new`, `online`, `offline`, `mia` or `missing`. `label_id` to indicate the selected label. `team_id` to indicate the selected team. If `filters` is specified, `id` cannot be specified. `label_id` and `status` cannot be used at the same time. |
Either ids or filters are required.
@@ -4663,9 +4666,9 @@ Adds manual labels to a host.
#### Parameters
-| Name | Type | In | Description |
-| ---- | ------- | ---- | ---------------------------- |
-| labels | list | body | The list of label names to add to the host. |
+| Name | Type | In | Description |
+| ------ | ------- | ---- | ---------------------------- |
+| labels | array | body | The list of label names to add to the host. |
#### Example
@@ -4692,9 +4695,9 @@ Removes manual labels from a host.
#### Parameters
-| Name | Type | In | Description |
-| ---- | ------- | ---- | ---------------------------- |
-| labels | list | body | The list of label names to delete from the host. |
+| Name | Type | In | Description |
+| ------ | ------- | ---- | ---------------------------- |
+| labels | array | body | The list of label names to delete from the host. |
#### Example
@@ -5424,7 +5427,6 @@ List all configuration profiles for macOS and Windows hosts enrolled to Fleet's
{
"name": "Label name 2",
"broken": true,
- "id": 2
},
{
"name": "Label name 3",
@@ -6559,7 +6561,7 @@ For example, a policy might ask “Is Gatekeeper enabled on macOS devices?“ Th
| Name | Type | In | Description |
| -------- | ------- | ---- | ------------------------------------------------- |
-| ids | list | body | **Required.** The IDs of the policies to delete. |
+| ids | array | body | **Required.** The IDs of the policies to delete. |
#### Example
@@ -6653,8 +6655,8 @@ Triggers [automations](https://fleetdm.com/docs/using-fleet/automations#policy-a
| Name | Type | In | Description |
| ---------- | -------- | ---- | -------------------------------------------------------- |
-| policy_ids | list | body | Filters to only run policy automations for the specified policies. |
-| team_ids | list | body | _Available in Fleet Premium_. Filters to only run policy automations for hosts in the specified teams. |
+| policy_ids | array | body | Filters to only run policy automations for the specified policies. |
+| team_ids | array | body | _Available in Fleet Premium_. Filters to only run policy automations for hosts in the specified teams. |
#### Example
@@ -6994,7 +6996,7 @@ Either `query` or `query_id` must be provided.
| Name | Type | In | Description |
| -------- | ------- | ---- | ------------------------------------------------- |
| team_id | integer | path | **Required.** Defines what team ID to operate on |
-| ids | list | body | **Required.** The IDs of the policies to delete. |
+| ids | array | body | **Required.** The IDs of the policies to delete. |
#### Example
@@ -7431,14 +7433,14 @@ Creates a global query or team query.
| name | string | body | **Required**. The name of the query. |
| query | string | body | **Required**. The query in SQL syntax. |
| description | string | body | The query's description. |
-| observer_can_run | bool | body | Whether or not users with the `observer` role can run the query. In Fleet 4.0.0, 3 user roles were introduced (`admin`, `maintainer`, and `observer`). This field is only relevant for the `observer` role. The `observer_plus` role can run any query and is not limited by this flag (`observer_plus` role was added in Fleet 4.30.0). |
+| observer_can_run | boolean | body | Whether or not users with the `observer` role can run the query. In Fleet 4.0.0, 3 user roles were introduced (`admin`, `maintainer`, and `observer`). This field is only relevant for the `observer` role. The `observer_plus` role can run any query and is not limited by this flag (`observer_plus` role was added in Fleet 4.30.0). |
| team_id | integer | body | _Available in Fleet Premium_. The parent team to which the new query should be added. If omitted, the query will be global. |
-| interval | integer | body | The amount of time, in seconds, the query waits before running. Can be set to `0` to never run. Default: 0. |
+| interval | integer | body | The amount of time, in seconds, the query waits before running. Can be set to `0` to never run. Default: 0. |
| platform | string | body | The OS platforms where this query will run (other platforms ignored). Comma-separated string. If omitted, runs on all compatible platforms. |
| min_osquery_version | string | body | The minimum required osqueryd version installed on a host. If omitted, all osqueryd versions are acceptable. |
| automations_enabled | boolean | body | Whether to send data to the configured log destination according to the query's `interval`. |
-| logging | string | body | The type of log output for this query. Valid values: `"snapshot"`(default), `"differential"`, or `"differential_ignore_removals"`. |
-| discard_data | bool | body | Whether to skip saving the latest query results for each host. Default: `false`. |
+| logging | string | body | The type of log output for this query. Valid values: `"snapshot"`(default), `"differential"`, or `"differential_ignore_removals"`. |
+| discard_data | boolean | body | Whether to skip saving the latest query results for each host. Default: `false`. |
#### Example
@@ -7505,13 +7507,13 @@ Modifies the query specified by ID.
| name | string | body | The name of the query. |
| query | string | body | The query in SQL syntax. |
| description | string | body | The query's description. |
-| observer_can_run | bool | body | Whether or not users with the `observer` role can run the query. In Fleet 4.0.0, 3 user roles were introduced (`admin`, `maintainer`, and `observer`). This field is only relevant for the `observer` role. The `observer_plus` role can run any query and is not limited by this flag (`observer_plus` role was added in Fleet 4.30.0). |
+| observer_can_run | boolean | body | Whether or not users with the `observer` role can run the query. In Fleet 4.0.0, 3 user roles were introduced (`admin`, `maintainer`, and `observer`). This field is only relevant for the `observer` role. The `observer_plus` role can run any query and is not limited by this flag (`observer_plus` role was added in Fleet 4.30.0). |
| interval | integer | body | The amount of time, in seconds, the query waits before running. Can be set to `0` to never run. Default: 0. |
| platform | string | body | The OS platforms where this query will run (other platforms ignored). Comma-separated string. If set to "", runs on all compatible platforms. |
| min_osquery_version | string | body | The minimum required osqueryd version installed on a host. If omitted, all osqueryd versions are acceptable. |
| automations_enabled | boolean | body | Whether to send data to the configured log destination according to the query's `interval`. |
| logging | string | body | The type of log output for this query. Valid values: `"snapshot"`(default), `"differential"`, or `"differential_ignore_removals"`. |
-| discard_data | bool | body | Whether to skip saving the latest query results for each host. |
+| discard_data | boolean | body | Whether to skip saving the latest query results for each host. |
> Note that any of the following conditions will cause the existing query report to be deleted:
> - Updating the `query` (SQL) field
@@ -7615,9 +7617,9 @@ Deletes the queries specified by ID. Returns the count of queries successfully d
#### Parameters
-| Name | Type | In | Description |
-| ---- | ---- | ---- | ------------------------------------- |
-| ids | list | body | **Required.** The IDs of the queries. |
+| Name | Type | In | Description |
+| ---- | ----- | ---- | ------------------------------------- |
+| ids | array | body | **Required.** The IDs of the queries. |
#### Example
@@ -8506,9 +8508,9 @@ Get a list of all software.
| order_direction | string | query | **Requires `order_key`**. The direction of the order given the order key. Options include `asc` and `desc`. Default is `asc`. |
| query | string | query | Search query keywords. Searchable fields include `title` and `cve`. |
| team_id | integer | query | _Available in Fleet Premium_. Filters the software to only include the software installed on the hosts that are assigned to the specified team. Use `0` to filter by hosts assigned to "No team". |
-| vulnerable | bool | query | If true or 1, only list software that has detected vulnerabilities. Default is `false`. |
-| available_for_install | bool | query | If `true` or `1`, only list software that is available for install (added by the user). Default is `false`. |
-| self_service | bool | query | If `true` or `1`, only lists self-service software. Default is `false`. |
+| vulnerable | boolean | query | If true or 1, only list software that has detected vulnerabilities. Default is `false`. |
+| available_for_install | boolean | query | If `true` or `1`, only list software that is available for install (added by the user). Default is `false`. |
+| self_service | boolean | query | If `true` or `1`, only lists self-service software. Default is `false`. |
#### Example
@@ -8627,7 +8629,7 @@ Get a list of all software versions.
| order_direction | string | query | **Requires `order_key`**. The direction of the order given the order key. Options include `asc` and `desc`. Default is `asc`. |
| query | string | query | Search query keywords. Searchable fields include `name`, `version`, and `cve`. |
| team_id | integer | query | _Available in Fleet Premium_. Filters the software to only include the software installed on the hosts that are assigned to the specified team. Use `0` to filter by hosts assigned to "No team". |
-| vulnerable | bool | query | If true or 1, only list software that has detected vulnerabilities. Default is `false`. |
+| vulnerable | boolean | query | If true or 1, only list software that has detected vulnerabilities. Default is `false`. |
#### Example
@@ -8990,6 +8992,8 @@ OS vulnerability data is currently available for Windows and macOS. For other pl
### Add package
+> **Experimental feature**. This feature is undergoing rapid improvement, which may result in breaking changes to the API or configuration surface. It is not recommended for use in automated workflows.
+
_Available in Fleet Premium._
Add a package (.pkg, .msi, .exe, .deb) to install on macOS, Windows, or Linux (Ubuntu) hosts.
@@ -9136,6 +9140,8 @@ Add App Store (VPP) app purchased in Apple Business Manager.
### Download package
+> **Experimental feature**. This feature is undergoing rapid improvement, which may result in breaking changes to the API or configuration surface. It is not recommended for use in automated workflows.
+
_Available in Fleet Premium._
`GET /api/v1/fleet/software/titles/:software_title_id/package?alt=media`
@@ -9191,6 +9197,8 @@ Install software (package or App Store app) on a macOS, iOS, iPadOS, Windows, or
### Get package install result
+> **Experimental feature**. This feature is undergoing rapid improvement, which may result in breaking changes to the API or configuration surface. It is not recommended for use in automated workflows.
+
_Available in Fleet Premium._
`GET /api/v1/fleet/software/install/results/:install_uuid`
@@ -9828,8 +9836,8 @@ _Available in Fleet Premium_
| ------------------------------------------------------- | ------- | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| id | integer | path | **Required.** The desired team's ID. |
| name | string | body | The team's name. |
-| host_ids | list | body | A list of hosts that belong to the team. |
-| user_ids | list | body | A list of users on the team. |
+| host_ids | array | body | A list of hosts that belong to the team. |
+| user_ids | array | body | A list of users on the team. |
| webhook_settings | object | body | Webhook settings contains for the team. |
| failing_policies_webhook | object | body | Failing policies webhook settings. |
| enable_failing_policies_webhook | boolean | body | Whether or not the failing policies webhook is enabled. |
@@ -9864,10 +9872,10 @@ _Available in Fleet Premium_
| deadline_days | integer | body | Hosts that belong to this team and are enrolled into Fleet's MDM will have this number of days before updates are installed on Windows. |
| grace_period_days | integer | body | Hosts that belong to this team and are enrolled into Fleet's MDM will have this number of days before Windows restarts to install updates. |
| macos_settings | object | body | macOS-specific settings. |
-| custom_settings | list | body | The list of objects where each object includes .mobileconfig or JSON file (configuration profile) and label name to apply to macOS hosts that belong to this team and are members of the specified label. |
+| custom_settings | array | body | The list of objects where each object includes .mobileconfig or JSON file (configuration profile) and label name to apply to macOS hosts that belong to this team and are members of the specified label. |
| enable_disk_encryption | boolean | body | Hosts that belong to this team and are enrolled into Fleet's MDM will have disk encryption enabled if set to true. |
| windows_settings | object | body | Windows-specific settings. |
-| custom_settings | list | body | The list of objects where each object includes XML file (configuration profile) and label name to apply to Windows hosts that belong to this team and are members of the specified label. |
+| custom_settings | array | body | The list of objects where each object includes XML file (configuration profile) and label name to apply to Windows hosts that belong to this team and are members of the specified label. |
| macos_setup | object | body | Setup for automatic MDM enrollment of macOS hosts. |
| enable_end_user_authentication | boolean | body | If set to true, end user authentication will be required during automatic MDM enrollment of new macOS hosts. Settings for your IdP provider must also be [configured](https://fleetdm.com/docs/using-fleet/mdm-macos-setup-experience#end-user-authentication-and-eula). |
| integrations | object | body | Integration settings for this team. |
@@ -10087,8 +10095,8 @@ _Available in Fleet Premium_
| Name | Type | In | Description |
| --- | --- | --- | --- |
| id | integer | path | **Required.** The desired team's ID. |
-| force | bool | query | Force apply the options even if there are validation errors. |
-| dry_run | bool | query | Validate the options and return any validation errors, but do not apply the changes. |
+| force | boolean | query | Force apply the options even if there are validation errors. |
+| dry_run | boolean | query | Validate the options and return any validation errors, but do not apply the changes. |
| _JSON data_ | object | body | The JSON to use as agent options for this team. See [Agent options](https://fleetdm.com/docs/using-fleet/configuration-files#agent-options) for details. |
#### Example
@@ -10199,9 +10207,9 @@ Transforms a host name into a host id. For example, the Fleet UI use this endpoi
#### Parameters
-| Name | Type | In | Description |
-| ---- | ----- | ---- | ---------------------------------------- |
-| list | array | body | **Required** list of items to translate. |
+| Name | Type | In | Description |
+| ----- | ----- | ---- | ---------------------------------------- |
+| array | array | body | **Required** list of items to translate. |
#### Example
diff --git a/ee/server/service/vpp.go b/ee/server/service/vpp.go
index 52f4c1f890..85c29652ca 100644
--- a/ee/server/service/vpp.go
+++ b/ee/server/service/vpp.go
@@ -5,6 +5,7 @@ import (
"database/sql"
"errors"
"fmt"
+ "io"
"net/http"
"sort"
"strings"
@@ -17,6 +18,9 @@ import (
"github.com/fleetdm/fleet/v4/server/mdm/apple/vpp"
)
+// Used for overriding the env var value in testing
+var testSetEmptyPrivateKey bool
+
// getVPPToken returns the base64 encoded VPP token, ready for use in requests to Apple's VPP API.
// It returns an error if the token is expired.
func (svc *Service) getVPPToken(ctx context.Context, teamID *uint) (string, error) {
@@ -413,3 +417,143 @@ func getVPPAppsMetadata(ctx context.Context, ids []fleet.VPPAppTeam) ([]*fleet.V
return apps, nil
}
+
+func (svc *Service) UploadVPPToken(ctx context.Context, token io.ReadSeeker) (*fleet.VPPTokenDB, error) {
+ if err := svc.authz.Authorize(ctx, &fleet.AppleCSR{}, fleet.ActionWrite); err != nil {
+ return nil, err
+ }
+
+ privateKey := svc.config.Server.PrivateKey
+ if testSetEmptyPrivateKey {
+ privateKey = ""
+ }
+
+ if len(privateKey) == 0 {
+ return nil, ctxerr.New(ctx, "Couldn't upload content token. Missing required private key. Learn how to configure the private key here: https://fleetdm.com/learn-more-about/fleet-server-private-key")
+ }
+
+ if token == nil {
+ return nil, ctxerr.Wrap(ctx, fleet.NewInvalidArgumentError("token", "Invalid token. Please provide a valid content token from Apple Business Manager."))
+ }
+
+ tokenBytes, err := io.ReadAll(token)
+ if err != nil {
+ return nil, ctxerr.Wrap(ctx, err, "reading VPP token")
+ }
+
+ locName, err := vpp.GetConfig(string(tokenBytes))
+ if err != nil {
+ var vppErr *vpp.ErrorResponse
+ if errors.As(err, &vppErr) {
+ // Per https://developer.apple.com/documentation/devicemanagement/app_and_book_management/app_and_book_management_legacy/interpreting_error_codes
+ if vppErr.ErrorNumber == 9622 {
+ return nil, ctxerr.Wrap(ctx, fleet.NewInvalidArgumentError("token", "Invalid token. Please provide a valid content token from Apple Business Manager."))
+ }
+ }
+ return nil, ctxerr.Wrap(ctx, err, "validating VPP token with Apple")
+ }
+
+ data := fleet.VPPTokenData{
+ Token: string(tokenBytes),
+ Location: locName,
+ }
+
+ tok, err := svc.ds.InsertVPPToken(ctx, &data)
+ if err != nil {
+ return nil, ctxerr.Wrap(ctx, err, "writing VPP token to db")
+ }
+
+ if err := svc.NewActivity(ctx, authz.UserFromContext(ctx), fleet.ActivityEnabledVPP{
+ Location: locName,
+ }); err != nil {
+ return nil, ctxerr.Wrap(ctx, err, "create activity for upload VPP token")
+ }
+
+ return tok, nil
+}
+
+func (svc *Service) UpdateVPPToken(ctx context.Context, tokenID uint, token io.ReadSeeker) (*fleet.VPPTokenDB, error) {
+ if err := svc.authz.Authorize(ctx, &fleet.AppleCSR{}, fleet.ActionWrite); err != nil {
+ return nil, err
+ }
+
+ privateKey := svc.config.Server.PrivateKey
+ if testSetEmptyPrivateKey {
+ privateKey = ""
+ }
+
+ if len(privateKey) == 0 {
+ return nil, ctxerr.New(ctx, "Couldn't upload content token. Missing required private key. Learn how to configure the private key here: https://fleetdm.com/learn-more-about/fleet-server-private-key")
+ }
+
+ if token == nil {
+ return nil, ctxerr.Wrap(ctx, fleet.NewInvalidArgumentError("token", "Invalid token. Please provide a valid content token from Apple Business Manager."))
+ }
+
+ tokenBytes, err := io.ReadAll(token)
+ if err != nil {
+ return nil, ctxerr.Wrap(ctx, err, "reading VPP token")
+ }
+
+ locName, err := vpp.GetConfig(string(tokenBytes))
+ if err != nil {
+ var vppErr *vpp.ErrorResponse
+ if errors.As(err, &vppErr) {
+ // Per https://developer.apple.com/documentation/devicemanagement/app_and_book_management/app_and_book_management_legacy/interpreting_error_codes
+ if vppErr.ErrorNumber == 9622 {
+ return nil, ctxerr.Wrap(ctx, fleet.NewInvalidArgumentError("token", "Invalid token. Please provide a valid content token from Apple Business Manager."))
+ }
+ }
+ return nil, ctxerr.Wrap(ctx, err, "validating VPP token with Apple")
+ }
+
+ data := fleet.VPPTokenData{
+ Token: string(tokenBytes),
+ Location: locName,
+ }
+
+ tok, err := svc.ds.UpdateVPPToken(ctx, tokenID, &data)
+ if err != nil {
+ return nil, ctxerr.Wrap(ctx, err, "updating vpp token")
+ }
+
+ return tok, nil
+}
+
+func (svc *Service) UpdateVPPTokenTeams(ctx context.Context, tokenID uint, teamIDs []uint) (*fleet.VPPTokenDB, error) {
+ if err := svc.authz.Authorize(ctx, &fleet.AppleCSR{}, fleet.ActionWrite); err != nil {
+ return nil, err
+ }
+
+ tok, err := svc.ds.UpdateVPPTokenTeams(ctx, tokenID, teamIDs)
+ if err != nil {
+ return nil, ctxerr.Wrap(ctx, err, "updating vpp token team")
+ }
+
+ return tok, nil
+}
+
+func (svc *Service) GetVPPTokens(ctx context.Context) ([]*fleet.VPPTokenDB, error) {
+ if err := svc.authz.Authorize(ctx, &fleet.AppleCSR{}, fleet.ActionRead); err != nil {
+ return nil, err
+ }
+
+ return svc.ds.ListVPPTokens(ctx)
+}
+
+func (svc *Service) DeleteVPPToken(ctx context.Context, tokenID uint) error {
+ if err := svc.authz.Authorize(ctx, &fleet.AppleCSR{}, fleet.ActionWrite); err != nil {
+ return err
+ }
+ tok, err := svc.ds.GetVPPToken(ctx, tokenID)
+ if err != nil {
+ return ctxerr.Wrap(ctx, err, "getting vpp token")
+ }
+ if err := svc.NewActivity(ctx, authz.UserFromContext(ctx), fleet.ActivityDisabledVPP{
+ Location: tok.Location,
+ }); err != nil {
+ return ctxerr.Wrap(ctx, err, "create activity for delete VPP token")
+ }
+
+ return svc.ds.DeleteVPPToken(ctx, tokenID)
+}
diff --git a/frontend/__mocks__/policyMock.ts b/frontend/__mocks__/policyMock.ts
index b14095463e..ba60c55c74 100644
--- a/frontend/__mocks__/policyMock.ts
+++ b/frontend/__mocks__/policyMock.ts
@@ -23,6 +23,10 @@ const DEFAULT_POLICY_MOCK: IPolicyStats = {
has_run: true,
next_update_ms: 3600000,
calendar_events_enabled: true,
+ install_software: {
+ name: "testSw0",
+ software_title_id: 1,
+ },
};
const createMockPolicy = (overrides?: Partial): IPolicyStats => {
diff --git a/frontend/components/Editor/Editor.tsx b/frontend/components/Editor/Editor.tsx
index e8f230e379..b724a296c3 100644
--- a/frontend/components/Editor/Editor.tsx
+++ b/frontend/components/Editor/Editor.tsx
@@ -29,6 +29,10 @@ interface IEditorProps {
* @default "editor"
*/
name?: string;
+ /** Include correct styles as a form field.
+ * @default false
+ */
+ isFormField?: boolean;
maxLines?: number;
className?: string;
onChange?: (value: string, event?: any) => void;
@@ -52,11 +56,13 @@ const Editor = ({
readOnly = false,
wrapEnabled = false,
name = "editor",
+ isFormField = false,
maxLines = 20,
className,
onChange,
}: IEditorProps) => {
const classNames = classnames(baseClass, className, {
+ "form-field": isFormField,
[`${baseClass}__error`]: !!error,
});
diff --git a/frontend/components/Editor/_styles.scss b/frontend/components/Editor/_styles.scss
index 676172697d..22fbacfd33 100644
--- a/frontend/components/Editor/_styles.scss
+++ b/frontend/components/Editor/_styles.scss
@@ -3,7 +3,6 @@
&__label {
font-size: $x-small;
font-weight: $bold;
- margin-bottom: $pad-small;
&--error {
color: $core-vibrant-red;
diff --git a/frontend/components/FleetAce/FleetAce.tsx b/frontend/components/FleetAce/FleetAce.tsx
index c30232cb59..b0422d4cde 100644
--- a/frontend/components/FleetAce/FleetAce.tsx
+++ b/frontend/components/FleetAce/FleetAce.tsx
@@ -29,6 +29,7 @@ export interface IFleetAceProps {
label?: string;
name?: string;
value?: string;
+ placeholder?: string;
readOnly?: boolean;
maxLines?: number;
showGutter?: boolean;
@@ -55,6 +56,7 @@ const FleetAce = ({
labelActionComponent,
name = "query-editor",
value,
+ placeholder,
readOnly,
maxLines = 20,
showGutter = true,
@@ -266,6 +268,7 @@ const FleetAce = ({
showPrintMargin={false}
theme="fleet"
value={value}
+ placeholder={placeholder}
width="100%"
wrapEnabled={wrapEnabled}
style={style}
diff --git a/frontend/components/FleetAce/_styles.scss b/frontend/components/FleetAce/_styles.scss
index c12237a3a7..f9f0dccf89 100644
--- a/frontend/components/FleetAce/_styles.scss
+++ b/frontend/components/FleetAce/_styles.scss
@@ -25,6 +25,16 @@
}
}
+ .ace_content {
+ padding-left: 4px;
+ }
+
+ .ace_placeholder {
+ font-family: "SourceCodePro", $monospace;
+ margin: initial;
+ font-size: 15px;
+ }
+
&__help-text {
@include help-text;
diff --git a/frontend/components/forms/fields/Dropdown/Dropdown.jsx b/frontend/components/forms/fields/Dropdown/Dropdown.jsx
index 1edde66fec..302233e5d6 100644
--- a/frontend/components/forms/fields/Dropdown/Dropdown.jsx
+++ b/frontend/components/forms/fields/Dropdown/Dropdown.jsx
@@ -27,6 +27,19 @@ class Dropdown extends Component {
onClose: PropTypes.func,
options: PropTypes.arrayOf(dropdownOptionInterface).isRequired,
placeholder: PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
+ /**
+ value must correspond to the value of a dropdown option to render
+ e.g. with options:
+
+ [
+ {
+ label: "Display name",
+ value: 1, <– the id of the thing
+ }
+ ]
+
+ set value to 1, not "Display name"
+ */
value: PropTypes.oneOfType([
PropTypes.array,
PropTypes.string,
@@ -75,7 +88,7 @@ class Dropdown extends Component {
const { multi, onChange, clearable, name, parseTarget } = this.props;
if (parseTarget) {
- // Returns both name and value
+ // Returns both name of the Dropdown and value of the selected option
return onChange({ value: selected.value, name });
}
diff --git a/frontend/interfaces/policy.ts b/frontend/interfaces/policy.ts
index 41586ea22d..621c52f638 100644
--- a/frontend/interfaces/policy.ts
+++ b/frontend/interfaces/policy.ts
@@ -41,6 +41,12 @@ export interface IPolicy {
updated_at: string;
critical: boolean;
calendar_events_enabled: boolean;
+ install_software?: IPolicySoftwareToInstall;
+}
+
+export interface IPolicySoftwareToInstall {
+ name: string;
+ software_title_id: number;
}
// Used on the manage hosts page and other places where aggregate stats are displayed
@@ -94,6 +100,8 @@ export interface IPolicyFormData {
team_id?: number | null;
id?: number;
calendar_events_enabled?: boolean;
+ // undefined from GET/LIST when not set, null for PATCH to unset
+ software_title_id?: number | null;
}
export interface IPolicyNew {
diff --git a/frontend/interfaces/software.ts b/frontend/interfaces/software.ts
index bf6ba786a1..9d6d3617b2 100644
--- a/frontend/interfaces/software.ts
+++ b/frontend/interfaces/software.ts
@@ -109,6 +109,7 @@ export interface ISoftwareTitleDetails {
source: string; // "apps" | "ios_apps" | "ipados_apps" | ?
hosts_count: number;
versions: ISoftwareTitleVersion[] | null;
+ versions_updated_at?: string;
bundle_identifier?: string;
browser?: string;
versions_count?: number;
diff --git a/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileUploader/components/AddProfileModal/AddProfileModal.tsx b/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileUploader/components/AddProfileModal/AddProfileModal.tsx
index 12191a9641..694970c4ca 100644
--- a/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileUploader/components/AddProfileModal/AddProfileModal.tsx
+++ b/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileUploader/components/AddProfileModal/AddProfileModal.tsx
@@ -77,7 +77,7 @@ interface IFileDetailsProps {
// TODO: if we reuse this one more time, we should consider moving this
// into FileUploader as a default preview. Currently we have this in
-// AddSoftwareForm.tsx and here.
+// AddPackageForm.tsx and here.
const FileDetails = ({ details: { name, platform } }: IFileDetailsProps) => (
diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/AdvancedOptionsModal/AdvancedOptionsModal.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/AdvancedOptionsModal/AdvancedOptionsModal.tsx
index b3f7c31146..5cfc313e44 100644
--- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/AdvancedOptionsModal/AdvancedOptionsModal.tsx
+++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/AdvancedOptionsModal/AdvancedOptionsModal.tsx
@@ -38,6 +38,7 @@ const AdvancedOptionsModal = ({
helpText="Fleet will run this command on hosts to install software."
label="Install script"
labelTooltip="For security agents, add the script provided by the vendor."
+ isFormField
/>
{preInstallQuery && (
@@ -72,6 +73,7 @@ const AdvancedOptionsModal = ({
maxLines={10}
value={postInstallScript}
helpText="Shell (macOS and Linux) or PowerShell (Windows)."
+ isFormField
/>
)}
diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/DeleteSoftwareModal/DeleteSoftwareModal.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/DeleteSoftwareModal/DeleteSoftwareModal.tsx
index 23d03c5852..fa75f1d554 100644
--- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/DeleteSoftwareModal/DeleteSoftwareModal.tsx
+++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/DeleteSoftwareModal/DeleteSoftwareModal.tsx
@@ -3,11 +3,15 @@ import React, { useCallback, useContext } from "react";
import softwareAPI from "services/entities/software";
import { NotificationContext } from "context/notification";
+import { getErrorReason } from "interfaces/errors";
+
import Modal from "components/Modal";
import Button from "components/buttons/Button";
const baseClass = "delete-software-modal";
+const DELETE_SW_USED_BY_POLICY_ERROR_MSG =
+ "Couldn't delete. Policy automation uses this software. Please disable policy automation for this software and try again.";
interface IDeleteSoftwareModalProps {
softwareId: number;
teamId: number;
@@ -28,8 +32,13 @@ const DeleteSoftwareModal = ({
await softwareAPI.deleteSoftwarePackage(softwareId, teamId);
renderFlash("success", "Software deleted successfully!");
onSuccess();
- } catch {
- renderFlash("error", "Couldn't delete. Please try again.");
+ } catch (error) {
+ const reason = getErrorReason(error);
+ if (reason.includes("Policy automation uses this software")) {
+ renderFlash("error", DELETE_SW_USED_BY_POLICY_ERROR_MSG);
+ } else {
+ renderFlash("error", "Couldn't delete. Please try again.");
+ }
}
onExit();
}, [softwareId, teamId, renderFlash, onSuccess, onExit]);
diff --git a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwarePackageCard/SoftwarePackageCard.tsx b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwarePackageCard/SoftwarePackageCard.tsx
index 8453abfbb6..1c6a31e9d7 100644
--- a/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwarePackageCard/SoftwarePackageCard.tsx
+++ b/frontend/pages/SoftwarePage/SoftwareTitleDetailsPage/SoftwarePackageCard/SoftwarePackageCard.tsx
@@ -4,8 +4,6 @@ import React, {
useLayoutEffect,
useState,
} from "react";
-import FileSaver from "file-saver";
-import { parse } from "content-disposition";
import PATHS from "router/paths";
import { AppContext } from "context/app";
@@ -45,10 +43,15 @@ function useTruncatedElement(ref: React.RefObject) {
useLayoutEffect(() => {
const element = ref.current;
- if (element) {
- const { scrollWidth, clientWidth } = element;
- setIsTruncated(scrollWidth > clientWidth);
+ function updateIsTruncated() {
+ if (element) {
+ const { scrollWidth, clientWidth } = element;
+ setIsTruncated(scrollWidth > clientWidth);
+ }
}
+ window.addEventListener("resize", updateIsTruncated);
+ updateIsTruncated();
+ return () => window.removeEventListener("resize", updateIsTruncated);
}, [ref]);
return isTruncated;
@@ -92,20 +95,29 @@ const STATUS_DISPLAY_OPTIONS: Record<
iconName: "success",
tooltip: (
<>
- Fleet installed software on these hosts. Currently, if the software is
- uninstalled, the "Installed" status won't be updated.
+ Software is installed on these hosts (install script finished
+
+ with exit code 0). Currently, if the software is uninstalled, the
+
+ "installed" status won't be updated.
>
),
},
pending: {
displayName: "Pending",
iconName: "pending-outline",
- tooltip: "Fleet will install software when these hosts come online.",
+ tooltip: "Fleet is installing or will install when the host comes online.",
},
failed: {
displayName: "Failed",
iconName: "error",
- tooltip: "Fleet failed to install software on these hosts.",
+ tooltip: (
+ <>
+ These hosts failed to install software. Click on a host to view
+
+ error(s).
+ >
+ ),
},
};
@@ -130,16 +142,18 @@ const PackageStatusCount = ({
})}`;
return (
+
+ Software will be installed only if the{" "}
+
+ >
+ }
+ />
+
+ Fleet will run this script on hosts to install software. Use the
+
+ $INSTALLER_PATH variable to point to the installer.
+ >
+ }
+ isFormField
+ />
+
+
+ )}
+
+ );
+};
+
+export default AddPackageAdvancedOptions;
diff --git a/frontend/pages/SoftwarePage/components/AddSoftwareAdvancedOptions/_styles.scss b/frontend/pages/SoftwarePage/components/AddPackageAdvancedOptions/_styles.scss
similarity index 88%
rename from frontend/pages/SoftwarePage/components/AddSoftwareAdvancedOptions/_styles.scss
rename to frontend/pages/SoftwarePage/components/AddPackageAdvancedOptions/_styles.scss
index 58f1f85892..0728e32415 100644
--- a/frontend/pages/SoftwarePage/components/AddSoftwareAdvancedOptions/_styles.scss
+++ b/frontend/pages/SoftwarePage/components/AddPackageAdvancedOptions/_styles.scss
@@ -1,4 +1,4 @@
-.add-software-advanced-options {
+.add-package-advanced-options {
display: flex;
flex-direction: column;
align-items: flex-start;
diff --git a/frontend/pages/SoftwarePage/components/AddPackageAdvancedOptions/index.ts b/frontend/pages/SoftwarePage/components/AddPackageAdvancedOptions/index.ts
new file mode 100644
index 0000000000..004c96332d
--- /dev/null
+++ b/frontend/pages/SoftwarePage/components/AddPackageAdvancedOptions/index.ts
@@ -0,0 +1 @@
+export { default } from "./AddPackageAdvancedOptions";
diff --git a/frontend/pages/SoftwarePage/components/AddPackageForm/AddSoftwareForm.tsx b/frontend/pages/SoftwarePage/components/AddPackageForm/AddPackageForm.tsx
similarity index 55%
rename from frontend/pages/SoftwarePage/components/AddPackageForm/AddSoftwareForm.tsx
rename to frontend/pages/SoftwarePage/components/AddPackageForm/AddPackageForm.tsx
index aab97985d0..cf3802b3f6 100644
--- a/frontend/pages/SoftwarePage/components/AddPackageForm/AddSoftwareForm.tsx
+++ b/frontend/pages/SoftwarePage/components/AddPackageForm/AddPackageForm.tsx
@@ -6,7 +6,6 @@ import getInstallScript from "utilities/software_install_scripts";
import Button from "components/buttons/Button";
import Checkbox from "components/forms/fields/Checkbox";
-import Editor from "components/Editor";
import {
FileUploader,
FileDetails,
@@ -14,25 +13,25 @@ import {
import Spinner from "components/Spinner";
import TooltipWrapper from "components/TooltipWrapper";
-import AddSoftwareAdvancedOptions from "../AddSoftwareAdvancedOptions";
+import AddPackageAdvancedOptions from "../AddPackageAdvancedOptions";
import { generateFormValidation } from "./helpers";
-export const baseClass = "add-software-form";
+export const baseClass = "add-package-form";
const UploadingSoftware = () => {
return (
-
Uploading. It may take a few minutes to finish.
+
Adding software. This may take a few minutes to finish.
diff --git a/frontend/pages/SoftwarePage/components/AppStoreVpp/_styles.scss b/frontend/pages/SoftwarePage/components/AppStoreVpp/_styles.scss
index e530588b7a..604750a258 100644
--- a/frontend/pages/SoftwarePage/components/AppStoreVpp/_styles.scss
+++ b/frontend/pages/SoftwarePage/components/AppStoreVpp/_styles.scss
@@ -53,6 +53,7 @@
&__no-software-description {
margin: 0;
color: $ui-fleet-black-75;
+ text-align: center;
}
&__error {
diff --git a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/MdmSettings.tsx b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/MdmSettings.tsx
index ff3cf5b539..b6e0f02795 100644
--- a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/MdmSettings.tsx
+++ b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/MdmSettings.tsx
@@ -27,6 +27,8 @@ interface IMdmSettingsProps {
const MdmSettings = ({ router }: IMdmSettingsProps) => {
const { isPremiumTier, config } = useContext(AppContext);
+ const isMdmEnabled = !!config?.mdm.enabled_and_configured;
+
// Currently the status of this API call is what determines various UI states on
// this page. Because of this we will not render any of this components UI until this API
// call has completed.
@@ -48,7 +50,7 @@ const MdmSettings = ({ router }: IMdmSettingsProps) => {
// we're fetching and setting the config, but for now we'll just assume that any 400 response
// means that MDM is not enabled and we'll show the "Turn on MDM" button.
staleTime: 5000,
- enabled: !!config?.mdm.enabled_and_configured,
+ enabled: isMdmEnabled,
}
);
@@ -63,7 +65,7 @@ const MdmSettings = ({ router }: IMdmSettingsProps) => {
{
...DEFAULT_USE_QUERY_OPTIONS,
retry: false,
- enabled: isPremiumTier && !!config?.mdm.enabled_and_configured,
+ enabled: isPremiumTier && isMdmEnabled,
}
);
@@ -80,7 +82,7 @@ const MdmSettings = ({ router }: IMdmSettingsProps) => {
{
...DEFAULT_USE_QUERY_OPTIONS,
retry: false,
- enabled: isPremiumTier && !!config?.mdm.enabled_and_configured,
+ enabled: isPremiumTier && isMdmEnabled,
}
);
@@ -104,7 +106,7 @@ const MdmSettings = ({ router }: IMdmSettingsProps) => {
// we use this to determine if we have all the data we need to render the UI.
// Notice that we do not need VPP or EULA data to render this page.
- const hasAllData = !!APNSInfo;
+ const hasAllData = !isMdmEnabled || !!APNSInfo;
return (
diff --git a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/AddVppModal/helpers.tsx b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/AddVppModal/helpers.tsx
index 77dc842782..7716c6de6c 100644
--- a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/AddVppModal/helpers.tsx
+++ b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/AddVppModal/helpers.tsx
@@ -20,7 +20,7 @@ export const getErrorMessage = (err: unknown) => {
reasonIncludes: "Duplicate entry",
});
const invalidTokenReason = getErrorReason(err, {
- reasonIncludes: "invalid",
+ reasonIncludes: "Invalid token",
});
if (duplicateEntryReason) {
@@ -28,7 +28,7 @@ export const getErrorMessage = (err: unknown) => {
}
if (invalidTokenReason) {
- return "Invalid token. Please provide a valid token from Apple Business Manager.";
+ return invalidTokenReason;
}
return DEFAULT_ERROR_MESSAGE;
diff --git a/frontend/pages/hosts/details/cards/Software/InstallStatusCell/InstallStatusCell.tsx b/frontend/pages/hosts/details/cards/Software/InstallStatusCell/InstallStatusCell.tsx
index b99503903d..ef5ac1b737 100644
--- a/frontend/pages/hosts/details/cards/Software/InstallStatusCell/InstallStatusCell.tsx
+++ b/frontend/pages/hosts/details/cards/Software/InstallStatusCell/InstallStatusCell.tsx
@@ -4,7 +4,6 @@ import ReactTooltip from "react-tooltip";
import { uniqueId } from "lodash";
import { IHostSoftware, SoftwareInstallStatus } from "interfaces/software";
-import { dateAgo } from "utilities/date_format";
import Icon from "components/Icon";
import TextCell from "components/TableContainer/DataTable/TextCell";
@@ -14,6 +13,7 @@ const baseClass = "install-status-cell";
type IStatusValue = SoftwareInstallStatus | "avaiableForInstall";
interface TootipArgs {
softwareName?: string | null;
+ // this field is used in My device > Self-service
lastInstalledAt?: string;
isAppStoreApp?: boolean;
}
@@ -36,26 +36,23 @@ export const INSTALL_STATUS_DISPLAY_OPTIONS: Record<
installed: {
iconName: "success",
displayText: "Installed",
- tooltip: ({ lastInstalledAt: lastInstall }) => (
- <>
- Fleet installed software on this host ({dateAgo(lastInstall as string)}
- ). Currently, if the software is uninstalled, the "Installed"
- status won't be updated.
- >
- ),
+ tooltip: () =>
+ "Software is installed (install script finished with exit code 0).",
},
pending: {
iconName: "pending-outline",
displayText: "Pending",
- tooltip: () => "Fleet will install software when the host comes online.",
+ tooltip: () =>
+ "Fleet is installing or will install when the host comes online.",
},
failed: {
iconName: "error",
displayText: "Failed",
- tooltip: ({ lastInstalledAt: lastInstall }) => (
+ tooltip: () => (
<>
- Fleet failed to install software ({dateAgo(lastInstall as string)} ago).
- Select Actions > Software details to see more.
+ The host failed to install software. To view errors, select
+
+ Actions > Show details.
>
),
},
@@ -96,10 +93,6 @@ const InstallStatusCell = ({
app_store_app,
}: IInstallStatusCellProps) => {
// FIXME: Improve the way we handle polymophism of software_package and app_store_app
- const lastInstalledAt =
- software_package?.last_install?.installed_at ||
- app_store_app?.last_install?.installed_at ||
- "";
const hasPackage = !!software_package;
const hasAppStoreApp = !!app_store_app;
@@ -140,7 +133,6 @@ const InstallStatusCell = ({
{displayConfig.tooltip({
softwareName,
- lastInstalledAt,
isAppStoreApp: hasAppStoreApp,
})}
diff --git a/frontend/pages/hosts/details/cards/Software/SelfService/SelfService.tests.tsx b/frontend/pages/hosts/details/cards/Software/SelfService/SelfService.tests.tsx
index 2c995aa2b2..a7ca5e5cdd 100644
--- a/frontend/pages/hosts/details/cards/Software/SelfService/SelfService.tests.tsx
+++ b/frontend/pages/hosts/details/cards/Software/SelfService/SelfService.tests.tsx
@@ -166,7 +166,7 @@ describe("SelfService", () => {
).toHaveTextContent("Install");
});
- it("renders no action button with 'Install in progress...' status", async () => {
+ it("renders no action button with 'Pending' status", async () => {
mockServer.use(
customDeviceSoftwareHandler({
software: [
@@ -186,7 +186,7 @@ describe("SelfService", () => {
expect(
screen.getByTestId("self-service-item__status--test")
- ).toHaveTextContent("Install in progress...");
+ ).toHaveTextContent("Pending");
expect(
screen.queryByTestId("self-service-item__item-action-button--test")
diff --git a/frontend/pages/hosts/details/cards/Software/SelfService/SelfServiceItem/SelfServiceItem.tsx b/frontend/pages/hosts/details/cards/Software/SelfService/SelfServiceItem/SelfServiceItem.tsx
index d0fce6aca3..3d817c9d16 100644
--- a/frontend/pages/hosts/details/cards/Software/SelfService/SelfServiceItem/SelfServiceItem.tsx
+++ b/frontend/pages/hosts/details/cards/Software/SelfService/SelfServiceItem/SelfServiceItem.tsx
@@ -25,25 +25,20 @@ const STATUS_CONFIG: Record = {
installed: {
iconName: "success",
displayText: "Installed",
- tooltip: ({ lastInstalledAt }) => (
- <>
- Software installed successfully ({dateAgo(lastInstalledAt as string)}).
- Currently, if the software is uninstalled, the "Installed"
- status won't be updated.
- >
- ),
+ tooltip: ({ lastInstalledAt }) =>
+ `Software is installed (${dateAgo(lastInstalledAt as string)}).`,
},
pending: {
iconName: "pending-outline",
- displayText: "Install in progress...",
- tooltip: () => "Software installation in progress...",
+ displayText: "Pending",
+ tooltip: () => "Fleet is installing software.",
},
failed: {
iconName: "error",
displayText: "Failed",
tooltip: ({ lastInstalledAt = "" }) => (
<>
- Software failed to install
+ Software failed to install{" "}
{lastInstalledAt ? ` (${dateAgo(lastInstalledAt)})` : ""}. Select{" "}
Retry to install again, or contact your IT department.
>
@@ -144,7 +139,6 @@ const getInstallButtonText = (status: SoftwareInstallStatus | null) => {
case "installed":
return "Reinstall";
default:
- // we don't show a button for pending installs
return "";
}
};
@@ -165,10 +159,7 @@ const InstallerStatusAction = ({
SoftwareInstallStatus | undefined
>(undefined);
- // displayStatus allows us to display the localStatus (if any) or the status from the list
- // software reponse
- const displayStatus = localStatus || status;
- const installButtonText = getInstallButtonText(displayStatus);
+ const installButtonText = getInstallButtonText(status);
// if the localStatus is "failed", we don't want our tooltip to include the old installed_at date so we
// set this to null, which tells the tooltip to omit the parenthetical date
@@ -200,21 +191,16 @@ const InstallerStatusAction = ({
return (