mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
Add tool to get a profile as defined in Apple BM (#18274)
This commit is contained in:
parent
3e8ebf84cf
commit
ea0da5e2fa
3 changed files with 48 additions and 4 deletions
|
|
@ -94,6 +94,26 @@ func (c *Client) SyncDevices(ctx context.Context, name string, opts ...DeviceReq
|
||||||
return resp, c.doWithAfterHook(ctx, name, http.MethodPost, "/devices/sync", req, resp)
|
return resp, c.doWithAfterHook(ctx, name, http.MethodPost, "/devices/sync", req, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDevicesDetails uses the Apple "Get Device Details" API endpoint to
|
||||||
|
// retrieve the details (such as its assigned enrollment profile UUID) for the
|
||||||
|
// specified device, identified by its serial number.
|
||||||
|
// See https://developer.apple.com/documentation/devicemanagement/get_device_details
|
||||||
|
func (c *Client) GetDeviceDetails(ctx context.Context, name, serialNumber string) (*Device, error) {
|
||||||
|
type request struct {
|
||||||
|
Devices []string `json:"devices"`
|
||||||
|
}
|
||||||
|
type response struct {
|
||||||
|
Devices map[string]*Device `json:"devices"`
|
||||||
|
}
|
||||||
|
resp := new(response)
|
||||||
|
if err := c.doWithAfterHook(ctx, name, http.MethodPost, "/devices", request{
|
||||||
|
Devices: []string{serialNumber},
|
||||||
|
}, resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resp.Devices[serialNumber], nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsCursorExhausted returns true if err is a DEP "exhausted cursor" error.
|
// IsCursorExhausted returns true if err is a DEP "exhausted cursor" error.
|
||||||
func IsCursorExhausted(err error) bool {
|
func IsCursorExhausted(err error) bool {
|
||||||
return httpErrorContains(err, http.StatusBadRequest, "EXHAUSTED_CURSOR")
|
return httpErrorContains(err, http.StatusBadRequest, "EXHAUSTED_CURSOR")
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ package godep
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Profile corresponds to the Apple DEP API "Profile" structure.
|
// Profile corresponds to the Apple DEP API "Profile" structure.
|
||||||
|
|
@ -75,3 +77,12 @@ func (c *Client) DefineProfile(ctx context.Context, name string, profile *Profil
|
||||||
resp := new(ProfileResponse)
|
resp := new(ProfileResponse)
|
||||||
return resp, c.doWithAfterHook(ctx, name, http.MethodPost, "/profile", profile, resp)
|
return resp, c.doWithAfterHook(ctx, name, http.MethodPost, "/profile", profile, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetProfile uses the Apple "Get a Profile" API endpoint to get the details
|
||||||
|
// for the specified profile UUID.
|
||||||
|
// See https://developer.apple.com/documentation/devicemanagement/get_a_profile
|
||||||
|
func (c *Client) GetProfile(ctx context.Context, name, profileUUID string) (*json.RawMessage, error) {
|
||||||
|
resp := &json.RawMessage{}
|
||||||
|
qs := url.Values{"profile_uuid": {profileUUID}}
|
||||||
|
return resp, c.doWithAfterHook(ctx, name, http.MethodGet, "/profile?"+qs.Encode(), nil, resp)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Command getaccount takes an Apple Business Manager server token in decrypted
|
// Command applebmapi takes an Apple Business Manager server token in decrypted
|
||||||
// JSON format and calls the Apple BM API to retrieve and print the account
|
// JSON format and calls the Apple BM API to retrieve and print the account
|
||||||
// information.
|
// information or the specified enrollment profile.
|
||||||
//
|
//
|
||||||
// Was implemented to test out https://github.com/fleetdm/fleet/issues/7515#issuecomment-1330889768,
|
// Was implemented to test out https://github.com/fleetdm/fleet/issues/7515#issuecomment-1330889768,
|
||||||
// and can still be useful for debugging purposes.
|
// and can still be useful for debugging purposes.
|
||||||
|
|
@ -27,12 +27,18 @@ import (
|
||||||
func main() {
|
func main() {
|
||||||
mysqlAddr := flag.String("mysql", "localhost:3306", "mysql address")
|
mysqlAddr := flag.String("mysql", "localhost:3306", "mysql address")
|
||||||
appleBMToken := flag.String("apple-bm-token", "", "path to (decrypted) Apple BM token")
|
appleBMToken := flag.String("apple-bm-token", "", "path to (decrypted) Apple BM token")
|
||||||
|
profileUUID := flag.String("profile-uuid", "", "the Apple profile UUID to retrieve")
|
||||||
|
serialNum := flag.String("serial-number", "", "serial number of a device to get the device details")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if *appleBMToken == "" {
|
if *appleBMToken == "" {
|
||||||
log.Fatal("must provide Apple BM token")
|
log.Fatal("must provide Apple BM token")
|
||||||
}
|
}
|
||||||
|
if *profileUUID != "" && *serialNum != "" {
|
||||||
|
log.Fatal("only one of -profile-uuid or -serial-number must be provided")
|
||||||
|
}
|
||||||
|
|
||||||
tok, err := os.ReadFile(*appleBMToken)
|
tok, err := os.ReadFile(*appleBMToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|
@ -64,11 +70,18 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
depClient := godep.NewClient(depStorage, fleethttp.NewClient())
|
depClient := godep.NewClient(depStorage, fleethttp.NewClient())
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
res, err := depClient.AccountDetail(ctx, apple_mdm.DEPName)
|
var res any
|
||||||
|
switch {
|
||||||
|
case *profileUUID != "":
|
||||||
|
res, err = depClient.GetProfile(ctx, apple_mdm.DEPName, *profileUUID)
|
||||||
|
case *serialNum != "":
|
||||||
|
res, err = depClient.GetDeviceDetails(ctx, apple_mdm.DEPName, *serialNum)
|
||||||
|
default:
|
||||||
|
res, err = depClient.AccountDetail(ctx, apple_mdm.DEPName)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue