Merge branch 'main' into jj-fix-typo

This commit is contained in:
Ashish Kuthiala 2026-04-20 23:47:34 -05:00 committed by GitHub
commit cc7a14b424
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
247 changed files with 6074 additions and 2245 deletions

View file

@ -13,7 +13,7 @@ on:
default: "main"
required: true
loadtest_containers:
description: "Deploys osquery-perf containers all at once. Total number of osquery-perf tasks to run (should be a multiple of 8, if setting loadtest_containers_starting_index). This is also used as the end index in enroll.sh"
description: "Deploys osquery-perf containers all at once. Total number of osquery-perf tasks to run. This is also used as the end index in enroll.sh"
type: string
required: true
loadtest_containers_starting_index:
@ -22,7 +22,7 @@ on:
default: 0
required: true
task_size:
description: "CPU and Memory setting for osquery-perf containers. Example: {\"cpu\":\"4098\",\"memory\":\"8192\"}"
description: "CPU and Memory setting for osquery-perf containers. Example: {\"cpu\":\"4096\",\"memory\":\"8192\"}"
type: string
default: "{\"cpu\":\"4096\",\"memory\":\"8192\"}"
required: true

View file

@ -1,3 +1,9 @@
## Fleet 4.83.2 (Apr 13, 2026)
### Bug fixes
- Fixed a crash on the "My device" page for Fleet Free instances. The page returned a 402 error when the host was assigned to a team because the device endpoint called a premium-only API, and also crashed when accessing undefined policies data.```
## Fleet 4.83.1 (Apr 10, 2026)
### Bug fixes

View file

@ -1,4 +1,4 @@
FROM --platform=linux/amd64 golang:1.26.1-trixie@sha256:96b28783b99bcd265fbfe0b36a3ac6462416ce6bf1feac85d4c4ff533cbaa473
FROM --platform=linux/amd64 golang:1.26.2-trixie@sha256:b53c282df83967299380adbd6a2dc67e750a58217f39285d6240f6f80b19eaad
LABEL maintainer="Fleet Developers"
RUN apt-get update && apt-get install -y musl-tools && rm -rf /var/lib/apt/lists/*

View file

@ -680,12 +680,62 @@ restore: $(SNAPSHOT_BINARY)
# Generate osqueryd.app.tar.gz bundle from osquery.io.
#
# Usage:
# To generate an osquery bundle for a released version of osquery:
# make osqueryd-app-tar-gz version=5.1.0 out-path=.
#
# To generate an osquery bundle for a unreleased change in osquery in a pull request
# (e.g. https://github.com/osquery/osquery/pull/8815):
# make osqueryd-app-tar-gz pr=8815 out-path=.
osqueryd-app-tar-gz:
ifneq ($(shell uname), Darwin)
@echo "Makefile target osqueryd-app-tar-gz is only supported on macOS"
@exit 1
endif
ifdef pr
$(eval TMP_DIR := $(shell mktemp -d))
@echo "Fetching macos_unsigned_tgz_universal artifact from osquery/osquery PR $(pr)..."
@PR_SHA=$$(gh pr view -R osquery/osquery $(pr) --json headRefOid -q .headRefOid) && \
echo "PR head SHA: $$PR_SHA" && \
RUN_IDS=$$(gh api "repos/osquery/osquery/actions/runs?head_sha=$$PR_SHA" \
-q '[.workflow_runs[] | select(.conclusion == "success") | .id] | .[]') && \
if [ -z "$$RUN_IDS" ]; then \
echo "Error: no successful workflow runs found for PR $(pr)"; \
rm -rf $(TMP_DIR); \
exit 1; \
fi && \
DOWNLOADED=false && \
for run_id in $$RUN_IDS; do \
if gh run download -R osquery/osquery $$run_id -n macos_unsigned_tgz_universal -D $(TMP_DIR)/artifact 2>/dev/null; then \
DOWNLOADED=true; \
echo "Downloaded artifact from run $$run_id"; \
break; \
fi; \
done && \
if [ "$$DOWNLOADED" != "true" ]; then \
echo "Error: macos_unsigned_tgz_universal artifact not found in any successful run for PR $(pr)"; \
rm -rf $(TMP_DIR); \
exit 1; \
fi
@INNER_TGZ=$$(find $(TMP_DIR)/artifact -name '*.tar.gz' -o -name '*.tgz' | head -1) && \
if [ -z "$$INNER_TGZ" ]; then \
echo "Error: no tarball found inside downloaded artifact"; \
rm -rf $(TMP_DIR); \
exit 1; \
fi && \
mkdir -p $(TMP_DIR)/extracted && \
tar xf "$$INNER_TGZ" -C $(TMP_DIR)/extracted
@OSQUERY_APP=$$(find $(TMP_DIR)/extracted -type d -name 'osquery.app' | head -1) && \
if [ -z "$$OSQUERY_APP" ]; then \
echo "Error: osquery.app not found in extracted artifact. Contents:"; \
find $(TMP_DIR)/extracted -type f; \
rm -rf $(TMP_DIR); \
exit 1; \
fi && \
OSQUERY_APP_DIR=$$(dirname "$$OSQUERY_APP") && \
"$$OSQUERY_APP/Contents/MacOS/osqueryd" --version && \
tar czf $(out-path)/osqueryd.app.tar.gz -C "$$OSQUERY_APP_DIR" osquery.app
rm -rf $(TMP_DIR)
else
$(eval TMP_DIR := $(shell mktemp -d))
curl -L https://github.com/osquery/osquery/releases/download/$(version)/osquery-$(version).pkg --output $(TMP_DIR)/osquery-$(version).pkg
pkgutil --expand $(TMP_DIR)/osquery-$(version).pkg $(TMP_DIR)/osquery_pkg_expanded
@ -695,6 +745,7 @@ endif
$(TMP_DIR)/osquery_pkg_payload_expanded/opt/osquery/lib/osquery.app/Contents/MacOS/osqueryd --version
tar czf $(out-path)/osqueryd.app.tar.gz -C $(TMP_DIR)/osquery_pkg_payload_expanded/opt/osquery/lib osquery.app
rm -r $(TMP_DIR)
endif
# Generate nudge.app.tar.gz bundle from nudge repo.
#
@ -889,7 +940,17 @@ vex-report:
# make update-go version=1.24.4
UPDATE_GO_DOCKERFILES := ./Dockerfile-desktop-linux ./infrastructure/loadtesting/terraform/docker/loadtest.Dockerfile ./tools/mdm/migration/mdmproxy/Dockerfile
UPDATE_GO_MODS := go.mod ./tools/mdm/windows/bitlocker/go.mod ./tools/snapshot/go.mod ./tools/terraform/go.mod
UPDATE_GO_MODS := \
go.mod \
./tools/mdm/windows/bitlocker/go.mod \
./tools/snapshot/go.mod \
./tools/terraform/go.mod \
./third_party/vuln-check/go.mod \
./tools/ci/setboolcheck/go.mod \
./tools/github-manage/go.mod \
./tools/qacheck/go.mod \
./third_party/goval-dictionary/go.mod \
./tools/fleet-mcp/go.mod
update-go:
@test $(version) || (echo "Mising 'version' argument, usage: 'make update-go version=1.24.4'" ; exit 1)
@for dockerfile in $(UPDATE_GO_DOCKERFILES) ; do \

View file

@ -22,6 +22,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@ -438,6 +439,9 @@ object ApiClient : CertificateApiClient {
)
}
// @EncodeDefault is marked @ExperimentalSerializationApi, but it has shipped in kotlinx.serialization since 1.3 (2022)
// and is widely used and reliable in production. The opt-in only acknowledges that the API shape could change in a future version.
@OptIn(kotlinx.serialization.ExperimentalSerializationApi::class)
@Serializable
data class EnrollRequest(
@SerialName("enroll_secret")
@ -446,6 +450,7 @@ data class EnrollRequest(
val hardwareUUID: String,
@SerialName("hardware_serial")
val hardwareSerial: String,
@EncodeDefault(EncodeDefault.Mode.ALWAYS)
@SerialName("platform")
val platform: String = "android",
@SerialName("computer_name")

View file

@ -100,10 +100,15 @@ class ApiClientReenrollTest {
assertTrue("First call should succeed", firstResult.isSuccess)
assertEquals(2, mockWebServer.requestCount) // enroll + config
// Verify first enrollment used the enroll secret
// Verify first enrollment used the enroll secret and sent platform="android" on the wire
val firstEnroll = mockWebServer.takeRequest()
assertEquals("/api/fleet/orbit/enroll", firstEnroll.path)
assertTrue(firstEnroll.body.readUtf8().contains("test-enroll-secret"))
val firstEnrollBody = firstEnroll.body.readUtf8()
assertTrue(firstEnrollBody.contains("test-enroll-secret"))
assertTrue(
"Expected platform=\"android\" in enroll body, got: $firstEnrollBody",
firstEnrollBody.contains("\"platform\":\"android\""),
)
// Verify first config used first-node-key
val firstConfig = mockWebServer.takeRequest()

View file

@ -0,0 +1 @@
- Fixed Android agent to always send the `platform` field on enrollment so the device is registered with the correct platform.

View file

@ -0,0 +1,54 @@
### Linux adoption is growing. Management hasn't kept up.
* macOS and Windows have mature management ecosystems. Linux does not.
* Compliance frameworks don't grant exemptions by operating system.
* Security audits don't skip Linux workstations.
* These create the Linux gap.
### Unmanaged devices are unmanaged risk.
This guide helps IT leaders understand and close the Linux management gap.
### What you'll learn
You'll learn about a maturity model for planning your adoption path, a clear framework for defining your requirements, and a concrete evaluation scorecard for comparing management platforms. Whether you manage 50 Linux workstations or 5,000, this guide gives you the structure to make a defensible platform decision and explain it to your team.
### Chapter list
- **Why Linux devices are important**
* What's driving enterprise Linux adoption and why management is no longer optional.
- **The business case for managing Linux devices**
* Cost, compliance, talent retention, and the price of inaction.
- **Defining your Linux device management needs**
* Key questions to ask and a maturity model to map your goals.
- **Automated provisioning for Linux desktop in the enterprise**
* The provisioning gap, enrollment approaches, and what zero-touch looks like on Linux.
- **Security baselines for Linux**
* Why baselines matter, what to enforce, and how to fight configuration drift.
- **App and certificate management for Linux**
* Software distribution challenges, the notarization gap, patching speed, and shrinking certificate lifetimes.
- **Protecting the Linux device**
* USB and Bluetooth threats, the sudo problem, and remote lock and wipe.
- **Controlling your software and your data**
* Software sovereignty, data sovereignty, and why your management tooling should reflect the values that made Linux worth adopting.
- **Choosing the right solution**
* Business and technical requirements, an evaluation criteria table, and a structured way to compare platforms.
<meta name="articleTitle" value="The IT leader's guide to Linux device management">
<meta name="authorFullName" value="n/a">
<meta name="authorGitHubUsername" value="fleet-release">
<meta name="category" value="whitepaper">
<meta name="publishedOn" value="2026-04-20">
<meta name="description" value="Close the Linux management gap. A guide to help IT leaders understand the business case, security, compliance, and choosing the right solution.">
<meta name="articleImageUrl" value="../website/assets/images/articles/IT-leaders-guide-to-Linux-device-management-cover-image-504x336@2x.png">
<meta name="whitepaperFilename" value="IT-leaders-guide-to-Linux-device-management.pdf">
<meta name="formHeadline" value="Learn how to close the Linux management gap">
<meta name="introductionTextBlockOne" value="Linux now exceeds 5% of desktop market share. Stack Overflow's 2025 developer survey shows nearly 30% of developers use Linux as their primary work OS.">
<meta name="introductionTextBlockTwo" value="Your most important contributors, developers, engineers, and security practitioners, are choosing Linux. And in most organizations, those devices sit outside formal IT management.">

View file

@ -57,6 +57,7 @@ You will also see how treating device management as a software discipline helps
<meta name="articleImageUrl" value="../website/assets/images/articles/modern-endpoint-management-managing-devices-as-code-cover-image-504x336@2x.png">
<meta name="formHeadline" value="Learn how GitOps transforms device management">
<meta name="whitepaperFilename" value="fleet-modern-endpoint-device-management-managing-devices-as-code.pdf">
<meta name="introductionTextBlockOne" value="Traditional device management does not scale. Teams still rely on manual updates, GUI tools, and scattered inventories.">

View file

@ -0,0 +1 @@
* Fixed a bug where pending MDM profile rows persisted in the database after Apple or Windows MDM was turned off, causing stale profiles to reappear when MDM was re-enabled. Also fixed cleanup of pending Windows profile rows when a device unenrolls from MDM.

View file

@ -0,0 +1 @@
* Added UI pages for creating and editing API-only users with support for fleet assignment, role selection, and API endpoint access control.

View file

@ -0,0 +1 @@
- Fixed an issue where adding a custom icon for a script-only package was not allowed in GitOps.

View file

@ -0,0 +1 @@
- Added support for Fleet variables in Apple's declaration profiles (DDM).

View file

@ -0,0 +1 @@
* Fixed a bug where host environment variables in script-only packages would cause gitops to fail

1
changes/update-go-1.26.2 Normal file
View file

@ -0,0 +1 @@
* Updated go to 1.26.2

View file

@ -4,11 +4,11 @@ name: fleet
keywords:
- fleet
- osquery
version: v6.8.9
version: v6.8.10
home: https://github.com/fleetdm/fleet
sources:
- https://github.com/fleetdm/fleet.git
appVersion: v4.83.1
appVersion: v4.83.2
dependencies:
- name: mysql
condition: mysql.enabled

View file

@ -4,7 +4,7 @@ hostName: fleet.localhost
replicas: 3 # The number of Fleet instances to deploy
revisionHistoryLimit: 10 # Number of old ReplicaSets for Fleet deployment to retain for rollback (set to 0 for unlimited)
imageRepository: fleetdm/fleet
imageTag: v4.83.1 # Version of Fleet to deploy
imageTag: v4.83.2 # Version of Fleet to deploy
# imagePullSecrets is optional.
# imagePullSecrets:
# - name: docker

View file

@ -202,7 +202,7 @@ func TestApplyAsGitOpsDeprecatedKeys(t *testing.T) {
ds.SetAsideLabelsFunc = func(ctx context.Context, notOnTeamID *uint, names []string, user fleet.User) error {
return nil
}
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
declaration.DeclarationUUID = uuid.NewString()
return declaration, nil
}

View file

@ -298,7 +298,7 @@ func TestApplyTeamSpecs(t *testing.T) {
}
}
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
declaration.DeclarationUUID = uuid.NewString()
return declaration, nil
}
@ -755,7 +755,7 @@ func TestApplyAppConfig(t *testing.T) {
return map[string]uint{fleet.BuiltinLabelMacOS14Plus: 1}, nil
}
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
declaration.DeclarationUUID = uuid.NewString()
return declaration, nil
}
@ -1486,7 +1486,7 @@ func TestApplyAsGitOps(t *testing.T) {
ds.SetAsideLabelsFunc = func(ctx context.Context, notOnTeamID *uint, names []string, user fleet.User) error {
return nil
}
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
declaration.DeclarationUUID = uuid.NewString()
return declaration, nil
}

View file

@ -2610,7 +2610,7 @@ func TestGetTeamsYAMLAndApply(t *testing.T) {
require.ElementsMatch(t, names, []string{fleet.BuiltinLabelMacOS14Plus})
return map[string]uint{fleet.BuiltinLabelMacOS14Plus: 1}, nil
}
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
declaration.DeclarationUUID = uuid.NewString()
return declaration, nil
}

View file

@ -1637,13 +1637,13 @@ func TestGitOpsFullTeam(t *testing.T) {
ds.NewMDMAppleConfigProfileFunc = func(ctx context.Context, profile fleet.MDMAppleConfigProfile, vars []fleet.FleetVarName) (*fleet.MDMAppleConfigProfile, error) {
return &profile, nil
}
ds.NewMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
ds.NewMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
return declaration, nil
}
ds.LabelIDsByNameFunc = func(ctx context.Context, names []string, filter fleet.TeamFilter) (map[string]uint, error) {
return map[string]uint{fleet.BuiltinLabelMacOS14Plus: 1}, nil
}
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
declaration.DeclarationUUID = uuid.NewString()
return declaration, nil
}
@ -5869,7 +5869,7 @@ func TestGitOpsAppleOSUpdates(t *testing.T) {
defaultTeamConfig = config
return nil
}
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
return &fleet.MDMAppleDeclaration{DeclarationUUID: "test-uuid"}, nil
}
ds.LabelIDsByNameFunc = func(ctx context.Context, names []string, filter fleet.TeamFilter) (map[string]uint, error) {
@ -6154,7 +6154,7 @@ func TestGitOpsWindowsOSUpdates(t *testing.T) {
defaultTeamConfig = config
return nil
}
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
return &fleet.MDMAppleDeclaration{DeclarationUUID: "test-uuid"}, nil
}

View file

@ -100,7 +100,7 @@ func setupEmptyGitOpsMocks(ds *mock.Store) {
) (fleet.MDMProfilesUpdates, error) {
return fleet.MDMProfilesUpdates{}, nil
}
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
return &fleet.MDMAppleDeclaration{}, nil
}
ds.DeleteMDMAppleDeclarationByNameFunc = func(ctx context.Context, teamID *uint, name string) error {

View file

@ -450,7 +450,7 @@ func SetupFullGitOpsPremiumServer(t *testing.T) (*mock.Store, **fleet.AppConfig,
savedTeams[team.Name] = &team
return team, nil
}
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (
*fleet.MDMAppleDeclaration, error,
) {
declaration.DeclarationUUID = uuid.NewString()

View file

@ -4222,7 +4222,7 @@ labels:
- name: Test Fleet Label
label_membership_type: dynamic
query: SELECT 1
`, fleetName)
fullFleetFile, err := os.CreateTemp(t.TempDir(), "*.yml")
@ -4518,3 +4518,44 @@ settings:
require.Empty(t, teamMeta.LabelsExcludeAny)
require.Empty(t, teamMeta.LabelsIncludeAll)
}
func (s *enterpriseIntegrationGitopsTestSuite) TestFleetGitopsDDMUnsupportedFleetVariable() {
t := s.T()
user := s.createGitOpsUser(t)
fleetctlConfig := s.createFleetctlConfig(t, user)
// Create a DDM declaration with an unsupported Fleet variable
declDir := t.TempDir()
declFile := path.Join(declDir, "decl-unsupported-var.json")
err := os.WriteFile(declFile, []byte(`{
"Type": "com.apple.configuration.management.test",
"Identifier": "com.example.unsupported-var",
"Payload": {"Value": "$FLEET_VAR_BOZO"}
}`), 0o644)
require.NoError(t, err)
globalFile, err := os.CreateTemp(t.TempDir(), "*.yml")
require.NoError(t, err)
_, err = globalFile.WriteString(fmt.Sprintf(`
agent_options:
controls:
macos_settings:
custom_settings:
- path: %s
org_settings:
server_settings:
server_url: $FLEET_URL
org_info:
org_name: Fleet
secrets:
policies:
queries:
`, declFile))
require.NoError(t, err)
t.Setenv("FLEET_URL", s.Server.URL)
// Applying a DDM declaration with an unsupported Fleet variable should fail
_, err = fleetctl.RunAppNoChecks([]string{"gitops", "--config", fleetctlConfig.Name(), "-f", globalFile.Name()})
require.ErrorContains(t, err, "Fleet variable $FLEET_VAR_BOZO is not supported in DDM profiles")
}

