fleet/server/service/apple_mdm_test.go

2589 lines
84 KiB
Go
Raw Normal View History

Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
package service
import (
"bytes"
"context"
"crypto/tls"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
"net/http"
"net/http/httptest"
"os"
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
"strings"
"sync/atomic"
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
"testing"
"github.com/fleetdm/fleet/v4/server/authz"
"github.com/fleetdm/fleet/v4/server/config"
"github.com/fleetdm/fleet/v4/server/contexts/license"
"github.com/fleetdm/fleet/v4/server/contexts/viewer"
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
"github.com/fleetdm/fleet/v4/server/fleet"
apple_mdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
"github.com/fleetdm/fleet/v4/server/mdm/apple/mobileconfig"
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
"github.com/fleetdm/fleet/v4/server/mock"
nanodep_mock "github.com/fleetdm/fleet/v4/server/mock/nanodep"
nanomdm_mock "github.com/fleetdm/fleet/v4/server/mock/nanomdm"
"github.com/fleetdm/fleet/v4/server/ptr"
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
"github.com/fleetdm/fleet/v4/server/test"
kitlog "github.com/go-kit/kit/log"
"github.com/google/uuid"
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
nanodep_client "github.com/micromdm/nanodep/client"
"github.com/micromdm/nanomdm/mdm"
nanomdm_pushsvc "github.com/micromdm/nanomdm/push/service"
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
"github.com/stretchr/testify/require"
)
func setupAppleMDMService(t *testing.T, license *fleet.LicenseInfo) (fleet.Service, context.Context, *mock.Store) {
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
ds := new(mock.Store)
cfg := config.TestConfig()
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch {
case strings.Contains(r.URL.Path, "/server/devices"):
_, err := w.Write([]byte("{}"))
require.NoError(t, err)
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
return
case strings.Contains(r.URL.Path, "/session"):
_, err := w.Write([]byte(`{"auth_session_token": "yoo"}`))
require.NoError(t, err)
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
return
}
}))
mdmStorage := &nanomdm_mock.Storage{}
depStorage := &nanodep_mock.Storage{}
pushFactory, _ := newMockAPNSPushProviderFactory()
pusher := nanomdm_pushsvc.New(
mdmStorage,
mdmStorage,
pushFactory,
NewNanoMDMLogger(kitlog.NewJSONLogger(os.Stdout)),
)
opts := &TestServerOpts{
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
FleetConfig: &cfg,
MDMStorage: mdmStorage,
DEPStorage: depStorage,
MDMPusher: pusher,
License: license,
}
svc, ctx := newTestServiceWithConfig(t, ds, cfg, nil, nil, opts)
mdmStorage.EnqueueCommandFunc = func(ctx context.Context, id []string, cmd *mdm.Command) (map[string]error, error) {
return nil, nil
}
mdmStorage.RetrievePushInfoFunc = func(ctx context.Context, tokens []string) (map[string]*mdm.Push, error) {
res := make(map[string]*mdm.Push, len(tokens))
for _, t := range tokens {
res[t] = &mdm.Push{
PushMagic: "",
Token: []byte(t),
Topic: "",
}
}
return res, nil
}
mdmStorage.RetrievePushCertFunc = func(ctx context.Context, topic string) (*tls.Certificate, string, error) {
cert, err := tls.LoadX509KeyPair("testdata/server.pem", "testdata/server.key")
return &cert, "", err
}
mdmStorage.IsPushCertStaleFunc = func(ctx context.Context, topic string, staleToken string) (bool, error) {
return false, nil
}
depStorage.RetrieveAuthTokensFunc = func(ctx context.Context, name string) (*nanodep_client.OAuth1Tokens, error) {
return &nanodep_client.OAuth1Tokens{}, nil
}
depStorage.RetrieveConfigFunc = func(context.Context, string) (*nanodep_client.Config, error) {
return &nanodep_client.Config{
BaseURL: ts.URL,
}, nil
}
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return &fleet.AppConfig{
OrgInfo: fleet.OrgInfo{
OrgName: "Foo Inc.",
},
ServerSettings: fleet.ServerSettings{
ServerURL: "https://foo.example.com",
},
MDM: fleet.MDM{
EnabledAndConfigured: true,
},
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
}, nil
}
ds.GetMDMAppleEnrollmentProfileByTokenFunc = func(ctx context.Context, token string) (*fleet.MDMAppleEnrollmentProfile, error) {
return nil, nil
}
ds.NewMDMAppleEnrollmentProfileFunc = func(ctx context.Context, enrollmentPayload fleet.MDMAppleEnrollmentProfilePayload) (*fleet.MDMAppleEnrollmentProfile, error) {
return &fleet.MDMAppleEnrollmentProfile{
ID: 1,
Token: "foo",
Type: fleet.MDMAppleEnrollmentTypeManual,
EnrollmentURL: "https://foo.example.com?token=foo",
}, nil
}
ds.GetMDMAppleEnrollmentProfileByTokenFunc = func(ctx context.Context, token string) (*fleet.MDMAppleEnrollmentProfile, error) {
return nil, nil
}
ds.ListMDMAppleEnrollmentProfilesFunc = func(ctx context.Context) ([]*fleet.MDMAppleEnrollmentProfile, error) {
return nil, nil
}
ds.NewMDMAppleInstallerFunc = func(ctx context.Context, name string, size int64, manifest string, installer []byte, urlToken string) (*fleet.MDMAppleInstaller, error) {
return nil, nil
}
ds.MDMAppleInstallerFunc = func(ctx context.Context, token string) (*fleet.MDMAppleInstaller, error) {
return nil, nil
}
ds.MDMAppleInstallerDetailsByIDFunc = func(ctx context.Context, id uint) (*fleet.MDMAppleInstaller, error) {
return nil, nil
}
ds.DeleteMDMAppleInstallerFunc = func(ctx context.Context, id uint) error {
return nil
}
ds.MDMAppleInstallerDetailsByTokenFunc = func(ctx context.Context, token string) (*fleet.MDMAppleInstaller, error) {
return nil, nil
}
ds.ListMDMAppleInstallersFunc = func(ctx context.Context) ([]fleet.MDMAppleInstaller, error) {
return nil, nil
}
ds.MDMAppleListDevicesFunc = func(ctx context.Context) ([]fleet.MDMAppleDevice, error) {
return nil, nil
}
ds.GetNanoMDMEnrollmentFunc = func(ctx context.Context, hostUUID string) (*fleet.NanoEnrollment, error) {
return &fleet.NanoEnrollment{Enabled: false}, nil
}
ds.GetMDMAppleCommandRequestTypeFunc = func(ctx context.Context, commandUUID string) (string, error) {
return "", nil
}
ds.MDMAppleGetEULAMetadataFunc = func(ctx context.Context) (*fleet.MDMAppleEULA, error) {
return &fleet.MDMAppleEULA{}, nil
}
ds.MDMAppleGetEULABytesFunc = func(ctx context.Context, token string) (*fleet.MDMAppleEULA, error) {
return &fleet.MDMAppleEULA{}, nil
}
ds.MDMAppleInsertEULAFunc = func(ctx context.Context, eula *fleet.MDMAppleEULA) error {
return nil
}
ds.MDMAppleDeleteEULAFunc = func(ctx context.Context, token string) error {
return nil
}
return svc, ctx, ds
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
}
func TestAppleMDMAuthorization(t *testing.T) {
svc, ctx, ds := setupAppleMDMService(t, &fleet.LicenseInfo{Tier: fleet.TierPremium})
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
checkAuthErr := func(t *testing.T, err error, shouldFailWithAuth bool) {
t.Helper()
if shouldFailWithAuth {
require.Error(t, err)
require.Contains(t, err.Error(), authz.ForbiddenErrorMessage)
} else {
require.NoError(t, err)
}
}
testAuthdMethods := func(t *testing.T, user *fleet.User, shouldFailWithAuth bool) {
ctx := test.UserContext(ctx, user)
_, err := svc.UploadMDMAppleInstaller(ctx, "foo", 3, bytes.NewReader([]byte("foo")))
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
checkAuthErr(t, err, shouldFailWithAuth)
_, err = svc.GetMDMAppleInstallerByID(ctx, 42)
checkAuthErr(t, err, shouldFailWithAuth)
err = svc.DeleteMDMAppleInstaller(ctx, 42)
checkAuthErr(t, err, shouldFailWithAuth)
_, err = svc.ListMDMAppleInstallers(ctx)
checkAuthErr(t, err, shouldFailWithAuth)
_, err = svc.ListMDMAppleDevices(ctx)
checkAuthErr(t, err, shouldFailWithAuth)
_, err = svc.ListMDMAppleDEPDevices(ctx)
checkAuthErr(t, err, shouldFailWithAuth)
// check EULA routes
_, err = svc.MDMAppleGetEULAMetadata(ctx)
checkAuthErr(t, err, shouldFailWithAuth)
err = svc.MDMAppleCreateEULA(ctx, "eula.pdf", bytes.NewReader([]byte("%PDF-")))
checkAuthErr(t, err, shouldFailWithAuth)
err = svc.MDMAppleDeleteEULA(ctx, "foo")
checkAuthErr(t, err, shouldFailWithAuth)
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
}
// Only global admins can access the endpoints.
testAuthdMethods(t, test.UserAdmin, false)
// All other users should not have access to the endpoints.
for _, user := range []*fleet.User{
test.UserNoRoles,
test.UserMaintainer,
test.UserObserver,
test.UserObserverPlus,
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
test.UserTeamAdminTeam1,
} {
testAuthdMethods(t, user, true)
}
// Token authenticated endpoints can be accessed by anyone.
ctx = test.UserContext(ctx, test.UserNoRoles)
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
_, err := svc.GetMDMAppleInstallerByToken(ctx, "foo")
require.NoError(t, err)
_, err = svc.GetMDMAppleEnrollmentProfileByToken(ctx, "foo", "")
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
require.NoError(t, err)
_, err = svc.GetMDMAppleInstallerDetailsByToken(ctx, "foo")
require.NoError(t, err)
_, err = svc.MDMAppleGetEULABytes(ctx, "foo")
require.NoError(t, err)
2022-12-19 13:37:08 +00:00
// Generating a new key pair does not actually make any changes to fleet, or expose any
// information. The user must configure fleet with the new key pair and restart the server.
_, err = svc.NewMDMAppleDEPKeyPair(ctx)
require.NoError(t, err)
// Must be device-authenticated, should fail
_, err = svc.GetDeviceMDMAppleEnrollmentProfile(ctx)
checkAuthErr(t, err, true)
// works with device-authenticated context
ctx = test.HostContext(context.Background(), &fleet.Host{})
_, err = svc.GetDeviceMDMAppleEnrollmentProfile(ctx)
require.NoError(t, err)
hostUUIDsToTeamID := map[string]uint{
"host1": 1,
"host2": 1,
"host3": 2,
"host4": 0,
}
ds.ListHostsLiteByUUIDsFunc = func(ctx context.Context, filter fleet.TeamFilter, uuids []string) ([]*fleet.Host, error) {
hosts := make([]*fleet.Host, 0, len(uuids))
for _, uuid := range uuids {
tmID := hostUUIDsToTeamID[uuid]
if tmID == 0 {
hosts = append(hosts, &fleet.Host{UUID: uuid, TeamID: nil})
} else {
hosts = append(hosts, &fleet.Host{UUID: uuid, TeamID: &tmID})
}
}
return hosts, nil
}
rawB64FreeCmd := base64.RawStdEncoding.EncodeToString([]byte(`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Command</key>
<dict>
<key>RequestType</key>
<string>FooBar</string>
</dict>
<key>CommandUUID</key>
<string>uuid</string>
</dict>
</plist>`))
t.Run("EnqueueMDMAppleCommand", func(t *testing.T) {
enqueueCmdCases := []struct {
desc string
user *fleet.User
uuids []string
shoudFailWithAuth bool
}{
{"no role", test.UserNoRoles, []string{"host1", "host2", "host3", "host4"}, true},
{"maintainer can run", test.UserMaintainer, []string{"host1", "host2", "host3", "host4"}, false},
{"admin can run", test.UserAdmin, []string{"host1", "host2", "host3", "host4"}, false},
{"observer cannot run", test.UserObserver, []string{"host1", "host2", "host3", "host4"}, true},
{"team 1 admin can run team 1", test.UserTeamAdminTeam1, []string{"host1", "host2"}, false},
{"team 2 admin can run team 2", test.UserTeamAdminTeam2, []string{"host3"}, false},
{"team 1 maintainer can run team 1", test.UserTeamMaintainerTeam1, []string{"host1", "host2"}, false},
{"team 1 observer cannot run team 1", test.UserTeamObserverTeam1, []string{"host1", "host2"}, true},
{"team 1 admin cannot run team 2", test.UserTeamAdminTeam1, []string{"host3"}, true},
{"team 1 admin cannot run no team", test.UserTeamAdminTeam1, []string{"host4"}, true},
{"team 1 admin cannot run mix of team 1 and 2", test.UserTeamAdminTeam1, []string{"host1", "host3"}, true},
}
for _, c := range enqueueCmdCases {
t.Run(c.desc, func(t *testing.T) {
ctx = test.UserContext(ctx, c.user)
Add `TestMDMClient` to simulate MDM clients in osquery-perf (#11672) #11528 osquery-perf simulated hosts enroll and are identified as manually enrolled. (Enrolling as DEP requires more work, e.g. a new mocked Apple DEP endpoint). Given that these are simulated MDM clients, they cannot be woken up with push notifications. Instead, these check for new commands to execute every 10 seconds (which is not realistic, but could serve as a good loadtesting exercise). I will now start setting up the loadtest environment with MDM enabled and configured to test this. - ~[ ] Changes file added for user-visible changes in `changes/` or `orbit/changes/`. See [Changes files](https://fleetdm.com/docs/contributing/committing-changes#changes-files) for more information.~ - ~[ ] Documented any API changes (docs/Using-Fleet/REST-API.md or docs/Contributing/API-for-contributors.md)~ - ~[ ] Documented any permissions changes~ - ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements)~ - [X] Added support on fleet's osquery simulator `cmd/osquery-perf` for new osquery data ingestion features. - [X] Added/updated tests - [X] Manual QA for all new/changed functionality - ~For Orbit and Fleet Desktop changes:~ - ~[ ] Manual QA must be performed in the three main OSs, macOS, Windows and Linux.~ - ~[ ] Auto-update manual QA, from released version of component to new version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-05-12 16:50:20 +00:00
_, _, err = svc.EnqueueMDMAppleCommand(ctx, rawB64FreeCmd, c.uuids)
checkAuthErr(t, err, c.shoudFailWithAuth)
})
}
// test with a command that requires a premium license
ctx = test.UserContext(ctx, test.UserAdmin)
ctx = license.NewContext(ctx, &fleet.LicenseInfo{Tier: fleet.TierFree})
rawB64PremiumCmd := base64.RawStdEncoding.EncodeToString([]byte(fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Command</key>
<dict>
<key>RequestType</key>
<string>%s</string>
</dict>
<key>CommandUUID</key>
<string>uuid</string>
</dict>
</plist>`, "DeviceLock")))
Add `TestMDMClient` to simulate MDM clients in osquery-perf (#11672) #11528 osquery-perf simulated hosts enroll and are identified as manually enrolled. (Enrolling as DEP requires more work, e.g. a new mocked Apple DEP endpoint). Given that these are simulated MDM clients, they cannot be woken up with push notifications. Instead, these check for new commands to execute every 10 seconds (which is not realistic, but could serve as a good loadtesting exercise). I will now start setting up the loadtest environment with MDM enabled and configured to test this. - ~[ ] Changes file added for user-visible changes in `changes/` or `orbit/changes/`. See [Changes files](https://fleetdm.com/docs/contributing/committing-changes#changes-files) for more information.~ - ~[ ] Documented any API changes (docs/Using-Fleet/REST-API.md or docs/Contributing/API-for-contributors.md)~ - ~[ ] Documented any permissions changes~ - ~[ ] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements)~ - [X] Added support on fleet's osquery simulator `cmd/osquery-perf` for new osquery data ingestion features. - [X] Added/updated tests - [X] Manual QA for all new/changed functionality - ~For Orbit and Fleet Desktop changes:~ - ~[ ] Manual QA must be performed in the three main OSs, macOS, Windows and Linux.~ - ~[ ] Auto-update manual QA, from released version of component to new version (see [tools/tuf/test](../tools/tuf/test/README.md)).~
2023-05-12 16:50:20 +00:00
_, _, err = svc.EnqueueMDMAppleCommand(ctx, rawB64PremiumCmd, []string{"host1"})
require.Error(t, err)
require.ErrorContains(t, err, fleet.ErrMissingLicense.Error())
})
cmdUUIDToHostUUIDs := map[string][]string{
"uuidTm1": {"host1", "host2"},
"uuidTm2": {"host3"},
"uuidNoTm": {"host4"},
"uuidMixTm1Tm2": {"host1", "host3"},
}
ds.GetMDMAppleCommandResultsFunc = func(ctx context.Context, commandUUID string) ([]*fleet.MDMAppleCommandResult, error) {
hosts := cmdUUIDToHostUUIDs[commandUUID]
res := make([]*fleet.MDMAppleCommandResult, 0, len(hosts))
for _, h := range hosts {
res = append(res, &fleet.MDMAppleCommandResult{
DeviceID: h,
})
}
return res, nil
}
t.Run("GetMDMAppleCommandResults", func(t *testing.T) {
cmdResultsCases := []struct {
desc string
user *fleet.User
cmdUUID string
shoudFailWithAuth bool
}{
{"no role", test.UserNoRoles, "uuidTm1", true},
{"maintainer can view", test.UserMaintainer, "uuidTm1", false},
{"maintainer can view", test.UserMaintainer, "uuidTm2", false},
{"maintainer can view", test.UserMaintainer, "uuidNoTm", false},
{"maintainer can view", test.UserMaintainer, "uuidMixTm1Tm2", false},
{"observer can view", test.UserObserver, "uuidTm1", false},
{"observer can view", test.UserObserver, "uuidTm2", false},
{"observer can view", test.UserObserver, "uuidNoTm", false},
{"observer can view", test.UserObserver, "uuidMixTm1Tm2", false},
{"observer+ can view", test.UserObserverPlus, "uuidTm1", false},
{"observer+ can view", test.UserObserverPlus, "uuidTm2", false},
{"observer+ can view", test.UserObserverPlus, "uuidNoTm", false},
{"observer+ can view", test.UserObserverPlus, "uuidMixTm1Tm2", false},
{"admin can view", test.UserAdmin, "uuidTm1", false},
{"admin can view", test.UserAdmin, "uuidTm2", false},
{"admin can view", test.UserAdmin, "uuidNoTm", false},
{"admin can view", test.UserAdmin, "uuidMixTm1Tm2", false},
{"tm1 maintainer can view tm1", test.UserTeamMaintainerTeam1, "uuidTm1", false},
{"tm1 maintainer cannot view tm2", test.UserTeamMaintainerTeam1, "uuidTm2", true},
{"tm1 maintainer cannot view no team", test.UserTeamMaintainerTeam1, "uuidNoTm", true},
{"tm1 maintainer cannot view mix", test.UserTeamMaintainerTeam1, "uuidMixTm1Tm2", true},
{"tm1 observer can view tm1", test.UserTeamObserverTeam1, "uuidTm1", false},
{"tm1 observer cannot view tm2", test.UserTeamObserverTeam1, "uuidTm2", true},
{"tm1 observer cannot view no team", test.UserTeamObserverTeam1, "uuidNoTm", true},
{"tm1 observer cannot view mix", test.UserTeamObserverTeam1, "uuidMixTm1Tm2", true},
{"tm1 observer+ can view tm1", test.UserTeamObserverPlusTeam1, "uuidTm1", false},
{"tm1 observer+ cannot view tm2", test.UserTeamObserverPlusTeam1, "uuidTm2", true},
{"tm1 observer+ cannot view no team", test.UserTeamObserverPlusTeam1, "uuidNoTm", true},
{"tm1 observer+ cannot view mix", test.UserTeamObserverPlusTeam1, "uuidMixTm1Tm2", true},
{"tm1 admin can view tm1", test.UserTeamAdminTeam1, "uuidTm1", false},
{"tm1 admin cannot view tm2", test.UserTeamAdminTeam1, "uuidTm2", true},
{"tm1 admin cannot view no team", test.UserTeamAdminTeam1, "uuidNoTm", true},
{"tm1 admin cannot view mix", test.UserTeamAdminTeam1, "uuidMixTm1Tm2", true},
}
for _, c := range cmdResultsCases {
t.Run(c.desc, func(t *testing.T) {
ctx = test.UserContext(ctx, c.user)
_, err = svc.GetMDMAppleCommandResults(ctx, c.cmdUUID)
checkAuthErr(t, err, c.shoudFailWithAuth)
})
}
})
t.Run("ListMDMAppleCommands", func(t *testing.T) {
ds.ListMDMAppleCommandsFunc = func(ctx context.Context, tmFilter fleet.TeamFilter, opt *fleet.MDMAppleCommandListOptions) ([]*fleet.MDMAppleCommand, error) {
return []*fleet.MDMAppleCommand{
{DeviceID: "no team", TeamID: nil},
{DeviceID: "tm1", TeamID: ptr.Uint(1)},
{DeviceID: "tm2", TeamID: ptr.Uint(2)},
}, nil
}
listCmdsCases := []struct {
desc string
user *fleet.User
want []string // the expected device ids in the results
shouldFail bool // with forbidden error
}{
{"no role", test.UserNoRoles, []string{}, true},
{"maintainer can view", test.UserMaintainer, []string{"no team", "tm1", "tm2"}, false},
{"observer can view", test.UserObserver, []string{"no team", "tm1", "tm2"}, false},
{"observer+ can view", test.UserObserverPlus, []string{"no team", "tm1", "tm2"}, false},
{"admin can view", test.UserAdmin, []string{"no team", "tm1", "tm2"}, false},
{"tm1 maintainer can view tm1", test.UserTeamMaintainerTeam1, []string{"tm1"}, false},
{"tm1 observer can view tm1", test.UserTeamObserverTeam1, []string{"tm1"}, false},
{"tm1 observer+ can view tm1", test.UserTeamObserverPlusTeam1, []string{"tm1"}, false},
{"tm1 admin can view tm1", test.UserTeamAdminTeam1, []string{"tm1"}, false},
}
for _, c := range listCmdsCases {
t.Run(c.desc, func(t *testing.T) {
ctx = test.UserContext(ctx, c.user)
res, err := svc.ListMDMAppleCommands(ctx, &fleet.MDMAppleCommandListOptions{})
checkAuthErr(t, err, c.shouldFail)
if c.shouldFail {
return
}
got := make([]string, len(res))
for i, r := range res {
got[i] = r.DeviceID
}
require.Equal(t, c.want, got)
})
}
})
Add Apple MDM functionality (#7940) * WIP * Adding DEP functionality to Fleet * Better organize additional MDM code * Add cmdr.py and amend API paths * Fix lint * Add demo file * Fix demo.md * go mod tidy * Add munki setup to Fleet * Add diagram to demo.md * Add fixes * Update TODOs and demo.md * Fix cmdr.py and add TODO * Add endpoints to demo.md * Add more Munki PoC/demo stuff * WIP * Remove proposals from PoC * Replace prepare commands with fleetctl commands * Update demo.md with current state * Remove config field * Amend demo * Remove Munki setup from MVP-Dogfood * Update demo.md * Add apple mdm commands (#7769) * fleetctl enqueue mdm command * fix deps * Fix build Co-authored-by: Lucas Rodriguez <lucas@fleetdm.com> * Add command to upload installers * go mod tidy * fix subcommands help There is a bug in urfave/cli where help text is not generated properly when subcommands are nested too deep. * Add support for installing apps * Add a way to list enrolled devices * Add dep listing * Rearrange endpoints * Move DEP routine to schedule * Define paths globally * Add a way to list enrollments and installers * Parse device-ids as comma-separated string * Remove unused types * Add simple commands and nest under enqueue-command * Fix simple commands * Add help to enqueue-command * merge apple_mdm database * Fix commands * update nanomdm * Split nanomdm and nanodep schemas * Set 512 MB in memory for upload * Remove empty file * Amend profile * Add sample commands * Add delete installers and fix bug in DEP profile assigning * Add dogfood.md deployment guide * Update schema.sql * Dump schema with MySQL 5 * Set default value for authenticate_at * add tokens to enrollment profiles When a device downloads an MDM enrollment profile, verify the token passed as a query parameter. This ensures untrusted devices don't enroll with our MDM server. - Rename enrollments to enrollment profiles. Enrollments is used by nano to refer to devices that are enrolled with MDM - Rename endpoint /api/<version>/fleet/mdm/apple/enrollments to ../enrollmentprofiles - Generate a token for authentication when creating an enrollment profile - Return unauthorized if token is invalid when downloading an enrollment profile from /api/mdm/apple/enroll?token= * remove mdm apple server url * update docs * make dump-test-schema * Update nanomdm with missing prefix table * Add docs and simplify changes * Add changes file * Add method docs * Fix compile and revert prepare.go changes * Revert migration status check change * Amend comments * Add more docs * Clarify storage of installers * Remove TODO * Remove unused * update dogfood.md * remove cmdr.py * Add authorization tests * Add TODO comment * use kitlog for nano logging * Add yaml tags * Remove unused flag * Remove changes file * Only run DEP routine if MDM is enabled * Add docs to all new exported types * Add docs * more nano logging changes * Fix unintentional removal * more nano logging changes * Fix compile test * Use string for configs and fix config test * Add docs and amend changes * revert changes to basicAuthHandler * remove exported BasicAuthHandler * rename rego authz type * Add more information to dep list * add db tag * update deps * Fix schema * Remove unimplemented Co-authored-by: Michal Nicpon <39177923+michalnicp@users.noreply.github.com> Co-authored-by: Michal Nicpon <michal@fleetdm.com>
2022-10-05 22:53:54 +00:00
}
func TestMDMAppleConfigProfileAuthz(t *testing.T) {
svc, ctx, ds := setupAppleMDMService(t, &fleet.LicenseInfo{Tier: fleet.TierPremium})
testCases := []struct {
name string
user *fleet.User
shouldFailGlobal bool
shouldFailTeam bool
}{
{
"global admin",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
false,
false,
},
{
"global maintainer",
&fleet.User{GlobalRole: ptr.String(fleet.RoleMaintainer)},
false,
false,
},
{
"global observer",
&fleet.User{GlobalRole: ptr.String(fleet.RoleObserver)},
true,
true,
},
{
"team admin, belongs to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleAdmin}}},
true,
false,
},
{
"team admin, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleAdmin}}},
true,
true,
},
{
"team maintainer, belongs to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleMaintainer}}},
true,
false,
},
{
"team maintainer, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleMaintainer}}},
true,
true,
},
{
"team observer, belongs to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleObserver}}},
true,
true,
},
{
"team observer, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleObserver}}},
true,
true,
},
{
"user no roles",
&fleet.User{ID: 1337},
true,
true,
},
}
ds.NewMDMAppleConfigProfileFunc = func(ctx context.Context, cp fleet.MDMAppleConfigProfile) (*fleet.MDMAppleConfigProfile, error) {
return &cp, nil
}
ds.ListMDMAppleConfigProfilesFunc = func(ctx context.Context, teamID *uint) ([]*fleet.MDMAppleConfigProfile, error) {
return nil, nil
}
ds.NewActivityFunc = func(context.Context, *fleet.User, fleet.ActivityDetails) error {
return nil
}
ds.GetMDMAppleHostsProfilesSummaryFunc = func(context.Context, *uint) (*fleet.MDMAppleConfigProfilesSummary, error) {
return nil, nil
}
ds.BulkSetPendingMDMAppleHostProfilesFunc = func(ctx context.Context, hids, tids, pids []uint, uuids []string) error {
return nil
}
mockGetFuncWithTeamID := func(teamID uint) mock.GetMDMAppleConfigProfileFunc {
return func(ctx context.Context, profileID uint) (*fleet.MDMAppleConfigProfile, error) {
require.Equal(t, uint(42), profileID)
return &fleet.MDMAppleConfigProfile{TeamID: &teamID}, nil
}
}
mockDeleteFuncWithTeamID := func(teamID uint) mock.DeleteMDMAppleConfigProfileFunc {
return func(ctx context.Context, profileID uint) error {
require.Equal(t, uint(42), profileID)
return nil
}
}
mockTeamFuncWithUser := func(u *fleet.User) mock.TeamFunc {
return func(ctx context.Context, teamID uint) (*fleet.Team, error) {
if len(u.Teams) > 0 {
for _, t := range u.Teams {
if t.ID == teamID {
return &fleet.Team{ID: teamID, Users: []fleet.TeamUser{{User: *u, Role: t.Role}}}, nil
}
}
}
return &fleet.Team{}, nil
}
}
checkShouldFail := func(err error, shouldFail bool) {
if !shouldFail {
require.NoError(t, err)
} else {
require.Error(t, err)
require.Contains(t, err.Error(), authz.ForbiddenErrorMessage)
}
}
mcBytes := mcBytesForTest("Foo", "Bar", "UUID")
for _, tt := range testCases {
ctx := viewer.NewContext(ctx, viewer.Viewer{User: tt.user})
ds.TeamFunc = mockTeamFuncWithUser(tt.user)
t.Run(tt.name, func(t *testing.T) {
// test authz create new profile (no team)
_, err := svc.NewMDMAppleConfigProfile(ctx, 0, bytes.NewReader(mcBytes), int64(len(mcBytes)))
checkShouldFail(err, tt.shouldFailGlobal)
// test authz create new profile (team 1)
_, err = svc.NewMDMAppleConfigProfile(ctx, 1, bytes.NewReader(mcBytes), int64(len(mcBytes)))
checkShouldFail(err, tt.shouldFailTeam)
// test authz list profiles (no team)
_, err = svc.ListMDMAppleConfigProfiles(ctx, 0)
checkShouldFail(err, tt.shouldFailGlobal)
// test authz list profiles (team 1)
_, err = svc.ListMDMAppleConfigProfiles(ctx, 1)
checkShouldFail(err, tt.shouldFailTeam)
// test authz get config profile (no team)
ds.GetMDMAppleConfigProfileFunc = mockGetFuncWithTeamID(0)
_, err = svc.GetMDMAppleConfigProfile(ctx, 42)
checkShouldFail(err, tt.shouldFailGlobal)
// test authz delete config profile (no team)
ds.DeleteMDMAppleConfigProfileFunc = mockDeleteFuncWithTeamID(0)
err = svc.DeleteMDMAppleConfigProfile(ctx, 42)
checkShouldFail(err, tt.shouldFailGlobal)
// test authz get config profile (team 1)
ds.GetMDMAppleConfigProfileFunc = mockGetFuncWithTeamID(1)
_, err = svc.GetMDMAppleConfigProfile(ctx, 42)
checkShouldFail(err, tt.shouldFailTeam)
// test authz delete config profile (team 1)
ds.DeleteMDMAppleConfigProfileFunc = mockDeleteFuncWithTeamID(1)
err = svc.DeleteMDMAppleConfigProfile(ctx, 42)
checkShouldFail(err, tt.shouldFailTeam)
// test authz get profiles summary (no team)
_, err = svc.GetMDMAppleProfilesSummary(ctx, nil)
checkShouldFail(err, tt.shouldFailGlobal)
// test authz get profiles summary (no team)
_, err = svc.GetMDMAppleProfilesSummary(ctx, ptr.Uint(1))
checkShouldFail(err, tt.shouldFailTeam)
})
}
}
func TestNewMDMAppleConfigProfile(t *testing.T) {
svc, ctx, ds := setupAppleMDMService(t, &fleet.LicenseInfo{Tier: fleet.TierPremium})
ctx = viewer.NewContext(ctx, viewer.Viewer{User: &fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)}})
mcBytes := mcBytesForTest("Foo", "Bar", "UUID")
r := bytes.NewReader(mcBytes)
ds.NewMDMAppleConfigProfileFunc = func(ctx context.Context, cp fleet.MDMAppleConfigProfile) (*fleet.MDMAppleConfigProfile, error) {
require.Equal(t, "Foo", cp.Name)
require.Equal(t, "Bar", cp.Identifier)
require.Equal(t, mcBytes, []byte(cp.Mobileconfig))
cp.ProfileID = 1
return &cp, nil
}
ds.NewActivityFunc = func(context.Context, *fleet.User, fleet.ActivityDetails) error {
return nil
}
ds.BulkSetPendingMDMAppleHostProfilesFunc = func(ctx context.Context, hids, tids, pids []uint, uuids []string) error {
return nil
}
cp, err := svc.NewMDMAppleConfigProfile(ctx, 0, r, r.Size())
require.NoError(t, err)
require.Equal(t, "Foo", cp.Name)
require.Equal(t, "Bar", cp.Identifier)
require.Equal(t, mcBytes, []byte(cp.Mobileconfig))
}
func mcBytesForTest(name, identifier, uuid string) []byte {
return []byte(fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array/>
<key>PayloadDisplayName</key>
<string>%s</string>
<key>PayloadIdentifier</key>
<string>%s</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>%s</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>
`, name, identifier, uuid))
}
func TestHostDetailsMDMProfiles(t *testing.T) {
svc, ctx, ds := setupAppleMDMService(t, &fleet.LicenseInfo{Tier: fleet.TierPremium})
ctx = viewer.NewContext(ctx, viewer.Viewer{User: &fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)}})
expected := []fleet.HostMDMAppleProfile{
{HostUUID: "H057-UU1D-1337", Name: "NAME-5", ProfileID: uint(5), CommandUUID: "CMD-UU1D-5", Status: &fleet.MDMAppleDeliveryPending, OperationType: fleet.MDMAppleOperationTypeInstall, Detail: ""},
{HostUUID: "H057-UU1D-1337", Name: "NAME-9", ProfileID: uint(8), CommandUUID: "CMD-UU1D-8", Status: &fleet.MDMAppleDeliveryVerifying, OperationType: fleet.MDMAppleOperationTypeInstall, Detail: ""},
{HostUUID: "H057-UU1D-1337", Name: "NAME-13", ProfileID: uint(13), CommandUUID: "CMD-UU1D-13", Status: &fleet.MDMAppleDeliveryFailed, OperationType: fleet.MDMAppleOperationTypeRemove, Detail: "Error removing profile"},
}
expectedByProfileID := make(map[uint]fleet.HostMDMAppleProfile)
for _, ep := range expected {
expectedByProfileID[ep.ProfileID] = ep
}
ds.GetHostMDMProfilesFunc = func(ctx context.Context, hostUUID string) ([]fleet.HostMDMAppleProfile, error) {
if hostUUID == "H057-UU1D-1337" {
return expected, nil
}
return []fleet.HostMDMAppleProfile{}, nil
}
ds.HostFunc = func(ctx context.Context, hostID uint) (*fleet.Host, error) {
if hostID == uint(42) {
return &fleet.Host{ID: uint(42), UUID: "H057-UU1D-1337"}, nil
}
return &fleet.Host{ID: hostID, UUID: "WR0N6-UU1D"}, nil
}
ds.HostByIdentifierFunc = func(ctx context.Context, identifier string) (*fleet.Host, error) {
if identifier == "h0571d3n71f13r" {
return &fleet.Host{ID: uint(42), UUID: "H057-UU1D-1337"}, nil
}
return &fleet.Host{ID: uint(21), UUID: "WR0N6-UU1D"}, nil
}
ds.LoadHostSoftwareFunc = func(ctx context.Context, host *fleet.Host, includeCVEScores bool) error {
return nil
}
ds.ListLabelsForHostFunc = func(ctx context.Context, hid uint) ([]*fleet.Label, error) {
return nil, nil
}
ds.ListPacksForHostFunc = func(ctx context.Context, hid uint) (packs []*fleet.Pack, err error) {
return nil, nil
}
ds.ListHostBatteriesFunc = func(ctx context.Context, id uint) ([]*fleet.HostBattery, error) {
return nil, nil
}
ds.ListPoliciesForHostFunc = func(ctx context.Context, host *fleet.Host) ([]*fleet.HostPolicy, error) {
return nil, nil
}
ds.GetHostMDMMacOSSetupFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDMMacOSSetup, error) {
return nil, nil
}
expectedNilSlice := []fleet.HostMDMAppleProfile(nil)
expectedEmptySlice := []fleet.HostMDMAppleProfile{}
cases := []struct {
name string
mdmEnabled bool
hostID *uint
hostIdentifier *string
expected *[]fleet.HostMDMAppleProfile
}{
{
name: "TestGetHostMDMProfilesOK",
mdmEnabled: true,
hostID: ptr.Uint(42),
hostIdentifier: nil,
expected: &expected,
},
{
name: "TestGetHostMDMProfilesEmpty",
mdmEnabled: true,
hostID: ptr.Uint(21),
hostIdentifier: nil,
expected: &expectedEmptySlice,
},
{
name: "TestGetHostMDMProfilesNil",
mdmEnabled: false,
hostID: ptr.Uint(42),
hostIdentifier: nil,
expected: &expectedNilSlice,
},
{
name: "TestHostByIdentifierMDMProfilesOK",
mdmEnabled: true,
hostID: nil,
hostIdentifier: ptr.String("h0571d3n71f13r"),
expected: &expected,
},
{
name: "TestHostByIdentifierMDMProfilesNil",
mdmEnabled: false,
hostID: nil,
hostIdentifier: ptr.String("h0571d3n71f13r"),
expected: &expectedNilSlice,
},
{
name: "TestHostByIdentifierMDMProfilesEmpty",
mdmEnabled: true,
hostID: nil,
hostIdentifier: ptr.String("4n07h3r1d3n71f13r"),
expected: &expectedEmptySlice,
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
ds.AppConfigFunc = func(context.Context) (*fleet.AppConfig, error) {
return &fleet.AppConfig{MDM: fleet.MDM{EnabledAndConfigured: c.mdmEnabled}}, nil
}
ds.AppConfigFuncInvoked = false
ds.HostFuncInvoked = false
ds.HostByIdentifierFuncInvoked = false
ds.GetHostMDMProfilesFuncInvoked = false
var gotHost *fleet.HostDetail
if c.hostID != nil {
h, err := svc.GetHost(ctx, *c.hostID, fleet.HostDetailOptions{})
require.NoError(t, err)
require.True(t, ds.HostFuncInvoked)
gotHost = h
}
if c.hostIdentifier != nil {
h, err := svc.HostByIdentifier(ctx, *c.hostIdentifier, fleet.HostDetailOptions{})
require.NoError(t, err)
require.True(t, ds.HostByIdentifierFuncInvoked)
gotHost = h
}
require.NotNil(t, gotHost)
require.True(t, ds.AppConfigFuncInvoked)
if !c.mdmEnabled {
require.Equal(t, gotHost.MDM.Profiles, c.expected)
return
}
require.True(t, ds.GetHostMDMProfilesFuncInvoked)
require.NotNil(t, gotHost.MDM.Profiles)
require.ElementsMatch(t, *c.expected, *gotHost.MDM.Profiles)
})
}
}
func TestMDMCommandAuthz(t *testing.T) {
svc, ctx, ds := setupAppleMDMService(t, &fleet.LicenseInfo{Tier: fleet.TierPremium})
ds.HostLiteFunc = func(ctx context.Context, hostID uint) (*fleet.Host, error) {
switch hostID {
case 1:
return &fleet.Host{UUID: "test-host-team-1", TeamID: ptr.Uint(1)}, nil
default:
return &fleet.Host{UUID: "test-host-no-team"}, nil
}
}
ds.GetHostMDMCheckinInfoFunc = func(ctx context.Context, hostUUID string) (*fleet.HostMDMCheckinInfo, error) {
return &fleet.HostMDMCheckinInfo{}, nil
}
ds.NewActivityFunc = func(context.Context, *fleet.User, fleet.ActivityDetails) error {
return nil
}
var mdmEnabled atomic.Bool
ds.GetNanoMDMEnrollmentFunc = func(ctx context.Context, hostUUID string) (*fleet.NanoEnrollment, error) {
// This function is called twice during EnqueueMDMAppleCommandRemoveEnrollmentProfile.
// It first is called to check that the device is enrolled as a pre-condition to enqueueing the
// command. It is called second time after the command has been enqueued to check whether
// the device was successfully unenrolled.
//
// For each test run, the bool should be initialized to true to simulate an existing device
// that is initially enrolled to Fleet's MDM.
enroll := fleet.NanoEnrollment{
Enabled: mdmEnabled.Swap(!mdmEnabled.Load()),
}
return &enroll, nil
}
testCases := []struct {
name string
user *fleet.User
shouldFailGlobal bool
shouldFailTeam bool
}{
{
"global admin",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
false,
false,
},
{
"global maintainer",
&fleet.User{GlobalRole: ptr.String(fleet.RoleMaintainer)},
false,
false,
},
{
"global observer",
&fleet.User{GlobalRole: ptr.String(fleet.RoleObserver)},
true,
true,
},
{
"team admin, belongs to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleAdmin}}},
true,
false,
},
{
"team admin, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleAdmin}}},
true,
true,
},
{
"team maintainer, belongs to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleMaintainer}}},
true,
false,
},
{
"team maintainer, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleMaintainer}}},
true,
true,
},
{
"team observer, belongs to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleObserver}}},
true,
true,
},
{
"team observer, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleObserver}}},
true,
true,
},
{
"user no roles",
&fleet.User{ID: 1337},
true,
true,
},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
ctx := viewer.NewContext(ctx, viewer.Viewer{User: tt.user})
mdmEnabled.Store(true)
err := svc.EnqueueMDMAppleCommandRemoveEnrollmentProfile(ctx, 42) // global host
if !tt.shouldFailGlobal {
require.NoError(t, err)
} else {
require.Error(t, err)
require.Contains(t, err.Error(), authz.ForbiddenErrorMessage)
}
mdmEnabled.Store(true)
err = svc.EnqueueMDMAppleCommandRemoveEnrollmentProfile(ctx, 1) // host belongs to team 1
if !tt.shouldFailTeam {
require.NoError(t, err)
} else {
require.Error(t, err)
require.Contains(t, err.Error(), authz.ForbiddenErrorMessage)
}
})
}
}
func TestMDMAuthenticate(t *testing.T) {
ds := new(mock.Store)
svc := MDMAppleCheckinAndCommandService{ds: ds}
ctx := context.Background()
uuid, serial, model := "ABC-DEF-GHI", "XYZABC", "MacBookPro 16,1"
ds.IngestMDMAppleDeviceFromCheckinFunc = func(ctx context.Context, mdmHost fleet.MDMAppleHostDetails) error {
require.Equal(t, uuid, mdmHost.UDID)
require.Equal(t, serial, mdmHost.SerialNumber)
require.Equal(t, model, mdmHost.Model)
return nil
}
ds.GetHostMDMCheckinInfoFunc = func(ct context.Context, hostUUID string) (*fleet.HostMDMCheckinInfo, error) {
require.Equal(t, uuid, hostUUID)
return &fleet.HostMDMCheckinInfo{HardwareSerial: serial, DisplayName: fmt.Sprintf("%s (%s)", model, serial), InstalledFromDEP: false}, nil
}
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
a, ok := activity.(*fleet.ActivityTypeMDMEnrolled)
require.True(t, ok)
require.Nil(t, user)
require.Equal(t, "mdm_enrolled", activity.ActivityName())
require.Equal(t, serial, a.HostSerial)
require.Equal(t, a.HostDisplayName, fmt.Sprintf("%s (%s)", model, serial))
require.False(t, a.InstalledFromDEP)
return nil
}
err := svc.Authenticate(
&mdm.Request{Context: ctx},
&mdm.Authenticate{
Enrollment: mdm.Enrollment{
UDID: uuid,
},
SerialNumber: serial,
Model: model,
},
)
require.NoError(t, err)
require.True(t, ds.IngestMDMAppleDeviceFromCheckinFuncInvoked)
require.True(t, ds.GetHostMDMCheckinInfoFuncInvoked)
require.True(t, ds.NewActivityFuncInvoked)
}
func TestMDMTokenUpdate(t *testing.T) {
ctx := context.Background()
ds := new(mock.Store)
mdmStorage := &nanomdm_mock.Storage{}
pushFactory, _ := newMockAPNSPushProviderFactory()
pusher := nanomdm_pushsvc.New(
mdmStorage,
mdmStorage,
pushFactory,
NewNanoMDMLogger(kitlog.NewJSONLogger(os.Stdout)),
)
cmdr := apple_mdm.NewMDMAppleCommander(mdmStorage, pusher)
svc := MDMAppleCheckinAndCommandService{ds: ds, commander: cmdr, logger: kitlog.NewNopLogger()}
uuid, serial, model, wantTeamID := "ABC-DEF-GHI", "XYZABC", "MacBookPro 16,1", uint(12)
serverURL := "https://example.com"
commands := map[string]int{}
mdmStorage.EnqueueCommandFunc = func(ctx context.Context, id []string, cmd *mdm.Command) (map[string]error, error) {
if _, ok := commands[cmd.Command.RequestType]; !ok {
commands[cmd.Command.RequestType] = 0
}
commands[cmd.Command.RequestType]++
require.NotNil(t, cmd)
return nil, nil
}
mdmStorage.RetrievePushInfoFunc = func(p0 context.Context, targetUUIDs []string) (map[string]*mdm.Push, error) {
require.ElementsMatch(t, []string{uuid}, targetUUIDs)
pushes := make(map[string]*mdm.Push, len(targetUUIDs))
for _, uuid := range targetUUIDs {
pushes[uuid] = &mdm.Push{
PushMagic: "magic" + uuid,
Token: []byte("token" + uuid),
Topic: "topic" + uuid,
}
}
return pushes, nil
}
mdmStorage.RetrievePushCertFunc = func(ctx context.Context, topic string) (*tls.Certificate, string, error) {
cert, err := tls.LoadX509KeyPair("testdata/server.pem", "testdata/server.key")
return &cert, "", err
}
mdmStorage.IsPushCertStaleFunc = func(ctx context.Context, topic string, staleToken string) (bool, error) {
return false, nil
}
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
appCfg := &fleet.AppConfig{}
appCfg.ServerSettings.ServerURL = serverURL
// assign a name to simulate EndUserAuthentication being configured
appCfg.MDM.EndUserAuthentication.IDPName = "FooIdP"
return appCfg, nil
}
ds.GetNanoMDMEnrollmentFunc = func(ctx context.Context, hostUUID string) (*fleet.NanoEnrollment, error) {
return &fleet.NanoEnrollment{Enabled: true, Type: "Device", TokenUpdateTally: 1}, nil
}
ds.GetHostMDMCheckinInfoFunc = func(ct context.Context, hostUUID string) (*fleet.HostMDMCheckinInfo, error) {
require.Equal(t, uuid, hostUUID)
return &fleet.HostMDMCheckinInfo{
HardwareSerial: serial,
DisplayName: model,
InstalledFromDEP: true,
TeamID: wantTeamID,
}, nil
}
ds.BulkSetPendingMDMAppleHostProfilesFunc = func(ctx context.Context, hids, tids, pids []uint, uuids []string) error {
return nil
}
ds.GetMDMAppleBootstrapPackageMetaFunc = func(ctx context.Context, teamID uint) (*fleet.MDMAppleBootstrapPackage, error) {
require.Equal(t, wantTeamID, teamID)
return &fleet.MDMAppleBootstrapPackage{}, nil
}
ds.RecordHostBootstrapPackageFunc = func(ctx context.Context, commandUUID string, hostUUID string) error {
require.Equal(t, uuid, hostUUID)
require.NotEmpty(t, commandUUID)
return nil
}
idpAcc := &fleet.MDMIdPAccount{
UUID: "FOO-BAR",
Fullname: "Jane Doe",
Username: "jane.doe@example.com",
}
ds.GetMDMIdPAccountFunc = func(ctx context.Context, uuid string) (*fleet.MDMIdPAccount, error) {
require.Equal(t, idpAcc.UUID, uuid)
return idpAcc, nil
}
ds.TeamFunc = func(ctx context.Context, tid uint) (*fleet.Team, error) {
tm := &fleet.Team{}
tm.Config.MDM.MacOSSetup.EnableEndUserAuthentication = true
return tm, nil
}
err := svc.TokenUpdate(
&mdm.Request{Context: ctx, EnrollID: &mdm.EnrollID{ID: uuid}},
&mdm.TokenUpdate{
Enrollment: mdm.Enrollment{
UDID: uuid,
},
},
)
require.NoError(t, err)
require.True(t, ds.BulkSetPendingMDMAppleHostProfilesFuncInvoked)
require.True(t, ds.GetHostMDMCheckinInfoFuncInvoked)
require.True(t, ds.AppConfigFuncInvoked)
require.True(t, ds.RecordHostBootstrapPackageFuncInvoked)
require.False(t, ds.GetMDMIdPAccountFuncInvoked)
require.Equal(t, 2, commands["InstallEnterpriseApplication"])
require.Equal(t, 0, commands["AccountConfiguration"])
ds.BulkSetPendingMDMAppleHostProfilesFuncInvoked = false
ds.GetHostMDMCheckinInfoFuncInvoked = false
ds.AppConfigFuncInvoked = false
ds.RecordHostBootstrapPackageFuncInvoked = false
commands["InstallEnterpriseApplication"] = 0
// with enrollment reference
err = svc.TokenUpdate(
&mdm.Request{
Context: ctx,
EnrollID: &mdm.EnrollID{ID: uuid},
Params: map[string]string{"enroll_reference": idpAcc.UUID},
},
&mdm.TokenUpdate{
Enrollment: mdm.Enrollment{
UDID: uuid,
},
},
)
require.NoError(t, err)
require.True(t, ds.BulkSetPendingMDMAppleHostProfilesFuncInvoked)
require.True(t, ds.GetHostMDMCheckinInfoFuncInvoked)
require.True(t, ds.AppConfigFuncInvoked)
require.True(t, ds.RecordHostBootstrapPackageFuncInvoked)
require.True(t, ds.GetMDMIdPAccountFuncInvoked)
require.Equal(t, 2, commands["InstallEnterpriseApplication"])
require.Equal(t, 1, commands["AccountConfiguration"])
}
func TestMDMCheckout(t *testing.T) {
ds := new(mock.Store)
svc := MDMAppleCheckinAndCommandService{ds: ds}
ctx := context.Background()
uuid, serial, installedFromDEP, displayName := "ABC-DEF-GHI", "XYZABC", true, "Test's MacBook"
ds.UpdateHostTablesOnMDMUnenrollFunc = func(ctx context.Context, hostUUID string) error {
require.Equal(t, uuid, hostUUID)
return nil
}
ds.GetHostMDMCheckinInfoFunc = func(ct context.Context, hostUUID string) (*fleet.HostMDMCheckinInfo, error) {
require.Equal(t, uuid, hostUUID)
return &fleet.HostMDMCheckinInfo{
HardwareSerial: serial,
DisplayName: displayName,
InstalledFromDEP: installedFromDEP,
}, nil
}
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
a, ok := activity.(*fleet.ActivityTypeMDMUnenrolled)
require.True(t, ok)
require.Nil(t, user)
require.Equal(t, "mdm_unenrolled", activity.ActivityName())
require.Equal(t, serial, a.HostSerial)
require.Equal(t, displayName, a.HostDisplayName)
require.True(t, a.InstalledFromDEP)
return nil
}
err := svc.CheckOut(
&mdm.Request{Context: ctx},
&mdm.CheckOut{
Enrollment: mdm.Enrollment{
UDID: uuid,
},
},
)
require.NoError(t, err)
require.True(t, ds.UpdateHostTablesOnMDMUnenrollFuncInvoked)
require.True(t, ds.GetHostMDMCheckinInfoFuncInvoked)
require.True(t, ds.NewActivityFuncInvoked)
}
func TestMDMCommandAndReportResultsProfileHandling(t *testing.T) {
ds := new(mock.Store)
svc := MDMAppleCheckinAndCommandService{ds: ds}
ctx := context.Background()
hostUUID := "ABC-DEF-GHI"
commandUUID := "COMMAND-UUID"
cases := []struct {
status string
requestType string
errors []mdm.ErrorChain
want *fleet.HostMDMAppleProfile
}{
{
status: "Acknowledged",
requestType: "InstallProfile",
errors: nil,
want: &fleet.HostMDMAppleProfile{
Status: &fleet.MDMAppleDeliveryVerifying,
Detail: "",
OperationType: fleet.MDMAppleOperationTypeInstall,
},
},
{
status: "Acknowledged",
requestType: "RemoveProfile",
errors: nil,
want: &fleet.HostMDMAppleProfile{
Status: &fleet.MDMAppleDeliveryVerifying,
Detail: "",
OperationType: fleet.MDMAppleOperationTypeRemove,
},
},
{
status: "Error",
requestType: "InstallProfile",
errors: []mdm.ErrorChain{
{ErrorCode: 123, ErrorDomain: "testDomain", USEnglishDescription: "testMessage"},
},
want: &fleet.HostMDMAppleProfile{
Status: &fleet.MDMAppleDeliveryFailed,
Detail: "testDomain (123): testMessage\n",
OperationType: fleet.MDMAppleOperationTypeInstall,
},
},
{
status: "Error",
requestType: "RemoveProfile",
errors: []mdm.ErrorChain{
{ErrorCode: 123, ErrorDomain: "testDomain", USEnglishDescription: "testMessage"},
{ErrorCode: 321, ErrorDomain: "domainTest", USEnglishDescription: "messageTest"},
},
want: &fleet.HostMDMAppleProfile{
Status: &fleet.MDMAppleDeliveryFailed,
Detail: "testDomain (123): testMessage\ndomainTest (321): messageTest\n",
OperationType: fleet.MDMAppleOperationTypeRemove,
},
},
{
status: "Error",
requestType: "RemoveProfile",
errors: nil,
want: &fleet.HostMDMAppleProfile{
Status: &fleet.MDMAppleDeliveryFailed,
Detail: "",
OperationType: fleet.MDMAppleOperationTypeRemove,
},
},
}
for _, c := range cases {
ds.GetMDMAppleCommandRequestTypeFunc = func(ctx context.Context, targetCmd string) (string, error) {
require.Equal(t, commandUUID, targetCmd)
return c.requestType, nil
}
ds.UpdateOrDeleteHostMDMAppleProfileFunc = func(ctx context.Context, profile *fleet.HostMDMAppleProfile) error {
c.want.CommandUUID = commandUUID
c.want.HostUUID = hostUUID
require.Equal(t, c.want, profile)
return nil
}
_, err := svc.CommandAndReportResults(
&mdm.Request{Context: ctx},
&mdm.CommandResults{
Enrollment: mdm.Enrollment{UDID: hostUUID},
CommandUUID: commandUUID,
Status: c.status,
RequestType: c.requestType,
ErrorChain: c.errors,
},
)
require.NoError(t, err)
require.True(t, ds.GetMDMAppleCommandRequestTypeFuncInvoked)
require.True(t, ds.UpdateOrDeleteHostMDMAppleProfileFuncInvoked)
}
}
func TestMDMBatchSetAppleProfiles(t *testing.T) {
svc, ctx, ds := setupAppleMDMService(t, &fleet.LicenseInfo{Tier: fleet.TierPremium})
ds.TeamByNameFunc = func(ctx context.Context, name string) (*fleet.Team, error) {
return &fleet.Team{ID: 1, Name: name}, nil
}
ds.TeamFunc = func(ctx context.Context, id uint) (*fleet.Team, error) {
return &fleet.Team{ID: id, Name: "team"}, nil
}
ds.BatchSetMDMAppleProfilesFunc = func(ctx context.Context, teamID *uint, profiles []*fleet.MDMAppleConfigProfile) error {
return nil
}
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
return nil
}
ds.BulkSetPendingMDMAppleHostProfilesFunc = func(ctx context.Context, hids, tids, pids []uint, uuids []string) error {
return nil
}
testCases := []struct {
name string
user *fleet.User
premium bool
teamID *uint
teamName *string
profiles [][]byte
wantErr string
}{
{
"global admin",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
false,
nil,
nil,
nil,
"",
},
{
"global admin, team",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
true,
ptr.Uint(1),
nil,
nil,
"",
},
{
"global maintainer",
&fleet.User{GlobalRole: ptr.String(fleet.RoleMaintainer)},
false,
nil,
nil,
nil,
"",
},
{
"global maintainer, team",
&fleet.User{GlobalRole: ptr.String(fleet.RoleMaintainer)},
true,
ptr.Uint(1),
nil,
nil,
"",
},
{
"global observer",
&fleet.User{GlobalRole: ptr.String(fleet.RoleObserver)},
false,
nil,
nil,
nil,
authz.ForbiddenErrorMessage,
},
{
"team admin, DOES belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleAdmin}}},
true,
ptr.Uint(1),
nil,
nil,
"",
},
{
"team admin, DOES belong to team by name",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleAdmin}}},
true,
nil,
ptr.String("team"),
nil,
"",
},
{
"team admin, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleAdmin}}},
true,
ptr.Uint(1),
nil,
nil,
authz.ForbiddenErrorMessage,
},
{
"team admin, DOES NOT belong to team by name",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleAdmin}}},
true,
nil,
ptr.String("team"),
nil,
authz.ForbiddenErrorMessage,
},
{
"team maintainer, DOES belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleMaintainer}}},
true,
ptr.Uint(1),
nil,
nil,
"",
},
{
"team maintainer, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleMaintainer}}},
true,
ptr.Uint(1),
nil,
nil,
authz.ForbiddenErrorMessage,
},
{
"team observer, DOES belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleObserver}}},
true,
ptr.Uint(1),
nil,
nil,
authz.ForbiddenErrorMessage,
},
{
"team observer, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleObserver}}},
true,
ptr.Uint(1),
nil,
nil,
authz.ForbiddenErrorMessage,
},
{
"user no roles",
&fleet.User{ID: 1337},
false,
nil,
nil,
nil,
authz.ForbiddenErrorMessage,
},
{
"team id with free license",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
false,
ptr.Uint(1),
nil,
nil,
ErrMissingLicense.Error(),
},
{
"team name with free license",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
false,
nil,
ptr.String("team"),
nil,
ErrMissingLicense.Error(),
},
{
"team id and name specified",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
true,
ptr.Uint(1),
ptr.String("team"),
nil,
"cannot specify both team_id and team_name",
},
{
"duplicate profile name",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
true,
ptr.Uint(1),
nil,
[][]byte{
mobileconfigForTest("N1", "I1"),
mobileconfigForTest("N1", "I2"),
},
`More than one configuration profile have the same name (PayloadDisplayName): "N1"`,
},
{
"duplicate profile identifier",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
true,
ptr.Uint(1),
nil,
[][]byte{
mobileconfigForTest("N1", "I1"),
mobileconfigForTest("N2", "I2"),
mobileconfigForTest("N3", "I1"),
},
`More than one configuration profile have the same identifier (PayloadIdentifier): "I1"`,
},
{
"no duplicates",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
false,
nil,
nil,
[][]byte{
mobileconfigForTest("N1", "I1"),
mobileconfigForTest("N2", "I2"),
mobileconfigForTest("N3", "I3"),
},
``,
},
{
"unsupported payload type",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
false,
nil,
nil,
[][]byte{[]byte(`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>Enable</key>
<string>On</string>
<key>PayloadDisplayName</key>
<string>FileVault 2</string>
<key>PayloadIdentifier</key>
<string>com.apple.MCX.FileVault2.A5874654-D6BA-4649-84B5-43847953B369</string>
<key>PayloadType</key>
<string>com.apple.MCX.FileVault2</string>
<key>PayloadUUID</key>
<string>A5874654-D6BA-4649-84B5-43847953B369</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</array>
<key>PayloadDisplayName</key>
<string>Config Profile Name</string>
<key>PayloadIdentifier</key>
<string>com.example.config.FE42D0A2-DBA9-4B72-BC67-9288665B8D59</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>FE42D0A2-DBA9-4B72-BC67-9288665B8D59</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>`)},
"unsupported PayloadType(s)",
},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
defer func() { ds.BatchSetMDMAppleProfilesFuncInvoked = false }()
// prepare the context with the user and license
ctx := viewer.NewContext(ctx, viewer.Viewer{User: tt.user})
tier := fleet.TierFree
if tt.premium {
tier = fleet.TierPremium
}
ctx = license.NewContext(ctx, &fleet.LicenseInfo{Tier: tier})
err := svc.BatchSetMDMAppleProfiles(ctx, tt.teamID, tt.teamName, tt.profiles, false)
if tt.wantErr == "" {
require.NoError(t, err)
require.True(t, ds.BatchSetMDMAppleProfilesFuncInvoked)
return
}
require.Error(t, err)
require.ErrorContains(t, err, tt.wantErr)
require.False(t, ds.BatchSetMDMAppleProfilesFuncInvoked)
})
}
}
func TestUpdateMDMAppleSettings(t *testing.T) {
svc, ctx, ds := setupAppleMDMService(t, &fleet.LicenseInfo{Tier: fleet.TierPremium})
ds.TeamFunc = func(ctx context.Context, id uint) (*fleet.Team, error) {
return &fleet.Team{ID: id, Name: "team"}, nil
}
ds.SaveTeamFunc = func(ctx context.Context, team *fleet.Team) (*fleet.Team, error) {
return team, nil
}
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
return nil
}
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return &fleet.AppConfig{}, nil
}
ds.SaveAppConfigFunc = func(ctx context.Context, appConfig *fleet.AppConfig) error {
return nil
}
testCases := []struct {
name string
user *fleet.User
premium bool
teamID *uint
wantErr string
}{
{
"global admin",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
false,
nil,
ErrMissingLicense.Error(),
},
{
"global admin premium",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
true,
nil,
"",
},
{
"global admin, team",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
true,
ptr.Uint(1),
"",
},
{
"global maintainer",
&fleet.User{GlobalRole: ptr.String(fleet.RoleMaintainer)},
false,
nil,
ErrMissingLicense.Error(),
},
{
"global maintainer premium",
&fleet.User{GlobalRole: ptr.String(fleet.RoleMaintainer)},
true,
nil,
"",
},
{
"global maintainer, team",
&fleet.User{GlobalRole: ptr.String(fleet.RoleMaintainer)},
true,
ptr.Uint(1),
"",
},
{
"global observer",
&fleet.User{GlobalRole: ptr.String(fleet.RoleObserver)},
true,
nil,
authz.ForbiddenErrorMessage,
},
{
"team admin, DOES belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleAdmin}}},
true,
ptr.Uint(1),
"",
},
{
"team admin, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleAdmin}}},
true,
ptr.Uint(1),
authz.ForbiddenErrorMessage,
},
{
"team maintainer, DOES belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleMaintainer}}},
true,
ptr.Uint(1),
"",
},
{
"team maintainer, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleMaintainer}}},
true,
ptr.Uint(1),
authz.ForbiddenErrorMessage,
},
{
"team observer, DOES belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleObserver}}},
true,
ptr.Uint(1),
authz.ForbiddenErrorMessage,
},
{
"team observer, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleObserver}}},
true,
ptr.Uint(1),
authz.ForbiddenErrorMessage,
},
{
"user no roles",
&fleet.User{ID: 1337},
true,
nil,
authz.ForbiddenErrorMessage,
},
{
"team id with free license",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
false,
ptr.Uint(1),
ErrMissingLicense.Error(),
},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
// prepare the context with the user and license
ctx := viewer.NewContext(ctx, viewer.Viewer{User: tt.user})
tier := fleet.TierFree
if tt.premium {
tier = fleet.TierPremium
}
ctx = license.NewContext(ctx, &fleet.LicenseInfo{Tier: tier})
err := svc.UpdateMDMAppleSettings(ctx, fleet.MDMAppleSettingsPayload{TeamID: tt.teamID})
if tt.wantErr == "" {
require.NoError(t, err)
return
}
require.Error(t, err)
require.ErrorContains(t, err, tt.wantErr)
})
}
}
func TestUpdateMDMAppleSetup(t *testing.T) {
setupTest := func(tier string) (fleet.Service, context.Context, *mock.Store) {
svc, ctx, ds := setupAppleMDMService(t, &fleet.LicenseInfo{Tier: tier})
ds.TeamFunc = func(ctx context.Context, id uint) (*fleet.Team, error) {
return &fleet.Team{ID: id, Name: "team"}, nil
}
ds.SaveTeamFunc = func(ctx context.Context, team *fleet.Team) (*fleet.Team, error) {
return team, nil
}
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
return nil
}
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return &fleet.AppConfig{MDM: fleet.MDM{EnabledAndConfigured: true}}, nil
}
ds.SaveAppConfigFunc = func(ctx context.Context, appConfig *fleet.AppConfig) error {
return nil
}
return svc, ctx, ds
}
type testCase struct {
name string
user *fleet.User
teamID *uint
wantErr string
}
// TODO: Add tests for gitops and observer plus roles? (Settings endpoint test above may also need to be updated)
t.Run("FreeTier", func(t *testing.T) {
freeTestCases := []testCase{
{
"global admin",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
nil,
"Requires Fleet Premium license",
},
{
"global maintainer",
&fleet.User{GlobalRole: ptr.String(fleet.RoleMaintainer)},
nil,
"Requires Fleet Premium license",
},
{
"team id with free license",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
ptr.Uint(1),
"Requires Fleet Premium license",
},
}
svc, ctx, _ := setupTest(fleet.TierFree)
for _, tt := range freeTestCases {
t.Run(tt.name, func(t *testing.T) {
// prepare the context with the user and license
ctx := viewer.NewContext(ctx, viewer.Viewer{User: tt.user})
err := svc.UpdateMDMAppleSetup(ctx, fleet.MDMAppleSetupPayload{TeamID: tt.teamID})
if tt.wantErr == "" {
require.NoError(t, err)
return
}
require.Error(t, err)
require.ErrorContains(t, err, tt.wantErr)
})
}
})
t.Run("PremiumTier", func(t *testing.T) {
premiumTestCases := []testCase{
{
"global admin premium",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
nil,
"",
},
{
"global admin, team",
&fleet.User{GlobalRole: ptr.String(fleet.RoleAdmin)},
ptr.Uint(1),
"",
},
{
"global maintainer premium",
&fleet.User{GlobalRole: ptr.String(fleet.RoleMaintainer)},
nil,
"",
},
{
"global maintainer, team",
&fleet.User{GlobalRole: ptr.String(fleet.RoleMaintainer)},
ptr.Uint(1),
"",
},
{
"global observer",
&fleet.User{GlobalRole: ptr.String(fleet.RoleObserver)},
nil,
authz.ForbiddenErrorMessage,
},
{
"team admin, DOES belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleAdmin}}},
ptr.Uint(1),
"",
},
{
"team admin, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleAdmin}}},
ptr.Uint(1),
authz.ForbiddenErrorMessage,
},
{
"team maintainer, DOES belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleMaintainer}}},
ptr.Uint(1),
"",
},
{
"team maintainer, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleMaintainer}}},
ptr.Uint(1),
authz.ForbiddenErrorMessage,
},
{
"team observer, DOES belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 1}, Role: fleet.RoleObserver}}},
ptr.Uint(1),
authz.ForbiddenErrorMessage,
},
{
"team observer, DOES NOT belong to team",
&fleet.User{Teams: []fleet.UserTeam{{Team: fleet.Team{ID: 2}, Role: fleet.RoleObserver}}},
ptr.Uint(1),
authz.ForbiddenErrorMessage,
},
{
"user no roles",
&fleet.User{ID: 1337},
nil,
authz.ForbiddenErrorMessage,
},
}
svc, ctx, _ := setupTest(fleet.TierPremium)
for _, tt := range premiumTestCases {
t.Run(tt.name, func(t *testing.T) {
// prepare the context with the user and license
ctx := viewer.NewContext(ctx, viewer.Viewer{User: tt.user})
err := svc.UpdateMDMAppleSetup(ctx, fleet.MDMAppleSetupPayload{TeamID: tt.teamID})
if tt.wantErr == "" {
require.NoError(t, err)
return
}
require.Error(t, err)
require.ErrorContains(t, err, tt.wantErr)
})
}
})
}
func TestMDMAppleCommander(t *testing.T) {
ctx := context.Background()
mdmStorage := &nanomdm_mock.Storage{}
pushFactory, _ := newMockAPNSPushProviderFactory()
pusher := nanomdm_pushsvc.New(
mdmStorage,
mdmStorage,
pushFactory,
NewNanoMDMLogger(kitlog.NewJSONLogger(os.Stdout)),
)
cmdr := apple_mdm.NewMDMAppleCommander(mdmStorage, pusher)
// TODO(roberto): there's a data race in the mock when more
// than one host ID is provided because the pusher uses one
// goroutine per uuid to send the commands
hostUUIDs := []string{"A"}
payloadName := "com.foo.bar"
payloadIdentifier := "com-foo-bar"
mc := mobileconfigForTest(payloadName, payloadIdentifier)
mdmStorage.EnqueueCommandFunc = func(ctx context.Context, id []string, cmd *mdm.Command) (map[string]error, error) {
require.NotNil(t, cmd)
require.Equal(t, cmd.Command.RequestType, "InstallProfile")
require.Contains(t, string(cmd.Raw), base64.StdEncoding.EncodeToString(mc))
return nil, nil
}
mdmStorage.RetrievePushInfoFunc = func(p0 context.Context, targetUUIDs []string) (map[string]*mdm.Push, error) {
require.ElementsMatch(t, hostUUIDs, targetUUIDs)
pushes := make(map[string]*mdm.Push, len(targetUUIDs))
for _, uuid := range targetUUIDs {
pushes[uuid] = &mdm.Push{
PushMagic: "magic" + uuid,
Token: []byte("token" + uuid),
Topic: "topic" + uuid,
}
}
return pushes, nil
}
mdmStorage.RetrievePushCertFunc = func(ctx context.Context, topic string) (*tls.Certificate, string, error) {
cert, err := tls.LoadX509KeyPair("testdata/server.pem", "testdata/server.key")
return &cert, "", err
}
mdmStorage.IsPushCertStaleFunc = func(ctx context.Context, topic string, staleToken string) (bool, error) {
return false, nil
}
cmdUUID := uuid.New().String()
err := cmdr.InstallProfile(ctx, hostUUIDs, mc, cmdUUID)
require.NoError(t, err)
require.True(t, mdmStorage.EnqueueCommandFuncInvoked)
mdmStorage.EnqueueCommandFuncInvoked = false
require.True(t, mdmStorage.RetrievePushInfoFuncInvoked)
mdmStorage.RetrievePushInfoFuncInvoked = false
mdmStorage.EnqueueCommandFunc = func(ctx context.Context, id []string, cmd *mdm.Command) (map[string]error, error) {
require.NotNil(t, cmd)
require.Equal(t, "RemoveProfile", cmd.Command.RequestType)
require.Contains(t, string(cmd.Raw), payloadIdentifier)
return nil, nil
}
cmdUUID = uuid.New().String()
err = cmdr.RemoveProfile(ctx, hostUUIDs, payloadIdentifier, cmdUUID)
require.True(t, mdmStorage.EnqueueCommandFuncInvoked)
mdmStorage.EnqueueCommandFuncInvoked = false
require.True(t, mdmStorage.RetrievePushInfoFuncInvoked)
mdmStorage.RetrievePushInfoFuncInvoked = false
require.NoError(t, err)
cmdUUID = uuid.New().String()
mdmStorage.EnqueueCommandFunc = func(ctx context.Context, id []string, cmd *mdm.Command) (map[string]error, error) {
require.NotNil(t, cmd)
require.Equal(t, "InstallEnterpriseApplication", cmd.Command.RequestType)
require.Contains(t, string(cmd.Raw), "http://test.example.com")
require.Contains(t, string(cmd.Raw), cmdUUID)
return nil, nil
}
err = cmdr.InstallEnterpriseApplication(ctx, hostUUIDs, "http://test.example.com", cmdUUID)
require.NoError(t, err)
require.True(t, mdmStorage.EnqueueCommandFuncInvoked)
mdmStorage.EnqueueCommandFuncInvoked = false
require.True(t, mdmStorage.RetrievePushInfoFuncInvoked)
mdmStorage.RetrievePushInfoFuncInvoked = false
}
func TestMDMAppleReconcileProfiles(t *testing.T) {
ctx := context.Background()
mdmStorage := &nanomdm_mock.Storage{}
ds := new(mock.Store)
pushFactory, _ := newMockAPNSPushProviderFactory()
pusher := nanomdm_pushsvc.New(
mdmStorage,
mdmStorage,
pushFactory,
NewNanoMDMLogger(kitlog.NewNopLogger()),
)
cmdr := apple_mdm.NewMDMAppleCommander(mdmStorage, pusher)
hostUUID, hostUUID2 := "ABC-DEF", "GHI-JKL"
contents1 := []byte("test-content-1")
contents1Base64 := base64.StdEncoding.EncodeToString(contents1)
contents2 := []byte("test-content-2")
contents2Base64 := base64.StdEncoding.EncodeToString(contents2)
contents4 := []byte("test-content-4")
contents4Base64 := base64.StdEncoding.EncodeToString(contents4)
ds.ListMDMAppleProfilesToInstallFunc = func(ctx context.Context) ([]*fleet.MDMAppleProfilePayload, error) {
return []*fleet.MDMAppleProfilePayload{
{ProfileID: 1, ProfileIdentifier: "com.add.profile", HostUUID: hostUUID},
{ProfileID: 2, ProfileIdentifier: "com.add.profile.two", HostUUID: hostUUID},
{ProfileID: 2, ProfileIdentifier: "com.add.profile.two", HostUUID: hostUUID2},
{ProfileID: 4, ProfileIdentifier: "com.add.profile.four", HostUUID: hostUUID2},
}, nil
}
ds.ListMDMAppleProfilesToRemoveFunc = func(ctx context.Context) ([]*fleet.MDMAppleProfilePayload, error) {
return []*fleet.MDMAppleProfilePayload{
{ProfileID: 3, ProfileIdentifier: "com.remove.profile", HostUUID: hostUUID},
{ProfileID: 3, ProfileIdentifier: "com.remove.profile", HostUUID: hostUUID2},
}, nil
}
ds.GetMDMAppleProfilesContentsFunc = func(ctx context.Context, profileIDs []uint) (map[uint]mobileconfig.Mobileconfig, error) {
require.ElementsMatch(t, []uint{1, 2, 4}, profileIDs)
// only those profiles that are to be installed
return map[uint]mobileconfig.Mobileconfig{
1: contents1,
2: contents2,
4: contents4,
}, nil
}
var enqueueFailForOp fleet.MDMAppleOperationType
mdmStorage.EnqueueCommandFunc = func(ctx context.Context, id []string, cmd *mdm.Command) (map[string]error, error) {
require.NotNil(t, cmd)
require.NotEmpty(t, cmd.CommandUUID)
switch cmd.Command.RequestType {
case "InstallProfile":
// may be called for a single host or both
if len(id) == 2 {
require.ElementsMatch(t, []string{hostUUID, hostUUID2}, id)
} else {
require.Len(t, id, 1)
}
if !strings.Contains(string(cmd.Raw), contents1Base64) && !strings.Contains(string(cmd.Raw), contents2Base64) &&
!strings.Contains(string(cmd.Raw), contents4Base64) {
require.Failf(t, "profile contents don't match", "expected to contain %s, %s or %s but got %s",
contents1Base64, contents2Base64, contents4Base64, string(cmd.Raw))
}
case "RemoveProfile":
require.ElementsMatch(t, []string{hostUUID, hostUUID2}, id)
require.Contains(t, string(cmd.Raw), "com.remove.profile")
}
switch {
case enqueueFailForOp == fleet.MDMAppleOperationTypeInstall && cmd.Command.RequestType == "InstallProfile":
return nil, errors.New("enqueue error")
case enqueueFailForOp == fleet.MDMAppleOperationTypeRemove && cmd.Command.RequestType == "RemoveProfile":
return nil, errors.New("enqueue error")
}
return nil, nil
}
mdmStorage.RetrievePushInfoFunc = func(ctx context.Context, tokens []string) (map[string]*mdm.Push, error) {
res := make(map[string]*mdm.Push, len(tokens))
for _, t := range tokens {
res[t] = &mdm.Push{
PushMagic: "",
Token: []byte(t),
Topic: "",
}
}
return res, nil
}
mdmStorage.RetrievePushCertFunc = func(ctx context.Context, topic string) (*tls.Certificate, string, error) {
cert, err := tls.LoadX509KeyPair("testdata/server.pem", "testdata/server.key")
return &cert, "", err
}
mdmStorage.IsPushCertStaleFunc = func(ctx context.Context, topic string, staleToken string) (bool, error) {
return false, nil
}
var failedCall bool
var failedCheck func([]*fleet.MDMAppleBulkUpsertHostProfilePayload)
ds.BulkUpsertMDMAppleHostProfilesFunc = func(ctx context.Context, payload []*fleet.MDMAppleBulkUpsertHostProfilePayload) error {
if failedCall {
failedCheck(payload)
return nil
}
// next call will be failed call, until reset
failedCall = true
// first time it is called, it is to set the status to pending and all
// host profiles have a command uuid
cmdUUIDByProfileIDInstall := make(map[uint]string)
cmdUUIDByProfileIDRemove := make(map[uint]string)
copies := make([]*fleet.MDMAppleBulkUpsertHostProfilePayload, len(payload))
for i, p := range payload {
if p.OperationType == fleet.MDMAppleOperationTypeInstall {
existing, ok := cmdUUIDByProfileIDInstall[p.ProfileID]
if ok {
require.Equal(t, existing, p.CommandUUID)
} else {
cmdUUIDByProfileIDInstall[p.ProfileID] = p.CommandUUID
}
} else {
require.Equal(t, fleet.MDMAppleOperationTypeRemove, p.OperationType)
existing, ok := cmdUUIDByProfileIDRemove[p.ProfileID]
if ok {
require.Equal(t, existing, p.CommandUUID)
} else {
cmdUUIDByProfileIDRemove[p.ProfileID] = p.CommandUUID
}
}
// clear the command UUID (in a copy so that it does not affect the
// pointed-to struct) from the payload for the subsequent checks
copyp := *p
copyp.CommandUUID = ""
copies[i] = &copyp
}
require.ElementsMatch(t, []*fleet.MDMAppleBulkUpsertHostProfilePayload{
{
ProfileID: 1,
ProfileIdentifier: "com.add.profile",
HostUUID: hostUUID,
OperationType: fleet.MDMAppleOperationTypeInstall,
Status: &fleet.MDMAppleDeliveryPending,
},
{
ProfileID: 2,
ProfileIdentifier: "com.add.profile.two",
HostUUID: hostUUID,
OperationType: fleet.MDMAppleOperationTypeInstall,
Status: &fleet.MDMAppleDeliveryPending,
},
{
ProfileID: 2,
ProfileIdentifier: "com.add.profile.two",
HostUUID: hostUUID2,
OperationType: fleet.MDMAppleOperationTypeInstall,
Status: &fleet.MDMAppleDeliveryPending,
},
{
ProfileID: 3,
ProfileIdentifier: "com.remove.profile",
HostUUID: hostUUID,
OperationType: fleet.MDMAppleOperationTypeRemove,
Status: &fleet.MDMAppleDeliveryPending,
},
{
ProfileID: 3,
ProfileIdentifier: "com.remove.profile",
HostUUID: hostUUID2,
OperationType: fleet.MDMAppleOperationTypeRemove,
Status: &fleet.MDMAppleDeliveryPending,
},
{
ProfileID: 4,
ProfileIdentifier: "com.add.profile.four",
HostUUID: hostUUID2,
OperationType: fleet.MDMAppleOperationTypeInstall,
Status: &fleet.MDMAppleDeliveryPending,
},
}, copies)
return nil
}
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
appCfg := &fleet.AppConfig{}
appCfg.ServerSettings.ServerURL = "https://test.example.com"
return appCfg, nil
}
ds.BulkUpsertMDMAppleConfigProfilesFunc = func(ctx context.Context, p []*fleet.MDMAppleConfigProfile) error {
return nil
}
ds.AggregateEnrollSecretPerTeamFunc = func(ctx context.Context) ([]*fleet.EnrollSecret, error) {
return []*fleet.EnrollSecret{}, nil
}
checkAndReset := func(t *testing.T, want bool, invoked *bool) {
if want {
require.True(t, *invoked)
} else {
require.False(t, *invoked)
}
*invoked = false
}
t.Run("success", func(t *testing.T) {
var failedCount int
failedCall = false
failedCheck = func(payload []*fleet.MDMAppleBulkUpsertHostProfilePayload) {
failedCount++
require.Len(t, payload, 0)
}
err := ReconcileProfiles(ctx, ds, cmdr, kitlog.NewNopLogger())
require.NoError(t, err)
require.Equal(t, 1, failedCount)
checkAndReset(t, true, &ds.ListMDMAppleProfilesToInstallFuncInvoked)
checkAndReset(t, true, &ds.ListMDMAppleProfilesToRemoveFuncInvoked)
checkAndReset(t, true, &ds.GetMDMAppleProfilesContentsFuncInvoked)
checkAndReset(t, true, &ds.BulkUpsertMDMAppleHostProfilesFuncInvoked)
})
t.Run("fail enqueue remove ops", func(t *testing.T) {
var failedCount int
failedCall = false
failedCheck = func(payload []*fleet.MDMAppleBulkUpsertHostProfilePayload) {
failedCount++
require.Len(t, payload, 2) // the 2 remove ops
require.ElementsMatch(t, []*fleet.MDMAppleBulkUpsertHostProfilePayload{
{
ProfileID: 3,
ProfileIdentifier: "com.remove.profile",
HostUUID: hostUUID,
OperationType: fleet.MDMAppleOperationTypeRemove,
Status: nil,
CommandUUID: "",
},
{
ProfileID: 3,
ProfileIdentifier: "com.remove.profile",
HostUUID: hostUUID2,
OperationType: fleet.MDMAppleOperationTypeRemove,
Status: nil,
CommandUUID: "",
},
}, payload)
}
enqueueFailForOp = fleet.MDMAppleOperationTypeRemove
err := ReconcileProfiles(ctx, ds, cmdr, kitlog.NewNopLogger())
require.NoError(t, err)
require.Equal(t, 1, failedCount)
checkAndReset(t, true, &ds.ListMDMAppleProfilesToInstallFuncInvoked)
checkAndReset(t, true, &ds.ListMDMAppleProfilesToRemoveFuncInvoked)
checkAndReset(t, true, &ds.GetMDMAppleProfilesContentsFuncInvoked)
checkAndReset(t, true, &ds.BulkUpsertMDMAppleHostProfilesFuncInvoked)
})
t.Run("fail enqueue install ops", func(t *testing.T) {
var failedCount int
failedCall = false
failedCheck = func(payload []*fleet.MDMAppleBulkUpsertHostProfilePayload) {
failedCount++
require.Len(t, payload, 4) // the 4 install ops
require.ElementsMatch(t, []*fleet.MDMAppleBulkUpsertHostProfilePayload{
{
ProfileID: 1,
ProfileIdentifier: "com.add.profile",
HostUUID: hostUUID,
OperationType: fleet.MDMAppleOperationTypeInstall,
Status: nil,
CommandUUID: "",
},
{
ProfileID: 2,
ProfileIdentifier: "com.add.profile.two",
HostUUID: hostUUID,
OperationType: fleet.MDMAppleOperationTypeInstall,
Status: nil,
CommandUUID: "",
},
{
ProfileID: 2,
ProfileIdentifier: "com.add.profile.two",
HostUUID: hostUUID2,
OperationType: fleet.MDMAppleOperationTypeInstall,
Status: nil,
CommandUUID: "",
},
{
ProfileID: 4,
ProfileIdentifier: "com.add.profile.four",
HostUUID: hostUUID2,
OperationType: fleet.MDMAppleOperationTypeInstall,
Status: nil,
CommandUUID: "",
},
}, payload)
}
enqueueFailForOp = fleet.MDMAppleOperationTypeInstall
err := ReconcileProfiles(ctx, ds, cmdr, kitlog.NewNopLogger())
require.NoError(t, err)
require.Equal(t, 1, failedCount)
checkAndReset(t, true, &ds.ListMDMAppleProfilesToInstallFuncInvoked)
checkAndReset(t, true, &ds.ListMDMAppleProfilesToRemoveFuncInvoked)
checkAndReset(t, true, &ds.GetMDMAppleProfilesContentsFuncInvoked)
checkAndReset(t, true, &ds.BulkUpsertMDMAppleHostProfilesFuncInvoked)
})
}
func TestAppleMDMFileVaultEscrowFunctions(t *testing.T) {
svc := Service{}
err := svc.MDMAppleEnableFileVaultAndEscrow(context.Background(), ptr.Uint(1))
require.ErrorIs(t, fleet.ErrMissingLicense, err)
err = svc.MDMAppleDisableFileVaultAndEscrow(context.Background(), ptr.Uint(1))
require.ErrorIs(t, fleet.ErrMissingLicense, err)
}
func TestGenerateEnrollmentProfileMobileConfig(t *testing.T) {
// SCEP challenge should be escaped for XML
b, err := apple_mdm.GenerateEnrollmentProfileMobileconfig("foo", "https://example.com", "foo&bar", "topic")
require.NoError(t, err)
require.Contains(t, string(b), "foo&amp;bar")
}
func TestEnsureFleetdConfig(t *testing.T) {
testError := errors.New("test error")
testURL := "https://example.com"
testTeamName := "test-team"
logger := kitlog.NewNopLogger()
t.Run("no enroll secret found", func(t *testing.T) {
ctx := context.Background()
ds := new(mock.Store)
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return &fleet.AppConfig{}, nil
}
ds.AggregateEnrollSecretPerTeamFunc = func(ctx context.Context) ([]*fleet.EnrollSecret, error) {
return []*fleet.EnrollSecret{}, nil
}
ds.BulkUpsertMDMAppleConfigProfilesFunc = func(ctx context.Context, ps []*fleet.MDMAppleConfigProfile) error {
require.Empty(t, ps)
return nil
}
err := ensureFleetdConfig(ctx, ds, logger)
require.NoError(t, err)
require.True(t, ds.BulkUpsertMDMAppleConfigProfilesFuncInvoked)
require.True(t, ds.AggregateEnrollSecretPerTeamFuncInvoked)
require.True(t, ds.AppConfigFuncInvoked)
})
t.Run("all enroll secrets empty", func(t *testing.T) {
ctx := context.Background()
ds := new(mock.Store)
secrets := []*fleet.EnrollSecret{
{Secret: "", TeamID: nil},
{Secret: "", TeamID: ptr.Uint(1)},
{Secret: "", TeamID: ptr.Uint(2)},
}
ds.AggregateEnrollSecretPerTeamFunc = func(ctx context.Context) ([]*fleet.EnrollSecret, error) {
return secrets, nil
}
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return &fleet.AppConfig{}, nil
}
ds.BulkUpsertMDMAppleConfigProfilesFunc = func(ctx context.Context, ps []*fleet.MDMAppleConfigProfile) error {
require.Empty(t, ps)
return nil
}
err := ensureFleetdConfig(ctx, ds, logger)
require.NoError(t, err)
require.True(t, ds.BulkUpsertMDMAppleConfigProfilesFuncInvoked)
require.True(t, ds.AggregateEnrollSecretPerTeamFuncInvoked)
require.True(t, ds.AppConfigFuncInvoked)
})
t.Run("uses the enroll secret of each team if available", func(t *testing.T) {
ctx := context.Background()
ds := new(mock.Store)
secrets := []*fleet.EnrollSecret{
{Secret: "global", TeamID: nil},
{Secret: "team-1", TeamID: ptr.Uint(1)},
{Secret: "team-2", TeamID: ptr.Uint(2)},
}
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
appCfg := &fleet.AppConfig{}
appCfg.ServerSettings.ServerURL = testURL
appCfg.MDM.AppleBMDefaultTeam = testTeamName
return appCfg, nil
}
ds.AggregateEnrollSecretPerTeamFunc = func(ctx context.Context) ([]*fleet.EnrollSecret, error) {
return secrets, nil
}
ds.BulkUpsertMDMAppleConfigProfilesFunc = func(ctx context.Context, ps []*fleet.MDMAppleConfigProfile) error {
require.Len(t, ps, len(secrets))
for i, p := range ps {
require.Contains(t, string(p.Mobileconfig), testURL)
require.Contains(t, string(p.Mobileconfig), secrets[i].Secret)
require.Equal(t, mobileconfig.FleetdConfigPayloadIdentifier, p.Identifier)
}
return nil
}
err := ensureFleetdConfig(ctx, ds, logger)
require.NoError(t, err)
require.True(t, ds.AggregateEnrollSecretPerTeamFuncInvoked)
require.True(t, ds.BulkUpsertMDMAppleConfigProfilesFuncInvoked)
})
t.Run("if the team doesn't have an enroll secret, fallback to no team", func(t *testing.T) {
ctx := context.Background()
ds := new(mock.Store)
secrets := []*fleet.EnrollSecret{
{Secret: "global", TeamID: nil},
{Secret: "", TeamID: ptr.Uint(1)},
}
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
appCfg := &fleet.AppConfig{}
appCfg.ServerSettings.ServerURL = testURL
appCfg.MDM.AppleBMDefaultTeam = testTeamName
return appCfg, nil
}
ds.AggregateEnrollSecretPerTeamFunc = func(ctx context.Context) ([]*fleet.EnrollSecret, error) {
return secrets, nil
}
ds.BulkUpsertMDMAppleConfigProfilesFunc = func(ctx context.Context, ps []*fleet.MDMAppleConfigProfile) error {
require.Len(t, ps, len(secrets))
for i, p := range ps {
require.Contains(t, string(p.Mobileconfig), testURL)
require.Contains(t, string(p.Mobileconfig), secrets[i].Secret)
require.Equal(t, mobileconfig.FleetdConfigPayloadIdentifier, p.Identifier)
}
return nil
}
err := ensureFleetdConfig(ctx, ds, logger)
require.NoError(t, err)
require.True(t, ds.AppConfigFuncInvoked)
require.True(t, ds.AggregateEnrollSecretPerTeamFuncInvoked)
require.True(t, ds.BulkUpsertMDMAppleConfigProfilesFuncInvoked)
})
t.Run("returns an error if there's a problem retrieving AppConfig", func(t *testing.T) {
ctx := context.Background()
ds := new(mock.Store)
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return nil, testError
}
err := ensureFleetdConfig(ctx, ds, logger)
require.ErrorIs(t, err, testError)
})
t.Run("returns an error if there's a problem retrieving secrets", func(t *testing.T) {
ctx := context.Background()
ds := new(mock.Store)
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return &fleet.AppConfig{}, nil
}
ds.AggregateEnrollSecretPerTeamFunc = func(ctx context.Context) ([]*fleet.EnrollSecret, error) {
return nil, testError
}
err := ensureFleetdConfig(ctx, ds, logger)
require.ErrorIs(t, err, testError)
})
t.Run("returns an error if there's a problem upserting profiles", func(t *testing.T) {
ctx := context.Background()
ds := new(mock.Store)
secrets := []*fleet.EnrollSecret{
{Secret: "global", TeamID: nil},
{Secret: "team-1", TeamID: ptr.Uint(1)},
}
ds.AggregateEnrollSecretPerTeamFunc = func(ctx context.Context) ([]*fleet.EnrollSecret, error) {
return secrets, nil
}
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return &fleet.AppConfig{}, nil
}
ds.BulkUpsertMDMAppleConfigProfilesFunc = func(ctx context.Context, p []*fleet.MDMAppleConfigProfile) error {
return testError
}
err := ensureFleetdConfig(ctx, ds, logger)
require.ErrorIs(t, err, testError)
require.True(t, ds.AppConfigFuncInvoked)
require.True(t, ds.AggregateEnrollSecretPerTeamFuncInvoked)
require.True(t, ds.BulkUpsertMDMAppleConfigProfilesFuncInvoked)
})
}
func TestMDMAppleSetupAssistant(t *testing.T) {
svc, ctx, ds := setupAppleMDMService(t, &fleet.LicenseInfo{Tier: fleet.TierPremium})
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activity fleet.ActivityDetails) error {
return nil
}
ds.NewJobFunc = func(ctx context.Context, j *fleet.Job) (*fleet.Job, error) {
return j, nil
}
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return &fleet.AppConfig{}, nil
}
ds.GetMDMAppleSetupAssistantFunc = func(ctx context.Context, teamID *uint) (*fleet.MDMAppleSetupAssistant, error) {
return &fleet.MDMAppleSetupAssistant{}, nil
}
ds.SetOrUpdateMDMAppleSetupAssistantFunc = func(ctx context.Context, asst *fleet.MDMAppleSetupAssistant) (*fleet.MDMAppleSetupAssistant, error) {
return asst, nil
}
ds.DeleteMDMAppleSetupAssistantFunc = func(ctx context.Context, teamID *uint) error {
return nil
}
ds.TeamFunc = func(ctx context.Context, id uint) (*fleet.Team, error) {
return &fleet.Team{ID: id}, nil
}
testCases := []struct {
name string
user *fleet.User
teamID *uint
shouldFailRead bool
shouldFailWrite bool
}{
{"no role no team", test.UserNoRoles, nil, true, true},
{"no role team", test.UserNoRoles, ptr.Uint(1), true, true},
{"global admin no team", test.UserAdmin, nil, false, false},
{"global admin team", test.UserAdmin, ptr.Uint(1), false, false},
{"global maintainer no team", test.UserMaintainer, nil, false, false},
{"global maintainer team", test.UserMaintainer, ptr.Uint(1), false, false},
{"global observer no team", test.UserObserver, nil, true, true},
{"global observer team", test.UserObserver, ptr.Uint(1), true, true},
{"global observer+ no team", test.UserObserverPlus, nil, true, true},
{"global observer+ team", test.UserObserverPlus, ptr.Uint(1), true, true},
{"global gitops no team", test.UserGitOps, nil, true, false},
{"global gitops team", test.UserGitOps, ptr.Uint(1), true, false},
{"team admin no team", test.UserTeamAdminTeam1, nil, true, true},
{"team admin team", test.UserTeamAdminTeam1, ptr.Uint(1), false, false},
{"team admin other team", test.UserTeamAdminTeam2, ptr.Uint(1), true, true},
{"team maintainer no team", test.UserTeamMaintainerTeam1, nil, true, true},
{"team maintainer team", test.UserTeamMaintainerTeam1, ptr.Uint(1), false, false},
{"team maintainer other team", test.UserTeamMaintainerTeam2, ptr.Uint(1), true, true},
{"team observer no team", test.UserTeamObserverTeam1, nil, true, true},
{"team observer team", test.UserTeamObserverTeam1, ptr.Uint(1), true, true},
{"team observer other team", test.UserTeamObserverTeam2, ptr.Uint(1), true, true},
{"team observer+ no team", test.UserTeamObserverPlusTeam1, nil, true, true},
{"team observer+ team", test.UserTeamObserverPlusTeam1, ptr.Uint(1), true, true},
{"team observer+ other team", test.UserTeamObserverPlusTeam2, ptr.Uint(1), true, true},
{"team gitops no team", test.UserTeamGitOpsTeam1, nil, true, true},
{"team gitops team", test.UserTeamGitOpsTeam1, ptr.Uint(1), true, false},
{"team gitops other team", test.UserTeamGitOpsTeam2, ptr.Uint(1), true, true},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
// prepare the context with the user and license
ctx := viewer.NewContext(ctx, viewer.Viewer{User: tt.user})
_, err := svc.GetMDMAppleSetupAssistant(ctx, tt.teamID)
checkAuthErr(t, tt.shouldFailRead, err)
_, err = svc.SetOrUpdateMDMAppleSetupAssistant(ctx, &fleet.MDMAppleSetupAssistant{
Name: "test",
Profile: json.RawMessage("{}"),
TeamID: tt.teamID,
})
checkAuthErr(t, tt.shouldFailWrite, err)
err = svc.DeleteMDMAppleSetupAssistant(ctx, tt.teamID)
checkAuthErr(t, tt.shouldFailWrite, err)
})
}
}
func mobileconfigForTest(name, identifier string) []byte {
return []byte(fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array/>
<key>PayloadDisplayName</key>
<string>%s</string>
<key>PayloadIdentifier</key>
<string>%s</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>%s</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>
`, name, identifier, uuid.New().String()))
}
func mobileconfigForTestWithContent(name, identifier, inneridentifier, innertype string) []byte {
return []byte(fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadDisplayName</key>
<string>%s</string>
<key>PayloadIdentifier</key>
<string>%s</string>
<key>PayloadType</key>
<string>%s</string>
<key>PayloadUUID</key>
<string>3548D750-6357-4910-8DEA-D80ADCE2C787</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>ShowRecoveryKey</key>
<false/>
</dict>
</array>
<key>PayloadDisplayName</key>
<string>%s</string>
<key>PayloadIdentifier</key>
<string>%s</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>%s</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>
`, name+".inner", inneridentifier, innertype, name, identifier, uuid.New().String()))
}