View file

@ -222,3 +222,43 @@ func (s *integrationGitopsTestSuite) TestFleetGitopsWithFleetSecrets() {
require.NoError(t, err)
assert.Contains(t, string(winProfile.SyncML), "${FLEET_SECRET_"+secretName2+"}")
}
func (s *integrationGitopsTestSuite) TestFleetGitopsDDMFleetVarsRequiresPremium() {
t := s.T()
fleetctlConfig := s.createFleetctlConfig()
// Create a DDM declaration with a Fleet variable
declDir := t.TempDir()
declFile := path.Join(declDir, "decl-fleetvar.json")
err := os.WriteFile(declFile, []byte(`{
"Type": "com.apple.configuration.management.test",
"Identifier": "com.example.fleetvar-test",
"Payload": {"Value": "$FLEET_VAR_HOST_HARDWARE_SERIAL"}
}`), 0o644)
require.NoError(t, err)
globalFile, err := os.CreateTemp(t.TempDir(), "*.yml")
require.NoError(t, err)
_, err = globalFile.WriteString(fmt.Sprintf(`
agent_options:
controls:
macos_settings:
custom_settings:
- path: %s
org_settings:
server_settings:
server_url: $FLEET_URL
org_info:
org_name: Fleet
secrets:
policies:
queries:
`, declFile))
require.NoError(t, err)
t.Setenv("FLEET_URL", s.Server.URL)
// Applying a DDM declaration with Fleet variables should fail without a premium license
_, err = fleetctl.RunAppNoChecks([]string{"gitops", "--config", fleetctlConfig.Name(), "-f", globalFile.Name()})
require.ErrorContains(t, err, "missing or invalid license")
}

View file

@ -16,6 +16,10 @@ set -euo pipefail
REPO_URL="https://github.com/canonical/ubuntu-security-notices.git"
REPO_DIR="ubuntu-security-notices"
DAYS_TO_KEEP=3 # how much git history to get for initial clone
# Fallback depth used when --shallow-since returns no commits (upstream was quiet).
# The sync only needs the tip commit to populate the working tree.
# We grab a few extra commits so the warning log shows recent upstream activity for debugging.
FALLBACK_DEPTH=3
echo "=== OSV Repository Sync ==="
echo ""
@ -57,7 +61,17 @@ else
git config core.sparseCheckout true
echo "osv/" > .git/info/sparse-checkout
git fetch --shallow-since="${DAYS_TO_KEEP} days ago" origin main
if ! git fetch --shallow-since="${DAYS_TO_KEEP} days ago" origin main; then
echo ""
echo "WARNING: --shallow-since=${DAYS_TO_KEEP}d returned no commits."
echo "Upstream has been quiet for >${DAYS_TO_KEEP} days. Falling back to --depth=${FALLBACK_DEPTH}."
echo ""
git fetch --depth="${FALLBACK_DEPTH}" origin main
echo "Recent history:"
git log --pretty=format:'%h %ci %s' origin/main
echo ""
echo ""
fi
git checkout -b main --track origin/main
COMMIT_SHA=$(git rev-parse HEAD)

View file

@ -33,12 +33,25 @@ package_path: package_name.yml
package_path: ../software/package_name.yml
```
### `path:` vs `paths:` (glob patterns)
Several sections support both `path:` (singular) and `paths:` (plural), including `scripts`, `configuration_profiles`, `labels`, `policies`, and `reports`:
- **`path:`** references a single, literal file path. Must not contain the characters `*`, `?`, `[`, or `{`.
- **`paths:`** accepts a glob pattern to match multiple files at once (e.g. `../lib/windows/profiles/*.xml`).
You cannot specify both `path:` and `paths:` on the same entry.
> **Important:** Filenames containing `*`, `?`, `[`, or `{` cannot be referenced using `path:`. If your filenames contain these characters (e.g. Windows profiles named `[AllowSpotlightCollection].xml`), either rename the files to remove them, or use `paths:` with a wildcard pattern like `*.xml`.
For the GitOps API token, create a dedicated API-only user with `fleetctl user create --api-only`. These users can modify configurations via GitOps but cant access the Fleet UI. Assign the GitOps role and set the appropriate global or fleet scope in the UI.
## labels
Labels can be specified in your `default.yml` and `fleets/fleet-name.yml` files using inline configuration or references to separate files in your `lib/` folder. Labels cannot be specified in `fleets/unassigned.yml`.
Labels support `path:` (single file) and `paths:` (glob pattern) references. See [`path:` vs `paths:`](#path-vs-paths-glob-patterns) for details. Filenames must not contain `*`, `?`, `[`, or `{` when using `path:`.
- `name` specifies the label's name. Must be unique across all global and fleet labels.
+ Changing a label's `name` in GitOps will delete and re-create the label, temporarily clearing its membership. To avoid this, update the label name in the UI before making the change in YAML.
- `description` specifies the label's description.
@ -111,6 +124,7 @@ labels:
```yaml
labels:
- path: ./lib/labels-name.labels.yml
- paths: ./lib/labels/*.yml
```
@ -118,6 +132,8 @@ labels:
Policies can be specified inline in your `default.yml`, `fleets/fleet-name.yml`, or `fleets/unassigned.yml` files. They can also be specified in separate files in your `lib/` folder.
Policies support `path:` (single file) and `paths:` (glob pattern) references. See [`path:` vs `paths:`](#path-vs-paths-glob-patterns) for details. Filenames must not contain `*`, `?`, `[`, or `{` when using `path:`.
### Options
For available options, see the parameters for the [Create policy](https://fleetdm.com/docs/rest-api/rest-api#create-policy) and [Create team policy](https://fleetdm.com/docs/rest-api/rest-api#create-team-policy) API endpoints.
@ -223,6 +239,7 @@ policies:
```yaml
policies:
- path: ../lib/policies-name.policies.yml
- paths: ../lib/*.policies.yml
```
> Currently, the `run_script` and `install_software` policy automations can only be configured for a fleet (`fleets/fleet-name.yml`) or "Unassigned" (`fleets/unassigned.yml`). The automations can only be added to policies in which the script (or software) is defined in the same fleet (or "Unassigned"). `calendar_events_enabled` can only be configured for policies on a fleet.
@ -234,6 +251,8 @@ policies:
Reports can be specified inline in your `default.yml` file or `fleets/fleet-name.yml` files. They can also be specified in separate files in your `lib/` folder.
Reports support `path:` (single file) and `paths:` (glob pattern) references. See [`path:` vs `paths:`](#path-vs-paths-glob-patterns) for details. Filenames must not contain `*`, `?`, `[`, or `{` when using `path:`.
### Options
For possible options, see the parameters for the [Create report API endpoint](https://fleetdm.com/docs/rest-api/rest-api#create-report).
@ -287,6 +306,7 @@ reports:
labels_include_any:
- Engineering
- Customer Support
- paths: ../lib/*.reports.yml
```
## agent_options
@ -351,7 +371,7 @@ agent_options:
The `controls` section allows you to configure scripts and device management (MDM) features in Fleet.
- `scripts` is a list of paths to macOS, Windows, or Linux scripts.
- `scripts` is a list of paths to macOS, Windows, or Linux scripts. Supports `path:` (single file) and `paths:` (glob pattern, filtered to `.sh` and `.ps1` files only). Filenames must not contain `*`, `?`, `[`, or `{` when using `path:`. See [`path:` vs `paths:`](#path-vs-paths-glob-patterns) for details.
- `windows_enabled_and_configured` specifies whether or not to turn on Windows MDM features (default: `false`). Can only be configured for "All fleets" (`default.yml`).
- `windows_entra_tenant_ids` is a list of Microsoft Entra tenant IDs to enable automatic (Autopilot) and manual enrollment by end users (**Settings** > **Accounts** > **Access work or school** on Windows). Can only be configured for "All fleets" (`default.yml`). Find your **Tenant ID**, on [**Microsoft Entra ID** > **Home**](https://entra.microsoft.com/#home).
- `enable_turn_on_windows_mdm_manually` specifies whether or not to require end users to manually turn on MDM in **Settings > Access work or school** (default: `false`). If `false`, MDM is automatically turned on for all Windows hosts that aren't connected to any MDM solution. Can only be configured for "All fleets" (`default.yml`).
@ -368,6 +388,7 @@ controls:
- path: ../lib/macos-script.sh
- path: ../lib/windows-script.ps1
- path: ../lib/linux-script.sh
- paths: ../lib/scripts/*.sh # Glob pattern (filtered to .sh and .ps1 only)
windows_enabled_and_configured: true
windows_entra_tenant_ids:
- 4e342a0d-ec1a-4353-bdeb-785542e0a8fb
@ -393,16 +414,24 @@ controls:
- path: ../lib/macos-profile1.mobileconfig
labels_exclude_any: # Available in Fleet Premium
- Macs on Sequoia
<<<<<<< AdamBaali-Gitops-YAML-globs-update
- path: ../lib/macos-profile2.json
labels_include_all: # Available in Fleet Premium
- Macs on Sonoma
- paths: ../lib/macos/profiles/*.mobileconfig # Glob pattern to include all .mobileconfig files
=======
- path: ../lib/macos-profile3.mobileconfig
>>>>>>> main
labels_include_any: # Available in Fleet Premium
- Engineering
- Product
- paths: ../lib/configuration-profiles/*.json
windows_settings:
configuration_profiles:
- path: ../lib/windows-profile.xml
- paths: ../lib/windows/profiles/*.xml # Glob pattern to include all .xml files in directory
labels_include_any:
- Engineering
android_settings:
configuration_profiles:
- path: ../lib/android-profile.json
@ -445,14 +474,21 @@ controls:
### apple_settings and windows_settings
- `apple_settings.configuration_profiles` is a list of paths to macOS, iOS, and iPadOS configuration profiles (.mobileconfig) or declaration profiles (.json).
- `windows_settings.configuration_profiles` is a list of paths to Windows configuration profiles (.xml).
- `apple_settings.configuration_profiles` is a list of macOS, iOS, and iPadOS configuration profiles (.mobileconfig) or declaration profiles (.json).
- `windows_settings.configuration_profiles` is a list of Windows configuration profiles (.xml).
Each entry can use either `path:` or `paths:`:
- **`path:`** references a single file. Filenames must not contain `*`, `?`, `[`, or `{`.
- **`paths:`** accepts a [glob pattern](#path-vs-paths-glob-patterns) to match multiple files (e.g. `../lib/windows/profiles/*.xml`). Labels and other options specified on a `paths:` entry apply to all matched files.
Use `labels_include_all` to target hosts that have all labels, `labels_include_any` to target hosts that have any label, or `labels_exclude_any` to target hosts that don't have any of the labels. Only one of `labels_include_all`, `labels_include_any`, or `labels_exclude_any` can be specified. If none are specified, all hosts are targeted.
### android_settings
- `android_settings.configuration_profiles` is a list of paths to Android configuration profiles (.json).
- `android_settings.configuration_profiles` is a list of Android configuration profiles (.json).
Each entry can use either `path:` or `paths:`. Filenames must not contain `*`, `?`, `[`, or `{` when using `path:`. See [`path:` vs `paths:`](#path-vs-paths-glob-patterns) for glob pattern support.
Use `labels_include_all` to target hosts that have all labels, `labels_include_any` to target hosts that have any label, or `labels_exclude_any` to target hosts that don't have any of the labels. Only one of `labels_include_all`, `labels_include_any`, or `labels_exclude_any` can be specified. If none are specified, all hosts are targeted.

View file

@ -232,7 +232,7 @@ Enables exporting logs to an OpenTelemetry collector in addition to stderr outpu
### mdm.allow_all_declarations
Documentation for setting has moved to the [Fleet server configuration](https://fleetdm.com/docs/configuration/fleet-server-configuration#mdm-allow_all_declarations) reference.
Documentation for setting has moved to the [Fleet server configuration](https://fleetdm.com/docs/configuration/fleet-server-configuration#mdm-allow-all-declarations) reference.
### FLEET_ENABLE_POST_CLIENT_DEBUG_ERRORS

View file

@ -3973,6 +3973,8 @@ If `hostname` is specified when there is more than one host with the same hostna
### Get host by Fleet Desktop token
> If you're hitting this endpoint often (e.g. every hour) for a large number of hosts (e.g. 1k+) the best practice is to set the `exclude_software` to `true` to prevent overloading the Fleet server.
Returns a subset of information about the host specified by `token`. To get all information about a host, use the ["Get host"](#get-host) endpoint.
This is the API route used by the **My device** page in Fleet Desktop to display information about the host to the end user.
@ -3986,6 +3988,7 @@ This endpoint doesn't require API token authentication. Authentication on macOS,
| Name | Type | In | Description |
| ----- | ------ | ---- | ---------------------------------- |
| token | string | path | The host's [Fleet Desktop token](https://fleetdm.com/guides/fleet-desktop#secure-fleet-desktop). For macOS, Windows, and Linux, this is a random UUID that rotates hourly. For iOS and iPadOS, this is the host's hardware UUID. |
| exclude_software | boolean | query | If `true`, the response will not include a list of installed software for the host. |
#### Request headers

View file

@ -0,0 +1,11 @@
{
"name": "Druva inSync",
"slug": "druva-insync/windows",
"package_identifier": "Druva.inSync",
"unique_identifier": "Druva inSync",
"fuzzy_match_name": true,
"installer_arch": "x64",
"installer_type": "msi",
"installer_scope": "machine",
"default_categories": ["Productivity"]
}

View file

@ -631,6 +631,13 @@
"unique_identifier": "com.getdropbox.dropbox",
"description": "Dropbox is a client for the Dropbox cloud storage service."
},
{
"name": "Druva inSync",
"slug": "druva-insync/windows",
"platform": "windows",
"unique_identifier": "Druva inSync",
"description": "Druva inSync is a cloud-based product that protects endpoint data."
},
{
"name": "Eclipse IDE",
"slug": "eclipse-ide/darwin",
@ -650,14 +657,14 @@
"slug": "elgato-control-center/darwin",
"platform": "darwin",
"unique_identifier": "com.corsair.ControlCenter",
"description": "Elgate Control Center is an app to control your Elgato key lights."
"description": "Elgato Control Center is an app to control your Elgato key lights."
},
{
"name": "Elgato Stream Deck",
"slug": "elgato-stream-deck/darwin",
"platform": "darwin",
"unique_identifier": "com.elgato.StreamDeck",
"description": "Elgateo Stream Deck is an app to assign keys, and then decorate and label them, on a Stream Deck."
"description": "Elgato Stream Deck is an app to assign keys, and then decorate and label them, on a Stream Deck."
},
{
"name": "Evernote",

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "1.142.1",
"version": "1.143.2",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'company.thebrowser.Browser';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'company.thebrowser.Browser' AND version_compare(bundle_short_version, '1.142.1') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'company.thebrowser.Browser' AND version_compare(bundle_short_version, '1.143.2') < 0);"
},
"installer_url": "https://releases.arc.net/release/Arc-1.142.1-78710.zip",
"installer_url": "https://releases.arc.net/release/Arc-1.143.2-79250.zip",
"install_script_ref": "0c68f8e0",
"uninstall_script_ref": "d6b0eb40",
"sha256": "b473533e163be0fc04798e41ba4b6ce30c6a71368331c31799b604e5244e7769",
"sha256": "d06d70a050f40651b761aa733f2c7096eaa396d57e5879f3bc20bbe8cdf90882",
"default_categories": [
"Browsers"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "147.1.89.132",
"version": "147.1.89.137",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.brave.Browser';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.brave.Browser' AND version_compare(bundle_short_version, '147.1.89.132') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.brave.Browser' AND version_compare(bundle_short_version, '147.1.89.137') < 0);"
},
"installer_url": "https://updates-cdn.bravesoftware.com/sparkle/Brave-Browser/stable-arm64/189.132/Brave-Browser-arm64.dmg",
"installer_url": "https://updates-cdn.bravesoftware.com/sparkle/Brave-Browser/stable-arm64/189.137/Brave-Browser-arm64.dmg",
"install_script_ref": "14ab8c47",
"uninstall_script_ref": "e860eed9",
"sha256": "28c566312b6bc4bbbab8af0a1ffdf409645dfcd596a514273baa4641ec57c27a",
"sha256": "e99cee5c36402f1d2afe324d546158578bc29f54b087dada4743087886088931",
"default_categories": [
"Browsers"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "147.1.89.132",
"version": "147.1.89.137",
"queries": {
"exists": "SELECT 1 FROM programs WHERE name = 'Brave' AND publisher = 'Brave Software Inc';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Brave' AND publisher = 'Brave Software Inc' AND version_compare(version, '147.1.89.132') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Brave' AND publisher = 'Brave Software Inc' AND version_compare(version, '147.1.89.137') < 0);"
},
"installer_url": "https://github.com/brave/brave-browser/releases/download/v1.89.132/BraveBrowserStandaloneSilentSetup.exe",
"installer_url": "https://github.com/brave/brave-browser/releases/download/v1.89.137/BraveBrowserStandaloneSilentSetup.exe",
"install_script_ref": "9a0c2b15",
"uninstall_script_ref": "30c77f69",
"sha256": "43e4177a53a5ca12633f607a6b623147be55493645ff6233dc65f1a9fcb70583",
"sha256": "6df590d6e0630609036b504af7a56e8c18e9dfc93539f3c17568586f973a7804",
"default_categories": [
"Browsers"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "1.2026.84.2",
"version": "1.2026.98.2",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.openai.atlas';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.openai.atlas' AND version_compare(bundle_short_version, '1.2026.84.2') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.openai.atlas' AND version_compare(bundle_short_version, '1.2026.98.2') < 0);"
},
"installer_url": "https://persistent.oaistatic.com/atlas/public/ChatGPT_Atlas_Desktop_public_1.2026.84.2_20260408151909000.dmg",
"installer_url": "https://persistent.oaistatic.com/atlas/public/ChatGPT_Atlas_Desktop_public_1.2026.98.2_20260416164957000.dmg",
"install_script_ref": "b8f2e355",
"uninstall_script_ref": "06984429",
"sha256": "2a75ebcfe662d792455309d2b1366ff95fb783e86ed3ab667f4a691beb34f1ab",
"sha256": "7f4c2a6807b45a6fe84a3477a7dc9c8ff1d7c4f02873fc299e91eda33c218427",
"default_categories": [
"Browsers"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "1.2026.051",
"version": "1.2026.099",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.openai.chat';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.openai.chat' AND version_compare(bundle_short_version, '1.2026.051') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.openai.chat' AND version_compare(bundle_short_version, '1.2026.099') < 0);"
},
"installer_url": "https://persistent.oaistatic.com/sidekick/public/ChatGPT_Desktop_public_1.2026.051_1775834670.dmg",
"installer_url": "https://persistent.oaistatic.com/sidekick/public/ChatGPT_Desktop_public_1.2026.099_1776706502.dmg",
"install_script_ref": "105f16ab",
"uninstall_script_ref": "dbaa4d2e",
"sha256": "4d5db720e5625514b34d53e52de9360413f0fb32de9d932eb88fcca66f99f7a7",
"sha256": "f3a6d63494ff9ef8af8abf6dd3be5297db7f904ea01040b790251e6846b4ac88",
"default_categories": [
"Productivity"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "1.2773.0",
"version": "1.3561.0",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.anthropic.claudefordesktop';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.anthropic.claudefordesktop' AND version_compare(bundle_short_version, '1.2773.0') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.anthropic.claudefordesktop' AND version_compare(bundle_short_version, '1.3561.0') < 0);"
},
"installer_url": "https://downloads.claude.ai/releases/darwin/universal/1.2773.0/Claude-884b3735b1ce5042a0c286824c6f9bd2d341f7c8.zip",
"installer_url": "https://downloads.claude.ai/releases/darwin/universal/1.3561.0/Claude-fbc74be3fdc714a2c46ef1fb84f71d4e4c062930.zip",
"install_script_ref": "d05235fc",
"uninstall_script_ref": "4cfbec7d",
"sha256": "74b8226817ca96199accbae6f1410ad23c1d4d024c900276b8faf946f42c8a37",
"sha256": "b037ee8ebe3d11e7eba959179dfdc534951ae8e387e96cacda1dceeecd035b52",
"default_categories": [
"Developer tools"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "1.2773.0",
"version": "1.3561.0",
"queries": {
"exists": "SELECT 1 FROM programs WHERE name = 'Claude' AND publisher = 'Anthropic, PBC';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Claude' AND publisher = 'Anthropic, PBC' AND version_compare(version, '1.2773.0') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Claude' AND publisher = 'Anthropic, PBC' AND version_compare(version, '1.3561.0') < 0);"
},
"installer_url": "https://downloads.claude.ai/releases/win32/x64/1.2773.0/Claude-884b3735b1ce5042a0c286824c6f9bd2d341f7c8.msix",
"installer_url": "https://downloads.claude.ai/releases/win32/x64/1.3561.0/Claude-fbc74be3fdc714a2c46ef1fb84f71d4e4c062930.msix",
"install_script_ref": "31a0b698",
"uninstall_script_ref": "03f72055",
"sha256": "17c8d3784cd1877d792bfd3a9457d628ca8797562eaf73b581704f7fad83daac",
"sha256": "726cf8552406f0a6260c5ddce9d5a6f560fb0f9098137447e636adfe752174cc",
"default_categories": [
"Productivity"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "6.2.6",
"version": "7.0.0",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.coteditor.CotEditor';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.coteditor.CotEditor' AND version_compare(bundle_short_version, '6.2.6') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.coteditor.CotEditor' AND version_compare(bundle_short_version, '7.0.0') < 0);"
},
"installer_url": "https://github.com/coteditor/CotEditor/releases/download/6.2.6/CotEditor_6.2.6.dmg",
"installer_url": "https://github.com/coteditor/CotEditor/releases/download/7.0.0/CotEditor_7.0.0.dmg",
"install_script_ref": "e5de4a42",
"uninstall_script_ref": "37cee933",
"sha256": "6ccc029ede9da8eb497f31a8423cfea91bf34e7a08c67b66be0e331a922e8fc2",
"sha256": "9eb8c709fe29046673d56e9e62c0176d4eb5869166860825cc005267f26da68d",
"default_categories": [
"Developer tools"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "3.1.15",
"version": "3.1.17",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.todesktop.230313mzl4w4u92';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.todesktop.230313mzl4w4u92' AND version_compare(bundle_short_version, '3.1.15') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.todesktop.230313mzl4w4u92' AND version_compare(bundle_short_version, '3.1.17') < 0);"
},
"installer_url": "https://downloads.cursor.com/production/3a67af7b780e0bfc8d32aefa96b8ff1cb8817f88/darwin/arm64/Cursor-darwin-arm64.zip",
"installer_url": "https://downloads.cursor.com/production/fce1e9ab7844f9ea35793da01e634aa7e50bce90/darwin/arm64/Cursor-darwin-arm64.zip",
"install_script_ref": "5a1b1299",
"uninstall_script_ref": "f7561d44",
"sha256": "e0b65b57d30d94eb668151c9b44d474f7fbb9c78a2bc4ec1bdff1a537bbc21a2",
"sha256": "2c308456eb5b834da262fe4f3cca744e179e68eb25591d0b4f83c3b742956290",
"default_categories": [
"Developer tools"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "3.1.15",
"version": "3.1.17",
"queries": {
"exists": "SELECT 1 FROM programs WHERE name = 'Cursor' AND publisher = 'Anysphere';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Cursor' AND publisher = 'Anysphere' AND version_compare(version, '3.1.15') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Cursor' AND publisher = 'Anysphere' AND version_compare(version, '3.1.17') < 0);"
},
"installer_url": "https://downloads.cursor.com/production/3a67af7b780e0bfc8d32aefa96b8ff1cb8817f88/win32/x64/system-setup/CursorSetup-x64-3.1.15.exe",
"installer_url": "https://downloads.cursor.com/production/fce1e9ab7844f9ea35793da01e634aa7e50bce90/win32/x64/system-setup/CursorSetup-x64-3.1.17.exe",
"install_script_ref": "03589b5e",
"uninstall_script_ref": "6c8096c5",
"sha256": "d667e13c7e538e11b23569071f2a47b271494038f9ae0be6c424a30c318bc73b",
"sha256": "14f6e7c8244175496bf8be1af05a7004d7013b6928576a0cdc350705baa8808d",
"default_categories": [
"Developer tools"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "26.0.2",
"version": "26.0.3",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'org.jkiss.dbeaver.core.product';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'org.jkiss.dbeaver.core.product' AND version_compare(bundle_short_version, '26.0.2') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'org.jkiss.dbeaver.core.product' AND version_compare(bundle_short_version, '26.0.3') < 0);"
},
"installer_url": "https://dbeaver.io/files/26.0.2/dbeaver-ce-26.0.2-macos-aarch64.dmg",
"installer_url": "https://dbeaver.io/files/26.0.3/dbeaver-ce-26.0.3-macos-aarch64.dmg",
"install_script_ref": "6f101bb8",
"uninstall_script_ref": "d5f7201c",
"sha256": "6000d9eedb444dfb3edc70b4e397879ed2e3d71f06444c34dbb1860d2188783c",
"sha256": "bfc0902d04403b32d8d4fab120417368aa374622dbfe2f508713d06474ae82e2",
"default_categories": [
"Developer tools"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "0.0.385",
"version": "0.0.386",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.hnc.Discord';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.hnc.Discord' AND version_compare(bundle_short_version, '0.0.385') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.hnc.Discord' AND version_compare(bundle_short_version, '0.0.386') < 0);"
},
"installer_url": "https://dl.discordapp.net/apps/osx/0.0.385/Discord.dmg",
"installer_url": "https://dl.discordapp.net/apps/osx/0.0.386/Discord.dmg",
"install_script_ref": "dac37ced",
"uninstall_script_ref": "8ed76f08",
"sha256": "c5b69b1d27abd56d610cdb6173b4575ec84971aa1bbf91875e992c85bad3cff7",
"sha256": "a01cf51f325bb95f4f9dd2ca96f9c1a03f547ac00c4e2034164835508cd8a04d",
"default_categories": [
"Communication"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "1.0.9233",
"version": "1.0.9234",
"queries": {
"exists": "SELECT 1 FROM programs WHERE name = 'Discord' AND publisher = 'Discord Inc.';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Discord' AND publisher = 'Discord Inc.' AND version_compare(version, '1.0.9233') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Discord' AND publisher = 'Discord Inc.' AND version_compare(version, '1.0.9234') < 0);"
},
"installer_url": "https://stable.dl2.discordapp.net/distro/app/stable/win/x64/1.0.9233/DiscordSetup.exe",
"installer_url": "https://stable.dl2.discordapp.net/distro/app/stable/win/x64/1.0.9234/DiscordSetup.exe",
"install_script_ref": "fd04e860",
"uninstall_script_ref": "73fc6eff",
"sha256": "eaba7863d5a7ed017a865f991267583e0768914aba99590874da0980832e45a3",
"sha256": "3f0306caceaa9594c608b39dbee8ceaba4422abc51052ee21deda7280eee9173",
"default_categories": [
"Communication"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "4.69.0",
"version": "4.70.0",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.electron.dockerdesktop';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.electron.dockerdesktop' AND version_compare(bundle_short_version, '4.69.0') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.electron.dockerdesktop' AND version_compare(bundle_short_version, '4.70.0') < 0);"
},
"installer_url": "https://desktop.docker.com/mac/main/arm64/224084/Docker.dmg",
"installer_url": "https://desktop.docker.com/mac/main/arm64/224270/Docker.dmg",
"install_script_ref": "091b8a34",
"uninstall_script_ref": "c31a36e7",
"sha256": "8e4638f2d427a4fb9d0f86f21d0975a344a164228d20fc22a620750b7943d644",
"sha256": "38a19ac039dee38e0e445118da34962039ef1601b0656dc4d138592efda2caba",
"default_categories": [
"Developer tools"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "29.6.6",
"version": "29.7.8",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.jgraph.drawio.desktop';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.jgraph.drawio.desktop' AND version_compare(bundle_short_version, '29.6.6') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.jgraph.drawio.desktop' AND version_compare(bundle_short_version, '29.7.8') < 0);"
},
"installer_url": "https://github.com/jgraph/drawio-desktop/releases/download/v29.6.6/draw.io-arm64-29.6.6.dmg",
"installer_url": "https://github.com/jgraph/drawio-desktop/releases/download/v29.7.8/draw.io-arm64-29.7.8.dmg",
"install_script_ref": "60c841d6",
"uninstall_script_ref": "58c5bcdc",
"sha256": "d725b6333977adf73ecbfa3dcc60dd4f2d745706e6758526611b737561a5c61e",
"sha256": "4ed41dcea4b40f7c534974f3b6c90aaf098e1cc747b4d0bc0b2967ee2f75fa18",
"default_categories": [
"Productivity"
]

View file

@ -0,0 +1,23 @@
{
"versions": [
{
"version": "7.5.7",
"queries": {
"exists": "SELECT 1 FROM programs WHERE name LIKE 'Druva inSync %' AND publisher = 'Druva Technologies Pte. Ltd.';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'Druva inSync %' AND publisher = 'Druva Technologies Pte. Ltd.' AND version_compare(version, '7.5.7') < 0);"
},
"installer_url": "https://downloads.druva.com/downloads/inSync/Windows/7.5.7/inSync7.5.7r110923.msi",
"install_script_ref": "8959087b",
"uninstall_script_ref": "b98f2558",
"sha256": "44e7295a0efba9e386e5dc24fa1e024e84b14d5e70f290ddd4389da5c5e5c96e",
"default_categories": [
"Productivity"
],
"upgrade_code": "{99ADCB07-6ABD-4A1D-AFF6-03649753BAFF}"
}
],
"refs": {
"8959087b": "$logFile = \"${env:TEMP}/fleet-install-software.log\"\n\ntry {\n\n$installProcess = Start-Process msiexec.exe `\n -ArgumentList \"/quiet /norestart /lv ${logFile} /i `\"${env:INSTALLER_PATH}`\"\" `\n -PassThru -Verb RunAs -Wait\n\nGet-Content $logFile -Tail 500\n\nExit $installProcess.ExitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n",
"b98f2558": "# Fleet uninstalls app by finding all related product codes for the specified upgrade code\n$inst = New-Object -ComObject \"WindowsInstaller.Installer\"\n$timeoutSeconds = 300 # 5 minute timeout per product\n\nforeach ($product_code in $inst.RelatedProducts('{99ADCB07-6ABD-4A1D-AFF6-03649753BAFF}')) {\n $process = Start-Process msiexec -ArgumentList @(\"/quiet\", \"/x\", $product_code, \"/norestart\") -PassThru\n \n # Wait for process with timeout\n $completed = $process.WaitForExit($timeoutSeconds * 1000)\n \n if (-not $completed) {\n Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue\n Exit 1603 # ERROR_UNINSTALL_FAILURE\n }\n \n # If the uninstall failed, bail\n if ($process.ExitCode -ne 0) {\n Write-Output \"Uninstall for $($product_code) exited $($process.ExitCode)\"\n Exit $process.ExitCode\n }\n}\n\n# All uninstalls succeeded; exit success\nExit 0\n"
}
}

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "126.2.10",
"version": "126.3.12",
"queries": {
"exists": "SELECT 1 FROM programs WHERE name = 'Figma' AND publisher = 'Figma, Inc.';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Figma' AND publisher = 'Figma, Inc.' AND version_compare(version, '126.2.10') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Figma' AND publisher = 'Figma, Inc.' AND version_compare(version, '126.3.12') < 0);"
},
"installer_url": "https://desktop.figma.com/win/build/Figma-126.2.10.exe",
"installer_url": "https://desktop.figma.com/win/build/Figma-126.3.12.exe",
"install_script_ref": "442d71b3",
"uninstall_script_ref": "e33afd6b",
"sha256": "1642d5c0747a8c91ab11f4bbe921d0b3fff30f66e730135142018c7ec9feddd8",
"sha256": "171f090862ce8cc97316fa8341850df1a3ef05e0145f3364ec7af98447533f97",
"default_categories": [
"Productivity"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "3.2.2",
"version": "3.2.4",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'org.gimp.gimp-3.0';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'org.gimp.gimp-3.0' AND version_compare(bundle_short_version, '3.2.2') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'org.gimp.gimp-3.0' AND version_compare(bundle_short_version, '3.2.4') < 0);"
},
"installer_url": "https://download.gimp.org/gimp/v3.2/macos/gimp-3.2.2-arm64.dmg",
"installer_url": "https://download.gimp.org/gimp/v3.2/macos/gimp-3.2.4-arm64.dmg",
"install_script_ref": "9d89c548",
"uninstall_script_ref": "c6d835f1",
"sha256": "899706072aca7db958a6f2f8ed25123f5bd4c0dd0228c880c50d4e7064da4dc3",
"sha256": "294c016dca7795999129a38b462f80fac3c13cb963e6de9d04eeb5d6e519392b",
"default_categories": [
"Productivity"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "3.2.2.0",
"version": "3.2.4.0",
"queries": {
"exists": "SELECT 1 FROM programs WHERE name LIKE 'GIMP %' AND publisher = 'The GIMP Team';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'GIMP %' AND publisher = 'The GIMP Team' AND version_compare(version, '3.2.2.0') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'GIMP %' AND publisher = 'The GIMP Team' AND version_compare(version, '3.2.4.0') < 0);"
},
"installer_url": "https://download.gimp.org/gimp/v3.2/windows/gimp-3.2.2-setup.exe",
"installer_url": "https://download.gimp.org/gimp/v3.2/windows/gimp-3.2.4-setup.exe",
"install_script_ref": "7e5269bc",
"uninstall_script_ref": "79fb181d",
"sha256": "cbdcdb49c144d5ef26693f03939fff22770bed22b83da7c420cdfe78a18b383e",
"sha256": "ec31d757dd82831d201ffcf47ffeac4175df739e0c02d5122e89aeeadfb988cc",
"default_categories": [
"Productivity"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "12.0.0",
"version": "12.0.1",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.axosoft.gitkraken';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.axosoft.gitkraken' AND version_compare(bundle_short_version, '12.0.0') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.axosoft.gitkraken' AND version_compare(bundle_short_version, '12.0.1') < 0);"
},
"installer_url": "https://api.gitkraken.dev/releases/production/darwin/arm64/12.0.0/GitKraken-v12.0.0.zip",
"installer_url": "https://api.gitkraken.dev/releases/production/darwin/arm64/12.0.1/GitKraken-v12.0.1.zip",
"install_script_ref": "0ff0c24b",
"uninstall_script_ref": "24856f6f",
"sha256": "b38d1f6551a4250a29967f1442f659e0db82bef8c9abbac9afaeb658a0ed23fb",
"sha256": "2c3f694fe3de2ffdca5d3bdbb5f8f2634725850f5eeccfafdb3204bc09be1edf",
"default_categories": [
"Developer tools"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "7.128.0",
"version": "7.140.1",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.granola.app';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.granola.app' AND version_compare(bundle_short_version, '7.128.0') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.granola.app' AND version_compare(bundle_short_version, '7.140.1') < 0);"
},
"installer_url": "https://dr2v7l5emb758.cloudfront.net/7.128.0/Granola-7.128.0-mac-universal.dmg",
"installer_url": "https://dr2v7l5emb758.cloudfront.net/7.140.1/Granola-7.140.1-mac-universal.dmg",
"install_script_ref": "4a04ff4b",
"uninstall_script_ref": "9f1ed248",
"sha256": "378ce94f09f574a57bfb32531e2f03c2a241c24a24a009350b1d04efe8ef602a",
"sha256": "4d9a9c461c6efb1262f2980771e7979643084d12b6f95e977006cc379d5d1135",
"default_categories": [
"Productivity"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "7.128.0",
"version": "7.140.1",
"queries": {
"exists": "SELECT 1 FROM programs WHERE name LIKE 'Granola %' AND publisher = 'Granola';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'Granola %' AND publisher = 'Granola' AND version_compare(version, '7.128.0') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'Granola %' AND publisher = 'Granola' AND version_compare(version, '7.140.1') < 0);"
},
"installer_url": "https://api.granola.ai/v1/check-for-update/Granola-7.128.0-win-x64.exe",
"installer_url": "https://api.granola.ai/v1/check-for-update/Granola-7.140.1-win-x64.exe",
"install_script_ref": "3f66ac53",
"uninstall_script_ref": "a4fab3f5",
"sha256": "4ff0a9cec505f1e892f5b0ab90164c062d3aa17f1bbe4040c536c1672e32ca2c",
"sha256": "9dfced2d0f94f8f9ef32c58cae3272f10cee1595f8b381f70bc92a3dc7941af9",
"default_categories": [
"Productivity"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "1.4.1",
"version": "1.4.2",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.colliderli.iina';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.colliderli.iina' AND version_compare(bundle_short_version, '1.4.1') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.colliderli.iina' AND version_compare(bundle_short_version, '1.4.2') < 0);"
},
"installer_url": "https://dl-portal.iina.io/IINA.v1.4.1.dmg",
"installer_url": "https://dl-portal.iina.io/IINA.v1.4.2-build164.dmg",
"install_script_ref": "18ab90f9",
"uninstall_script_ref": "20f465cb",
"sha256": "177ad469ea129bed95a82ac59b5fb58d0a06c35342fca7a37dba214a8821f848",
"sha256": "804e3368518f19039ebfbc3d698e1fabc9cd20f15fc4e42de635456cdf6a7f58",
"default_categories": [
"Utilities"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "0.344.0",
"version": "0.345.1",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.loom.desktop';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.loom.desktop' AND version_compare(bundle_short_version, '0.344.0') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.loom.desktop' AND version_compare(bundle_short_version, '0.345.1') < 0);"
},
"installer_url": "https://packages.loom.com/desktop-packages/Loom-0.344.0-arm64.dmg",
"installer_url": "https://packages.loom.com/desktop-packages/Loom-0.345.1-arm64.dmg",
"install_script_ref": "8185f7a5",
"uninstall_script_ref": "393b959f",
"sha256": "c5c561c45ce97d6bfaf344b0f12417165345e69a78dee3cfd02705e3c56b929d",
"sha256": "dc837812b1e3255575e44e72b0a84f34b0f6500e91af32b234eb65f8fcd115ad",
"default_categories": [
"Productivity"
]

File diff suppressed because one or more lines are too long

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "147.0.3912.60",
"version": "147.0.3912.72",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.microsoft.edgemac';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.microsoft.edgemac' AND version_compare(bundle_short_version, '147.0.3912.60') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.microsoft.edgemac' AND version_compare(bundle_short_version, '147.0.3912.72') < 0);"
},
"installer_url": "https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/b3b6a577-fc74-4bfe-b7a9-ee3a54e24a9a/MicrosoftEdge-147.0.3912.60.dmg",
"installer_url": "https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/897aa370-de25-41e0-9664-a7944796d7ee/MicrosoftEdge-147.0.3912.72.dmg",
"install_script_ref": "b9ba259a",
"uninstall_script_ref": "6ee9d9a4",
"sha256": "89826009dce74190b59f40f64ebcee50243728d7206ca4bbe44c6e78d2e97462",
"sha256": "6c1aaff7682af11d192e1fb9cadfdbccb2b2b68b58255a81d877a22a80b1eab8",
"default_categories": [
"Browsers"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "147.0.3912.60",
"version": "147.0.3912.72",
"queries": {
"exists": "SELECT 1 FROM programs WHERE name = 'Microsoft Edge' AND publisher = 'Microsoft Corporation';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Microsoft Edge' AND publisher = 'Microsoft Corporation' AND version_compare(version, '147.0.3912.60') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Microsoft Edge' AND publisher = 'Microsoft Corporation' AND version_compare(version, '147.0.3912.72') < 0);"
},
"installer_url": "https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/5428dd4e-4363-469a-a2f5-e7d44afa501f/MicrosoftEdgeEnterpriseX64.msi",
"installer_url": "https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/a7793e3c-0595-419c-bfc9-a891c92c6e53/MicrosoftEdgeEnterpriseX64.msi",
"install_script_ref": "8959087b",
"uninstall_script_ref": "a173cfc1",
"sha256": "b0c8fe30357b666beff27433b81d001df50af53b16a598e2c0e65dd66d1c1b35",
"sha256": "f38cde736a1b9a538d85832ebba099e67f76c8c3ef781c559967c6ab95e1b130",
"default_categories": [
"Browsers"
],

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "10.0.3",
"version": "10.0.4",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.nordvpn.macos';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.nordvpn.macos' AND version_compare(bundle_short_version, '10.0.3') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.nordvpn.macos' AND version_compare(bundle_short_version, '10.0.4') < 0);"
},
"installer_url": "https://downloads.nordcdn.com/apps/macos/generic/NordVPN-OpenVPN/10.0.3/NordVPN.pkg",
"installer_url": "https://downloads.nordcdn.com/apps/macos/generic/NordVPN-OpenVPN/10.0.4/NordVPN.pkg",
"install_script_ref": "1fd3c81d",
"uninstall_script_ref": "ebca7748",
"sha256": "feb1eee445598ce3fd1b1440e345ed6ac484d351a3f8bf8b5be10b0d14e56fc4",
"sha256": "dce634baebc9d9f78f4c2048ecb1345fb71426f8438d82b8e7c6a27ade012ec4",
"default_categories": [
"Productivity"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "1.132.0",
"version": "1.133.0",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.cron.electron';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.cron.electron' AND version_compare(bundle_short_version, '1.132.0') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.cron.electron' AND version_compare(bundle_short_version, '1.133.0') < 0);"
},
"installer_url": "https://calendar-desktop-release.notion-static.com/Notion%20Calendar-darwin-arm64-1.132.0.zip",
"installer_url": "https://calendar-desktop-release.notion-static.com/Notion%20Calendar-darwin-arm64-1.133.0.zip",
"install_script_ref": "85d6bd1a",
"uninstall_script_ref": "0e018931",
"sha256": "2c336bde3e3ab22a9ac2d2cbbe942947200db874a65a3837bf85c25ddb806371",
"sha256": "3d8b73a890fa1b389535a580e13b7cb73cf8fbd32366ada0d56624b28b7cf1fb",
"default_categories": [
"Productivity"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "0.20.7",
"version": "0.21.0",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.electron.ollama';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.electron.ollama' AND version_compare(bundle_short_version, '0.20.7') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.electron.ollama' AND version_compare(bundle_short_version, '0.21.0') < 0);"
},
"installer_url": "https://github.com/ollama/ollama/releases/download/v0.20.7/Ollama-darwin.zip",
"installer_url": "https://github.com/ollama/ollama/releases/download/v0.21.0/Ollama-darwin.zip",
"install_script_ref": "306a3ea4",
"uninstall_script_ref": "f60ddfee",
"sha256": "74670dafa053a48aef8c7666100cf91f2a3c84fe88cee1a8293e7a7cb3442eea",
"sha256": "700face7ac186443b627895863f5984cd760374dc12ad1dcb6279ae2d6ced7eb",
"default_categories": [
"Developer tools"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "0.20.7",
"version": "0.21.0",
"queries": {
"exists": "SELECT 1 FROM programs WHERE name = 'Ollama' AND publisher = 'Ollama';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Ollama' AND publisher = 'Ollama' AND version_compare(version, '0.20.7') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Ollama' AND publisher = 'Ollama' AND version_compare(version, '0.21.0') < 0);"
},
"installer_url": "https://github.com/ollama/ollama/releases/download/v0.20.7/OllamaSetup.exe",
"installer_url": "https://github.com/ollama/ollama/releases/download/v0.21.0/OllamaSetup.exe",
"install_script_ref": "e14c71ee",
"uninstall_script_ref": "3f049b5d",
"sha256": "eb67a3a654034cccd27bfb90639890a1071b857876a8393128f72e6edb671b0f",
"sha256": "3ab56c0e0a4b2b61e172a1b938fc50b98b0f7ceb4064e9ea81cf3cccb07b0546",
"default_categories": [
"Developer tools"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "2.0.5",
"version": "2.1.1",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'dev.kdrag0n.MacVirt';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'dev.kdrag0n.MacVirt' AND version_compare(bundle_short_version, '2.0.5') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'dev.kdrag0n.MacVirt' AND version_compare(bundle_short_version, '2.1.1') < 0);"
},
"installer_url": "https://cdn-updates.orbstack.dev/arm64/OrbStack_v2.0.5_19905_arm64.dmg",
"installer_url": "https://cdn-updates.orbstack.dev/arm64/OrbStack_v2.1.1_20026_arm64.dmg",
"install_script_ref": "3d018c85",
"uninstall_script_ref": "401d288b",
"sha256": "601889551cdfdc7feee148b7fdb0480fa0ba5c0db0be8f1c047fc840886a7571",
"sha256": "18a41f759958e1fa0951696b820b5478d3ed7353f8ca486fe9d026a1a7d97207",
"default_categories": [
"Developer tools"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "26.3.0",
"version": "26.3.1",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.parallels.desktop.console';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.parallels.desktop.console' AND version_compare(bundle_short_version, '26.3.0') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.parallels.desktop.console' AND version_compare(bundle_short_version, '26.3.1') < 0);"
},
"installer_url": "https://download.parallels.com/desktop/v26/26.3.0-57392/ParallelsDesktop-26.3.0-57392.dmg",
"installer_url": "https://download.parallels.com/desktop/v26/26.3.1-57396/ParallelsDesktop-26.3.1-57396.dmg",
"install_script_ref": "db96404a",
"uninstall_script_ref": "117c49a4",
"sha256": "a554e51976556ff43febf8bb074eca59bdca83ee4b9b4ebebf8111c548e85bba",
"sha256": "ec0207f524578c53350fb017d702f855900900c67738ffdb225f188ad912c503",
"default_categories": [
"Productivity"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "12.6.3",
"version": "12.7.0",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.postmanlabs.mac';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.postmanlabs.mac' AND version_compare(bundle_short_version, '12.6.3') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.postmanlabs.mac' AND version_compare(bundle_short_version, '12.7.0') < 0);"
},
"installer_url": "https://dl.pstmn.io/download/version/12.6.3/osx_arm64",
"installer_url": "https://dl.pstmn.io/download/version/12.7.0/osx_arm64",
"install_script_ref": "b89b1fb9",
"uninstall_script_ref": "15e9f11c",
"sha256": "e03d51e679e895959ee40ef4f827aa227f91634c79ee2d3a3bdfd369b5a6de7b",
"sha256": "c6dc1084cb40cc01edb65d2fb2bcf5e8ceea4fb129a65c0235c25eeed81b7770",
"default_categories": [
"Developer tools"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "12.6.3",
"version": "12.7.0",
"queries": {
"exists": "SELECT 1 FROM programs WHERE name LIKE 'Postman x64 %' AND publisher = 'Postman';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'Postman x64 %' AND publisher = 'Postman' AND version_compare(version, '12.6.3') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name LIKE 'Postman x64 %' AND publisher = 'Postman' AND version_compare(version, '12.7.0') < 0);"
},
"installer_url": "https://dl.pstmn.io/download/version/12.6.3/windows_64",
"installer_url": "https://dl.pstmn.io/download/version/12.7.0/windows_64",
"install_script_ref": "538f63bf",
"uninstall_script_ref": "cd01b68f",
"sha256": "ef677cc7ead3bef96174207d9bb202ec68bf9a66103d355ab40ded3ee81098d3",
"sha256": "077849da6aa3adc674870e2d46209c5fa7e456535f3536af9529027a74cf69a4",
"default_categories": [
"Developer tools"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "4.5.4",
"version": "4.5.5",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.luckymarmot.Paw';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.luckymarmot.Paw' AND version_compare(bundle_short_version, '4.5.4') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.luckymarmot.Paw' AND version_compare(bundle_short_version, '4.5.5') < 0);"
},
"installer_url": "https://cdn-builds.paw.cloud/paw/RapidAPI-4.5.4.zip",
"installer_url": "https://cdn-builds.paw.cloud/paw/RapidAPI-4.5.5.zip",
"install_script_ref": "1c8ec07f",
"uninstall_script_ref": "eb82b992",
"sha256": "cc8953efdde6eb142c294001d4dec30b49d1389513a7cecd7ad87eaf7c1f7991",
"sha256": "d5447b2e3ff87dd870608be55a3b28f2d1833bed2c1fc5e48b2b173768baffbf",
"default_categories": [
"Developer tools"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "5.2.0",
"version": "5.2.1",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.sequelace.SequelAce';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.sequelace.SequelAce' AND version_compare(bundle_short_version, '5.2.0') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.sequelace.SequelAce' AND version_compare(bundle_short_version, '5.2.1') < 0);"
},
"installer_url": "https://github.com/Sequel-Ace/Sequel-Ace/releases/download/production/5.2.0-20099/Sequel-Ace-5.2.0.zip",
"installer_url": "https://github.com/Sequel-Ace/Sequel-Ace/releases/download/production/5.2.1-20100/Sequel-Ace-5.2.1.zip",
"install_script_ref": "a24ed130",
"uninstall_script_ref": "36152630",
"sha256": "17d3866a7d973b13d11792eb2c17141fb1885ab5f6f801e0462961d3faa5d598",
"sha256": "f041ddab14b995b83f0746f6473fa833ecc525a5c08045dc2614217e0258453f",
"default_categories": [
"Developer tools"
]

View file

@ -1,10 +1,10 @@
{
"versions": [
{
"version": "1.2.87.414",
"version": "1.2.87.415",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.spotify.client';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.spotify.client' AND version_compare(bundle_short_version, '1.2.87.414') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.spotify.client' AND version_compare(bundle_short_version, '1.2.87.415') < 0);"
},
"installer_url": "https://download.scdn.co/SpotifyARM64.dmg",
"install_script_ref": "d4b8bdad",

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "1.2.87.414.g4e7a1155",
"version": "1.2.87.415.g88652836",
"queries": {
"exists": "SELECT 1 FROM programs WHERE name = 'Spotify' AND publisher = 'Spotify AB';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Spotify' AND publisher = 'Spotify AB' AND version_compare(version, '1.2.87.414.g4e7a1155') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Spotify' AND publisher = 'Spotify AB' AND version_compare(version, '1.2.87.415.g88652836') < 0);"
},
"installer_url": "https://download.scdn.co/SpotifyFullSetupX64.exe",
"install_script_ref": "7e4727ac",
"uninstall_script_ref": "48d55e3d",
"sha256": "c2e640ed2dbeefcf2f6266659a6a1a03f4110f05e4499b91951755febc9929d6",
"sha256": "c82b19e0f74df1f274e104cb1c8f6c241319ca7e43c78ff789029fcd0fc4db33",
"default_categories": [
"Productivity"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "2.12.9",
"version": "2.12.11",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'eu.exelban.Stats';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'eu.exelban.Stats' AND version_compare(bundle_short_version, '2.12.9') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'eu.exelban.Stats' AND version_compare(bundle_short_version, '2.12.11') < 0);"
},
"installer_url": "https://github.com/exelban/stats/releases/download/v2.12.9/Stats.dmg",
"installer_url": "https://github.com/exelban/stats/releases/download/v2.12.11/Stats.dmg",
"install_script_ref": "3de99bb8",
"uninstall_script_ref": "4222ba77",
"sha256": "0d6d6dde8956a72c597e4e41af07063d07ced2df9a395adcff2a8bc171d89a4e",
"sha256": "41edc5bc9c6a4503f9b48826ea1040ea3b94f76221f0801788c8714d18924093",
"default_categories": [
"Productivity"
]

File diff suppressed because one or more lines are too long

View file

@ -6,7 +6,7 @@
"exists": "SELECT 1 FROM programs WHERE name = 'Telegram Desktop' AND publisher = 'Telegram FZ-LLC';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Telegram Desktop' AND publisher = 'Telegram FZ-LLC' AND version_compare(version, '6.7.6') < 0);"
},
"installer_url": "https://td.telegram.org/tx64/tsetup-x64.6.7.6.exe",
"installer_url": "https://github.com/telegramdesktop/tdesktop/releases/download/v6.7.6/tsetup-x64.6.7.6.exe",
"install_script_ref": "0b88a95e",
"uninstall_script_ref": "42311f1b",
"sha256": "8b77909856093627788a8dca744e48a30fa3f28db2cec80dc1c72cebf83f40b5",

View file

@ -1,12 +1,12 @@
{
"versions": [
{
"version": "0.2026.04.08.08.36.05",
"version": "0.2026.04.15.08.45.02",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'dev.warp.Warp-Stable';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'dev.warp.Warp-Stable' AND version_compare(bundle_short_version, '0.2026.04.08.08.36.05') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'dev.warp.Warp-Stable' AND version_compare(bundle_short_version, '0.2026.04.15.08.45.02') < 0);"
},
"installer_url": "https://releases.warp.dev/stable/v0.2026.04.08.08.36.stable_05/Warp.dmg",
"installer_url": "https://releases.warp.dev/stable/v0.2026.04.15.08.45.stable_02/Warp.dmg",
"install_script_ref": "01373831",
"uninstall_script_ref": "54d05203",
"sha256": "no_check",

View file

@ -1,10 +1,10 @@
{
"versions": [
{
"version": "26.15.20",
"version": "26.16.15",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'net.whatsapp.WhatsApp';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'net.whatsapp.WhatsApp' AND version_compare(bundle_short_version, '26.15.20') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'net.whatsapp.WhatsApp' AND version_compare(bundle_short_version, '26.16.15') < 0);"
},
"installer_url": "https://web.whatsapp.com/desktop/mac_native/release/?configuration=Release&src=whatsapp_downloads_page",
"install_script_ref": "f2b910d2",

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "2.0.50",
"version": "2.0.61",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.exafunction.windsurf';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.exafunction.windsurf' AND version_compare(bundle_short_version, '2.0.50') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.exafunction.windsurf' AND version_compare(bundle_short_version, '2.0.61') < 0);"
},
"installer_url": "https://windsurf-stable.codeiumdata.com/darwin-arm64-dmg/stable/c973f91b37b89375b5b009109c2fe84d185fab48/Windsurf-darwin-arm64-2.0.50.dmg",
"installer_url": "https://windsurf-stable.codeiumdata.com/darwin-arm64-dmg/stable/abcd9c8664da5af505557f3b327b5537400635f2/Windsurf-darwin-arm64-2.0.61.dmg",
"install_script_ref": "c8855980",
"uninstall_script_ref": "461afb53",
"sha256": "4ef3563a37133a12a97cfa26a4febb5ba7877da9abbbfd0897deb2b267c028b0",
"sha256": "53010c8710535ee78f2f28c7afbe94fd8ff2738b0b1b2587c684c42e721dc086",
"default_categories": [
"Developer tools"
]

View file

@ -1,15 +1,15 @@
{
"versions": [
{
"version": "0.232.2",
"version": "0.232.3",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'dev.zed.Zed';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'dev.zed.Zed' AND version_compare(bundle_short_version, '0.232.2') < 0);"
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'dev.zed.Zed' AND version_compare(bundle_short_version, '0.232.3') < 0);"
},
"installer_url": "https://zed.dev/api/releases/stable/0.232.2/Zed-aarch64.dmg",
"installer_url": "https://zed.dev/api/releases/stable/0.232.3/Zed-aarch64.dmg",
"install_script_ref": "b0e5ef67",
"uninstall_script_ref": "a96df5e9",
"sha256": "82717ddea4c03ad033a9c99d1440d1b71d6f6141b02eedd1aa1cb8eb3dcb938f",
"sha256": "2f6ca2b175772e57c1d5b2893f8c8556e16581341f9568ee0ce4f84f5128b488",
"default_categories": [
"Developer tools"
]

View file

@ -1338,7 +1338,7 @@ func (svc *Service) mdmAppleEditedAppleOSUpdates(ctx context.Context, teamID *ui
{LabelName: labelName, LabelID: lblIDs[labelName]},
}
decl, err := svc.ds.SetOrUpdateMDMAppleDeclaration(ctx, d)
decl, err := svc.ds.SetOrUpdateMDMAppleDeclaration(ctx, d, nil)
if err != nil {
return err
}

View file

@ -235,7 +235,7 @@ func TestGetOrCreatePreassignTeam(t *testing.T) {
require.ElementsMatch(t, names, []string{fleet.BuiltinLabelMacOS14Plus})
return map[string]uint{names[0]: 1}, nil
}
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration) (*fleet.MDMAppleDeclaration, error) {
ds.SetOrUpdateMDMAppleDeclarationFunc = func(ctx context.Context, declaration *fleet.MDMAppleDeclaration, usesFleetVars []fleet.FleetVarName) (*fleet.MDMAppleDeclaration, error) {
declaration.DeclarationUUID = uuid.NewString()
return declaration, nil
}

View file

@ -29,6 +29,7 @@ interface IActionsDropdownProps {
menuAlign?: "right" | "left" | "default";
menuPlacement?: "top" | "bottom" | "auto";
variant?: "button" | "brand-button" | "small-button";
buttonLabel?: string;
}
const getOptionBackgroundColor = (state: { isFocused: boolean }) => {
@ -122,6 +123,7 @@ const ActionsDropdown = ({
menuAlign = "default",
menuPlacement = "bottom",
variant,
buttonLabel,
}: IActionsDropdownProps): JSX.Element => {
const dropdownClassnames = classnames(baseClass, className);
@ -161,7 +163,7 @@ const ActionsDropdown = ({
aria-haspopup="listbox"
aria-expanded={menuIsOpen}
>
<span>Actions</span>
<span>{buttonLabel || "Actions"}</span>
<Icon
name="chevron-down"
color="core-fleet-white"

View file

@ -6,6 +6,16 @@
display: flex;
flex-direction: column;
gap: $pad-medium;
// Hardcoded to fit all 3 custom target options (Exclude any, Include all,
// Include any) without scrolling
.Select-menu-outer {
max-height: 260px;
}
.Select-menu {
max-height: 244px;
}
}
&__checkboxes {

View file

@ -0,0 +1,12 @@
export interface IApiEndpointRef {
method: string;
path: string;
}
export interface IApiEndpoint extends IApiEndpointRef {
display_name: string;
deprecated: boolean;
}
/** Unique key for an endpoint since there's no `id` field */
export const endpointKey = (ep: IApiEndpointRef) => `${ep.method} ${ep.path}`;

View file

@ -1,6 +1,7 @@
import PropTypes from "prop-types";
import teamInterface, { ITeam } from "./team";
import { IUserSettings } from "./config";
import { IApiEndpointRef } from "./api_endpoint";
export default PropTypes.shape({
created_at: PropTypes.string,
@ -59,6 +60,7 @@ export interface IUser {
api_only: boolean;
teams: ITeam[];
fleets: ITeam[]; // This will eventually replace `teams`, but for now we need both to avoid breaking changes.
api_endpoints?: IApiEndpointRef[];
}
/**
@ -80,6 +82,8 @@ export interface IUserFormErrors {
name?: string | null;
password?: string | null;
sso_enabled?: boolean | null;
api_endpoints?: string | null;
teams?: string | null;
}
export interface IResetPasswordFormErrors {
new_password?: string | null;
@ -97,7 +101,7 @@ export interface ILoginUserData {
}
export interface ICreateUserFormData {
email: string;
email?: string;
global_role: UserRole | null;
name: string;
password?: string | null;

File diff suppressed because one or more lines are too long

View file

@ -10,6 +10,7 @@ import BetterDisplay from "./BetterDisplay";
import Charles from "./Charles";
import ConnectFonts from "./ConnectFonts";
import CrashPlan from "./CrashPlan";
import DruvaInSync from "./DruvaInSync";
import GoogleCredentialProviderForWindows from "./GoogleCredentialProviderForWindows";
import Iina from "./Iina";
import Kitty from "./Kitty";
@ -316,6 +317,7 @@ export const SOFTWARE_NAME_TO_ICON_MAP = {
crashplan: CrashPlan,
"google credential provider for windows": GoogleCredentialProviderForWindows,
iina: Iina,
insyncclient: DruvaInSync,
kitty: Kitty,
krita: Krita,
lastpass: LastPass,

View file

@ -188,19 +188,34 @@ export const CUSTOM_TARGET_OPTIONS: IDropdownOption[] = [
{
value: "labelsIncludeAny",
label: "Include any",
helpText: "Hosts that have any of the selected labels.",
helpText: (
<>
Software will only be available for install on hosts that{" "}
<strong>have any</strong> of these labels.
</>
),
disabled: false,
},
{
value: "labelsIncludeAll",
label: "Include all",
helpText: "Hosts that have all of the selected labels.",
helpText: (
<>
Software will only be available for install on hosts that{" "}
<strong>have all</strong> of these labels.
</>
),
disabled: false,
},
{
value: "labelsExcludeAny",
label: "Exclude any",
helpText: "Hosts that don't have any of the selected labels.",
helpText: (
<>
Software will only be available for install on hosts that{" "}
<strong>don&apos;t have any</strong> of these labels.
</>
),
disabled: false,
},
];

View file

@ -301,64 +301,68 @@ const Calendars = ({ appConfig }: IAppConfigFormProps): JSX.Element => {
work calendar.)
</li>
<li>
Save your changes.
<Card>
<form onSubmit={onFormSubmit} autoComplete="off">
<InputField
label="API key JSON"
onChange={onInputChange}
name="apiKeyJson"
value={apiKeyJson}
parseTarget
type="textarea"
placeholder={API_KEY_JSON_PLACEHOLDER}
ignore1password
inputClassName={`${baseClass}__api-key-json`}
error={formErrors.apiKeyJson}
disabled={gomEnabled}
helpText={
apiKeyJson === UNCHANGED_PASSWORD_API_RESPONSE
? "API key is configured. Replace with a new key to update."
: undefined
}
/>
<InputField
label="Primary domain"
onChange={onInputChange}
name="domain"
value={domain}
parseTarget
placeholder="example.com"
helpText={
<>
You can find your primary domain in Google Workspace{" "}
<CustomLink
url={GOOGLE_WORKSPACE_DOMAINS}
text="here"
newTab
/>
</>
}
error={formErrors.domain}
disabled={gomEnabled}
/>
<div className="button-wrap">
<GitOpsModeTooltipWrapper
tipOffset={8}
renderChildren={(dC) => (
<Button
type="submit"
disabled={Object.keys(formErrors).length > 0 || dC}
className="save-loading"
isLoading={isUpdatingSettings}
>
Save
</Button>
)}
<div className={`${baseClass}__save-changes`}>
Save your changes.
<Card>
<form onSubmit={onFormSubmit} autoComplete="off">
<InputField
label="API key JSON"
onChange={onInputChange}
name="apiKeyJson"
value={apiKeyJson}
parseTarget
type="textarea"
placeholder={API_KEY_JSON_PLACEHOLDER}
ignore1password
inputClassName={`${baseClass}__api-key-json`}
error={formErrors.apiKeyJson}
disabled={gomEnabled}
helpText={
apiKeyJson === UNCHANGED_PASSWORD_API_RESPONSE
? "API key is configured. Replace with a new key to update."
: undefined
}
/>
</div>
</form>
</Card>
<InputField
label="Primary domain"
onChange={onInputChange}
name="domain"
value={domain}
parseTarget
placeholder="example.com"
helpText={
<>
You can find your primary domain in Google Workspace{" "}
<CustomLink
url={GOOGLE_WORKSPACE_DOMAINS}
text="here"
newTab
/>
</>
}
error={formErrors.domain}
disabled={gomEnabled}
/>
<div className="button-wrap">
<GitOpsModeTooltipWrapper
tipOffset={8}
renderChildren={(dC) => (
<Button
type="submit"
disabled={
Object.keys(formErrors).length > 0 || dC
}
className="save-loading"
isLoading={isUpdatingSettings}
>
Save
</Button>
)}
/>
</div>
</form>
</Card>
</div>
</li>
</ul>
</p>
@ -389,15 +393,16 @@ const Calendars = ({ appConfig }: IAppConfigFormProps): JSX.Element => {
account.
</li>
<li>
For the OAuth scopes, paste the following value:
<InputField
readOnly
inputWrapperClass={`${baseClass}__oauth-scopes`}
name="oauth-scopes"
enableCopy
type="textarea"
value={OAUTH_SCOPES}
/>
<div className={`${baseClass}__oauth-scopes`}>
For the OAuth scopes, paste the following value:
<InputField
readOnly
name="oauth-scopes"
enableCopy
type="textarea"
value={OAUTH_SCOPES}
/>
</div>
</li>
<li>
Click <b>Authorize</b>.

View file

@ -19,10 +19,6 @@
margin: $pad-small 0;
}
.card {
margin-top: $pad-small;
}
&__configuration {
button {
align-self: flex-end;
@ -36,12 +32,18 @@
font-size: $x-small;
}
&__save-changes,
&__oauth-scopes {
@include vertical-form-layout;
padding-bottom: $pad-large;
}
#oauth-scopes {
font-family: "SourceCodePro", $monospace;
color: $core-fleet-black;
min-height: 82px;
min-width: 100%;
padding: $pad-medium;
padding-right: $pad-xxlarge;
resize: none;
}

View file

@ -9,6 +9,6 @@
&__learn-more-link {
// used to keep the "Learn more" text content on a single line.
min-width: 88px;
min-width: max-content;
}
}

View file

@ -233,7 +233,6 @@ const AppleBusinessManagerPage = ({ router }: { router: InjectedRouter }) => {
{showRenewModal && selectedToken.current && (
<RenewAbmModal
tokenId={selectedToken.current.id}
orgName={selectedToken.current.org_name}
onCancel={onCancelRenewToken}
onRenewedToken={onRenewed}
/>

View file

@ -52,73 +52,15 @@ const AddAbmModal = ({ onCancel, onAdded }: IAddAbmModalProps) => {
return (
<Modal className={baseClass} title="Add AB" onExit={onCancel} width="large">
<ol className={`${baseClass}__setup-list`}>
<li>
<span>1.</span>
<p>
Download your public key. <DownloadABMKey baseClass={baseClass} />
</p>
</li>
<li>
<span>2.</span>
<span>
<span>
Sign in to{" "}
<CustomLink
newTab
text="Apple Business"
url="https://business.apple.com"
/>
<br />
If your organization doesn&apos;t have an account, select{" "}
<b>Enroll now</b>.
</span>
</span>
</li>
<li>
<span>3.</span>
<span>
Select your <b>account name</b> at the bottom left of the screen,
then select <b>Preferences</b>.
</span>
</li>
<li>
<span>4.</span>
<span>
In the <b>Your MDM Servers</b> section, select <b>Add</b>.
</span>
</li>
<li>
<span>5.</span>
<span>Enter a name for the server such as &quot;Fleet&quot;.</span>
</li>
<li>
<span>6.</span>
<span>
Under <b>MDM Server Settings</b>, upload the public key downloaded
in the first step and select <b>Save</b>.
</span>
</li>
<li>
<span>7.</span>
<span>
In the <b>Default Device Assignment</b> section, select{" "}
<b>Change</b>, then assign the newly created server as the default
for your Macs, iPhones, and iPads. Then select <b>Done</b>.
</span>
</li>
<li>
<span>8.</span>
<span>
Select newly created server in the sidebar, then select{" "}
<b>Download MDM Server Token</b> on the top.
</span>
</li>
<li>
<span>9.</span>
<span>Upload the downloaded token (.p7m file).</span>
</li>
</ol>
<p>
Follow the step-by-step guide to connect Fleet to Apple Business
Manager.{" "}
<CustomLink
url="https://fleetdm.com/learn-more-about/setup-abm"
text="Learn how"
newTab
/>
</p>
<FileUploader
className={`${baseClass}__file-uploader ${
isUploading ? `${baseClass}__file-uploader--loading` : ""
@ -139,6 +81,7 @@ const AddAbmModal = ({ onCancel, onAdded }: IAddAbmModalProps) => {
>
Add AB
</Button>
<DownloadABMKey baseClass={baseClass} />
</div>
</Modal>
);

View file

@ -1,10 +1,13 @@
.add-abm-modal {
p {
margin: 0;
}
&__request-button {
display: flex;
gap: $pad-small;
align-items: center;
margin-top: $pad-small;
label {
display: flex;
@ -13,33 +16,8 @@
}
}
&__setup-list {
font-size: $x-small;
display: flex;
flex-direction: column;
gap: $pad-large;
padding: 0;
margin: 0;
max-width: 660px;
list-style: none;
li {
display: flex;
flex-direction: row;
gap: $pad-small;
p {
display: flex;
flex-direction: column;
align-items: flex-start;
margin: 0;
}
}
}
&__file-uploader {
margin-top: $pad-medium;
margin-left: $pad-medium;
.file-uploader__message {
color: $ui-fleet-black-75;

View file

@ -14,14 +14,12 @@ const baseClass = "renew-abm-modal";
interface IRenewAbmModalProps {
tokenId: number;
orgName: string;
onCancel: () => void;
onRenewedToken: () => void;
}
const RenewAbmModal = ({
tokenId,
orgName,
onCancel,
onRenewedToken,
}: IRenewAbmModalProps) => {
@ -65,31 +63,24 @@ const RenewAbmModal = ({
width="large"
>
<div className={`${baseClass}__page-content ${baseClass}__setup-content`}>
<p className={`${baseClass}__description`}>
Renew Apple Business for <b>{orgName}</b> by uploading your AB token.{" "}
<p>
Follow the step-by-step guide to renew.{" "}
<CustomLink
url="https://fleetdm.com/learn-more-about/renew-abm"
text="Learn how"
newTab
text="Learn more"
url="https://fleetdm.com/guides/apple-mdm-setup#to-renew-an-abm-token"
/>
</p>
<ul className={`${baseClass}__setup-instructions-list`}>
<li>
<p>
Upload the downloaded token (.p7m file) below.
<FileUploader
className={`${baseClass}__file-uploader`}
accept=".p7m"
buttonMessage="Choose file"
buttonType="brand-inverse-icon"
graphicName="file-p7m"
message="AB token (.p7m)"
onFileUpload={onSelectFile}
fileDetails={tokenFile ? { name: tokenFile.name } : undefined}
/>
</p>
</li>
</ul>
<FileUploader
className={`${baseClass}__file-uploader`}
accept=".p7m"
buttonMessage="Choose file"
buttonType="brand-inverse-icon"
graphicName="file-p7m"
message="AB token (.p7m)"
onFileUpload={onSelectFile}
fileDetails={tokenFile ? { name: tokenFile.name } : undefined}
/>
<div className="modal-cta-wrap">
<Button
className={`${baseClass}__submit-button ${

View file

@ -3,7 +3,7 @@
&__setup-content {
display: flex;
flex-direction: column;
gap: $pad-large;
gap: $pad-medium;
color: $core-fleet-black;
p {
@ -11,25 +11,6 @@
}
}
&__setup-instructions-list {
padding: 0;
margin: 0;
list-style: none;
display: flex;
flex-direction: column;
gap: $pad-large;
li > p {
margin: 0;
}
}
&__file-uploader {
margin-top: $pad-medium;
margin-left: $pad-medium;
}
&__button-wrap {
display: flex;
justify-content: flex-end;

View file

@ -210,7 +210,6 @@ const VppPage = ({ router }: IVppPageProps) => {
{showRenewModal && selectedToken.current && (
<RenewVppModal
tokenId={selectedToken.current.id}
orgName={selectedToken.current.org_name}
onCancel={onCancelRenewToken}
onRenewedToken={onRenewed}
/>

View file

@ -5,9 +5,9 @@ import mdmAppleAPI from "services/entities/mdm_apple";
import Modal from "components/Modal";
import Button from "components/buttons/Button";
import CustomLink from "components/CustomLink";
import FileUploader from "components/FileUploader";
import VppSetupSteps from "../VppSetupSteps";
import { getErrorMessage } from "./helpers";
const baseClass = "add-vpp-modal";
@ -57,7 +57,14 @@ const AddVppModal = ({ onCancel, onAdded }: IAddVppModalProps) => {
onExit={onCancel}
width="large"
>
<VppSetupSteps extendendSteps />
<p className={`${baseClass}__description`}>
Follow the step-by-step guide to add VPP.{" "}
<CustomLink
url="https://fleetdm.com/learn-more-about/add-vpp"
text="Learn how"
newTab
/>
</p>
<FileUploader
className={`${baseClass}__file-uploader ${
isUploading ? `${baseClass}__file-uploader--loading` : ""

View file

@ -1,5 +1,9 @@
.add-vpp-modal {
&__description {
margin: 0;
}
&__request-button {
display: flex;
gap: $pad-small;
@ -39,7 +43,6 @@
&__file-uploader {
margin-top: $pad-medium;
margin-left: $pad-medium;
.file-uploader__message {
color: $ui-fleet-black-75;

View file

@ -5,23 +5,21 @@ import { NotificationContext } from "context/notification";
import mdmAppleAPI from "services/entities/mdm_apple";
import Button from "components/buttons/Button";
import CustomLink from "components/CustomLink";
import { FileUploader } from "components/FileUploader/FileUploader";
import Modal from "components/Modal";
import VppSetupSteps from "../VppSetupSteps";
import { getErrorMessage } from "./helpers";
const baseClass = "modal renew-vpp-modal";
interface IRenewVppModalProps {
tokenId: number;
orgName: string;
onCancel: () => void;
onRenewedToken: () => void;
}
const RenewVppModal = ({
tokenId,
orgName,
onCancel,
onRenewedToken,
}: IRenewVppModalProps) => {
@ -68,9 +66,13 @@ const RenewVppModal = ({
width="large"
>
<p className={`${baseClass}__description`}>
Renew Volume Purchasing Program for <b>{orgName}</b> location.
Follow the step-by-step guide to renew.{" "}
<CustomLink
url="https://fleetdm.com/learn-more-about/renew-vpp"
text="Learn how"
newTab
/>
</p>
<VppSetupSteps />
<FileUploader
className={`${baseClass}__file-uploader`}
accept=".vpptoken"

View file

@ -1,11 +1,10 @@
.renew-vpp-modal {
&__description {
margin: 0 0 $pad-large;
margin: 0;
}
&__file-uploader {
margin-top: $pad-medium;
margin-left: $pad-medium;
}
}

View file

@ -1,67 +0,0 @@
import CustomLink from "components/CustomLink";
import React from "react";
const baseClass = "vpp-setup-steps";
interface IVppSetupStepsProps {
/** This prop is used to display additional setup steps content. We have this
* because some places that use this component show additional content.
*/
extendendSteps?: boolean;
}
const VppSetupSteps = ({ extendendSteps = false }: IVppSetupStepsProps) => {
return (
<ol className={baseClass}>
<li>
<span>1.</span>
<p>
Sign in to{" "}
<CustomLink
newTab
url="https://business.apple.com"
text="Apple Business"
/>
{extendendSteps && (
<>
<br />
If your organization doesn&apos;t have an account, select{" "}
<b>Sign up now</b>.
</>
)}
</p>
</li>
<li>
<span>2.</span>
<p>
Select your <b>account name</b> at the bottom left of the screen, then
select <b>Preferences</b>.
</p>
</li>
<li>
<span>3.</span>
<p>
Select <b>Payments and Billing</b> in the menu.
</p>
</li>
<li>
<span>4.</span>
<p>
Under the <b>Content Tokens</b>, download the token for the location
you want to use.
{extendendSteps && (
<>
<br /> Each token is based on a location in Apple Business.
</>
)}
</p>
</li>
<li>
<span>5.</span>
<p>Upload content token (.vpptoken file) below.</p>
</li>
</ol>
);
};
export default VppSetupSteps;

Some files were not shown because too many files have changed in this diff Show more