mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
feat: get Apple MDM CSR endpoint (#19253)
> Related issue: #19014 # Checklist for submitter If some of the following don't apply, delete the relevant line. <!-- Note that API documentation changes are now addressed by the product design team. --> - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://fleetdm.com/docs/contributing/committing-changes#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements) - [x] Added/updated tests - [x] Manual QA for all new/changed functionality
This commit is contained in:
commit
23e773c213
12 changed files with 310 additions and 11 deletions
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
|
@ -38,6 +38,5 @@
|
|||
"prettier.requireConfig": true,
|
||||
"yaml.schemas": {
|
||||
"https://json.schemastore.org/codecov.json": ".github/workflows/codecov.yml"
|
||||
},
|
||||
"favorites.sortOrder": "ASC"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
changes/19014-certs-endpoints
Normal file
2
changes/19014-certs-endpoints
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
- Adds a `GET /fleet/mdm/apple/request_csr` endpoint, which returns the signed APNS CSR needed to
|
||||
activate Apple MDM.
|
||||
|
|
@ -4145,3 +4145,27 @@ VALUES
|
|||
|
||||
return ctxerr.Wrap(ctx, err, "writing mdm config assets to db")
|
||||
}
|
||||
|
||||
func (ds *Datastore) GetMDMConfigAssetsByName(ctx context.Context, assetNames []fleet.MDMAssetName) ([]fleet.MDMConfigAsset, error) {
|
||||
stmt := `
|
||||
SELECT
|
||||
name, value
|
||||
FROM
|
||||
mdm_config_assets
|
||||
WHERE
|
||||
name IN (?)
|
||||
AND deletion_uuid = ''
|
||||
`
|
||||
|
||||
stmt, args, err := sqlx.In(stmt, assetNames)
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "sqlx.In GetMDMConfigAssetsByName")
|
||||
}
|
||||
|
||||
var res []fleet.MDMConfigAsset
|
||||
if err := sqlx.SelectContext(ctx, ds.reader(ctx), &res, stmt, args...); err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "get mdm config assets by name")
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ func TestMDMApple(t *testing.T) {
|
|||
{"MDMAppleSetPendingDeclarationsAs", testMDMAppleSetPendingDeclarationsAs},
|
||||
{"SetOrUpdateMDMAppleDeclaration", testSetOrUpdateMDMAppleDDMDeclaration},
|
||||
{"DEPAssignmentUpdates", testMDMAppleDEPAssignmentUpdates},
|
||||
{"TestInsertMDMAsset", testInsertMDMAsset},
|
||||
{"TestInsertMDMAsset", testMDMConfigAsset},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
|
|
@ -5499,7 +5499,7 @@ func createRawAppleCmd(reqType, cmdUUID string) string {
|
|||
</plist>`, reqType, cmdUUID)
|
||||
}
|
||||
|
||||
func testInsertMDMAsset(t *testing.T, ds *Datastore) {
|
||||
func testMDMConfigAsset(t *testing.T, ds *Datastore) {
|
||||
ctx := context.Background()
|
||||
assets := []fleet.MDMConfigAsset{
|
||||
{
|
||||
|
|
@ -5508,15 +5508,14 @@ func testInsertMDMAsset(t *testing.T, ds *Datastore) {
|
|||
},
|
||||
{
|
||||
Name: fleet.MDMAssetCAKey,
|
||||
Value: []byte("some bytes"),
|
||||
Value: []byte("some other bytes"),
|
||||
},
|
||||
}
|
||||
|
||||
err := ds.InsertMDMConfigAssets(ctx, assets)
|
||||
require.NoError(t, err)
|
||||
|
||||
var a []fleet.MDMConfigAsset
|
||||
|
||||
require.NoError(t, sqlx.SelectContext(ctx, ds.reader(ctx), &a, `SELECT name, value FROM mdm_config_assets`))
|
||||
require.Len(t, a, 2)
|
||||
a, err := ds.GetMDMConfigAssetsByName(ctx, []fleet.MDMAssetName{fleet.MDMAssetCACert, fleet.MDMAssetCAKey})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, assets, a)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1249,8 +1249,12 @@ type Datastore interface {
|
|||
// the provided value.
|
||||
MDMAppleSetPendingDeclarationsAs(ctx context.Context, hostUUID string, status *MDMDeliveryStatus, detail string) error
|
||||
|
||||
// InsertMDMConfigAssets inserts MDM related config assets, such as SCEP and APNS certs and keys.
|
||||
InsertMDMConfigAssets(ctx context.Context, assets []MDMConfigAsset) error
|
||||
|
||||
// GetMDMConfigAssetsByName returns the requested config assets.
|
||||
GetMDMConfigAssetsByName(ctx context.Context, assetNames []MDMAssetName) ([]MDMConfigAsset, error)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Microsoft MDM
|
||||
|
||||
|
|
|
|||
|
|
@ -689,6 +689,11 @@ type Service interface {
|
|||
GetAppleBM(ctx context.Context) (*AppleBM, error)
|
||||
RequestMDMAppleCSR(ctx context.Context, email, org string) (*AppleCSR, error)
|
||||
|
||||
// GetMDMAppleCSR returns a signed CSR as base64 encoded bytes for Apple MDM. The first time
|
||||
// this method is called, it will create a SCEP certificate, a SCEP key, and an APNS key and
|
||||
// write these to the DB. On subsequent calls, it will use the saved APNS key for generating the CSR.
|
||||
GetMDMAppleCSR(ctx context.Context) ([]byte, error)
|
||||
|
||||
// GetHostDEPAssignment retrieves the host DEP assignment for the specified host.
|
||||
GetHostDEPAssignment(ctx context.Context, host *Host) (*HostDEPAssignment, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,36 @@ func GenerateAPNSCSRKey(email, org string) (*x509.CertificateRequest, *rsa.Priva
|
|||
return certReq, key, nil
|
||||
}
|
||||
|
||||
func GenerateAPNSCSR(org, email string, key *rsa.PrivateKey) (*x509.CertificateRequest, error) {
|
||||
subj := pkix.Name{
|
||||
Organization: []string{org},
|
||||
ExtraNames: []pkix.AttributeTypeAndValue{{
|
||||
Type: emailAddressOID,
|
||||
Value: email,
|
||||
}},
|
||||
}
|
||||
template := &x509.CertificateRequest{
|
||||
Subject: subj,
|
||||
SignatureAlgorithm: x509.SHA256WithRSA,
|
||||
}
|
||||
|
||||
b, err := x509.CreateCertificateRequest(rand.Reader, template, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
certReq, err := x509.ParseCertificateRequest(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return certReq, nil
|
||||
}
|
||||
|
||||
func NewPrivateKey() (*rsa.PrivateKey, error) {
|
||||
return newPrivateKey()
|
||||
}
|
||||
|
||||
type FleetWebsiteError struct {
|
||||
Status int
|
||||
message string
|
||||
|
|
@ -116,6 +146,55 @@ func GetSignedAPNSCSR(client *http.Client, csr *x509.CertificateRequest) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
type WebsiteResponse struct {
|
||||
CSR []byte `json:"csr"`
|
||||
}
|
||||
|
||||
// GetSignedAPNSCSRNoEmail makes a request to the fleetdm.com API to get a signed APNs
|
||||
// CSR and returns the signed CSR directly.
|
||||
func GetSignedAPNSCSRNoEmail(client *http.Client, csr *x509.CertificateRequest) ([]byte, error) {
|
||||
csrPEM := EncodeCertRequestPEM(csr)
|
||||
|
||||
payload := getSignedAPNSCSRRequest{
|
||||
UnsignedCSRData: csrPEM,
|
||||
}
|
||||
|
||||
b, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal payload: %w", err)
|
||||
}
|
||||
|
||||
// for testing
|
||||
baseURL := defaultFleetDMAPIURL
|
||||
if x := os.Getenv("TEST_FLEETDM_API_URL"); x != "" {
|
||||
baseURL = strings.TrimRight(x, "/")
|
||||
}
|
||||
u := baseURL + getSignedAPNSCSRPath + "?deliveryMethod=json"
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, u, bytes.NewReader(b))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating csr signing request for fleetdm api: %w", err)
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("sending csr signing request to fleetdm api: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBytes, _ := io.ReadAll(resp.Body)
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, FleetWebsiteError{Status: resp.StatusCode, message: string(respBytes)}
|
||||
}
|
||||
|
||||
var csrResp WebsiteResponse
|
||||
if err := json.Unmarshal(respBytes, &csrResp); err != nil {
|
||||
return nil, fmt.Errorf("unmarshalling signed csr response from fleetdm api: %w", err)
|
||||
}
|
||||
|
||||
return csrResp.CSR, nil
|
||||
}
|
||||
|
||||
// NewSCEPCACertKey creates a self-signed CA certificate for use with SCEP and
|
||||
// returns the certificate and its private key.
|
||||
func NewSCEPCACertKey() (*x509.Certificate, *rsa.PrivateKey, error) {
|
||||
|
|
|
|||
|
|
@ -823,6 +823,8 @@ type MDMAppleSetPendingDeclarationsAsFunc func(ctx context.Context, hostUUID str
|
|||
|
||||
type InsertMDMConfigAssetsFunc func(ctx context.Context, assets []fleet.MDMConfigAsset) error
|
||||
|
||||
type GetMDMConfigAssetsByNameFunc func(ctx context.Context, assetNames []fleet.MDMAssetName) ([]fleet.MDMConfigAsset, error)
|
||||
|
||||
type WSTEPStoreCertificateFunc func(ctx context.Context, name string, crt *x509.Certificate) error
|
||||
|
||||
type WSTEPNewSerialFunc func(ctx context.Context) (*big.Int, error)
|
||||
|
|
@ -2162,6 +2164,9 @@ type DataStore struct {
|
|||
InsertMDMConfigAssetsFunc InsertMDMConfigAssetsFunc
|
||||
InsertMDMConfigAssetsFuncInvoked bool
|
||||
|
||||
GetMDMConfigAssetsByNameFunc GetMDMConfigAssetsByNameFunc
|
||||
GetMDMConfigAssetsByNameFuncInvoked bool
|
||||
|
||||
WSTEPStoreCertificateFunc WSTEPStoreCertificateFunc
|
||||
WSTEPStoreCertificateFuncInvoked bool
|
||||
|
||||
|
|
@ -5177,6 +5182,13 @@ func (s *DataStore) InsertMDMConfigAssets(ctx context.Context, assets []fleet.MD
|
|||
return s.InsertMDMConfigAssetsFunc(ctx, assets)
|
||||
}
|
||||
|
||||
func (s *DataStore) GetMDMConfigAssetsByName(ctx context.Context, assetNames []fleet.MDMAssetName) ([]fleet.MDMConfigAsset, error) {
|
||||
s.mu.Lock()
|
||||
s.GetMDMConfigAssetsByNameFuncInvoked = true
|
||||
s.mu.Unlock()
|
||||
return s.GetMDMConfigAssetsByNameFunc(ctx, assetNames)
|
||||
}
|
||||
|
||||
func (s *DataStore) WSTEPStoreCertificate(ctx context.Context, name string, crt *x509.Certificate) error {
|
||||
s.mu.Lock()
|
||||
s.WSTEPStoreCertificateFuncInvoked = true
|
||||
|
|
|
|||
|
|
@ -495,6 +495,8 @@ func attachFleetAPIRoutes(r *mux.Router, svc fleet.Service, config config.FleetC
|
|||
// Generative AI
|
||||
ue.POST("/api/_version_/fleet/autofill/policy", autofillPoliciesEndpoint, autofillPoliciesRequest{})
|
||||
|
||||
ue.GET("/api/_version_/fleet/mdm/apple/request_csr", getMDMAppleCSREndpoint, getMDMAppleCSRRequest{})
|
||||
|
||||
// Only Fleet MDM specific endpoints should be within the root /mdm/ path.
|
||||
// NOTE: remember to update
|
||||
// `service.mdmConfigurationRequiredEndpoints` when you add an
|
||||
|
|
|
|||
|
|
@ -270,7 +270,13 @@ func (s *integrationMDMTestSuite) SetupSuite() {
|
|||
fleetdmSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
status := s.fleetDMNextCSRStatus.Swap(http.StatusOK)
|
||||
w.WriteHeader(status.(int))
|
||||
_, _ = w.Write([]byte(fmt.Sprintf("status: %d", status)))
|
||||
resp := []byte(fmt.Sprintf("status: %d", status))
|
||||
if status == http.StatusOK && strings.Contains(r.URL.RawQuery, "deliveryMethod=json") {
|
||||
resp = []byte(fmt.Sprintf(`{"csr": "%s"}`, base64.StdEncoding.EncodeToString([]byte(`-----BEGIN CERTIFICATE REQUEST-----
|
||||
foobar
|
||||
-----END CERTIFICATE REQUEST-----`))))
|
||||
}
|
||||
_, _ = w.Write(resp)
|
||||
}))
|
||||
s.T().Setenv("TEST_FLEETDM_API_URL", fleetdmSrv.URL)
|
||||
|
||||
|
|
@ -893,6 +899,45 @@ func (s *integrationMDMTestSuite) TestAppleMDMCSRRequest() {
|
|||
require.Contains(t, string(reqCSRResp.SCEPKey), "-----BEGIN RSA PRIVATE KEY-----\n")
|
||||
}
|
||||
|
||||
func (s *integrationMDMTestSuite) TestGetMDMCSR() {
|
||||
t := s.T()
|
||||
ctx := context.Background()
|
||||
|
||||
// Check that we return bad gateway if the website API errors
|
||||
s.FailNextCSRRequestWith(http.StatusInternalServerError)
|
||||
errResp := validationErrResp{}
|
||||
s.DoJSON("GET", "/api/latest/fleet/mdm/apple/request_csr", getMDMAppleCSRRequest{}, http.StatusBadGateway, &errResp)
|
||||
require.Len(t, errResp.Errors, 1)
|
||||
require.Contains(t, errResp.Errors[0].Reason, "FleetDM CSR request failed")
|
||||
|
||||
// Successful request
|
||||
resp := getMDMAppleCSRResponse{}
|
||||
s.SucceedNextCSRRequest()
|
||||
s.DoJSON("GET", "/api/latest/fleet/mdm/apple/request_csr", getMDMAppleCSRRequest{}, http.StatusOK, &resp)
|
||||
require.NotNil(t, resp.CSR)
|
||||
require.Equal(t, string(resp.CSR), `-----BEGIN CERTIFICATE REQUEST-----
|
||||
foobar
|
||||
-----END CERTIFICATE REQUEST-----`)
|
||||
|
||||
// Check that we created the right assets
|
||||
assetsFromCall1, err := s.ds.GetMDMConfigAssetsByName(ctx, []fleet.MDMAssetName{fleet.MDMAssetCACert, fleet.MDMAssetCAKey, fleet.MDMAssetAPNSKey})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, assetsFromCall1, 3)
|
||||
|
||||
resp = getMDMAppleCSRResponse{}
|
||||
s.SucceedNextCSRRequest()
|
||||
s.DoJSON("GET", "/api/latest/fleet/mdm/apple/request_csr", getMDMAppleCSRRequest{}, http.StatusOK, &resp)
|
||||
require.NotNil(t, resp.CSR)
|
||||
require.Equal(t, string(resp.CSR), `-----BEGIN CERTIFICATE REQUEST-----
|
||||
foobar
|
||||
-----END CERTIFICATE REQUEST-----`)
|
||||
|
||||
// Check that the assets stayed the same in the subsequent call
|
||||
assetsFromCall2, err := s.ds.GetMDMConfigAssetsByName(ctx, []fleet.MDMAssetName{fleet.MDMAssetCACert, fleet.MDMAssetCAKey, fleet.MDMAssetAPNSKey})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, assetsFromCall1, assetsFromCall2)
|
||||
}
|
||||
|
||||
func (s *integrationMDMTestSuite) TestMDMAppleUnenroll() {
|
||||
t := s.T()
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ package service
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
|
@ -108,7 +111,7 @@ func (svc *Service) GetAppleBM(ctx context.Context) (*fleet.AppleBM, error) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// GET /mdm/apple/request_csr
|
||||
// POST /mdm/apple/request_csr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type requestMDMAppleCSRRequest struct {
|
||||
|
|
@ -2109,3 +2112,115 @@ func (svc *Service) ResendHostMDMProfile(ctx context.Context, hostID uint, profi
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// GET /mdm/apple/request_csr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type getMDMAppleCSRRequest struct{}
|
||||
|
||||
type getMDMAppleCSRResponse struct {
|
||||
CSR []byte `json:"csr"` // base64 encoded
|
||||
Err error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (r getMDMAppleCSRResponse) error() error { return r.Err }
|
||||
|
||||
func getMDMAppleCSREndpoint(ctx context.Context, request interface{}, svc fleet.Service) (errorer, error) {
|
||||
signedCSRB64, err := svc.GetMDMAppleCSR(ctx)
|
||||
if err != nil {
|
||||
return &getMDMAppleCSRResponse{Err: err}, nil
|
||||
}
|
||||
|
||||
return &getMDMAppleCSRResponse{CSR: signedCSRB64}, nil
|
||||
}
|
||||
|
||||
func (svc *Service) GetMDMAppleCSR(ctx context.Context) ([]byte, error) {
|
||||
if err := svc.authz.Authorize(ctx, &fleet.AppleCSR{}, fleet.ActionWrite); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vc, ok := viewer.FromContext(ctx)
|
||||
if !ok {
|
||||
return nil, fleet.ErrNoContext
|
||||
}
|
||||
|
||||
// Check if we have existing certs and keys
|
||||
var apnsKey *rsa.PrivateKey
|
||||
savedAssets, err := svc.ds.GetMDMConfigAssetsByName(ctx, []fleet.MDMAssetName{fleet.MDMAssetCACert, fleet.MDMAssetCAKey, fleet.MDMAssetAPNSKey})
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "checking asset existence")
|
||||
}
|
||||
|
||||
if len(savedAssets) == 0 {
|
||||
// Then we should create them
|
||||
scepCert, scepKey, err := apple_mdm.NewSCEPCACertKey()
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "generate SCEP cert and key")
|
||||
}
|
||||
|
||||
apnsKey, err = apple_mdm.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "generate new apns private key")
|
||||
}
|
||||
|
||||
// Store our config assets
|
||||
var assets []fleet.MDMConfigAsset
|
||||
for k, v := range map[fleet.MDMAssetName][]byte{
|
||||
fleet.MDMAssetCACert: apple_mdm.EncodeCertPEM(scepCert),
|
||||
fleet.MDMAssetCAKey: apple_mdm.EncodePrivateKeyPEM(scepKey),
|
||||
fleet.MDMAssetAPNSKey: apple_mdm.EncodePrivateKeyPEM(apnsKey),
|
||||
} {
|
||||
assets = append(assets, fleet.MDMConfigAsset{
|
||||
Name: k,
|
||||
Value: v,
|
||||
})
|
||||
}
|
||||
|
||||
if err := svc.ds.InsertMDMConfigAssets(ctx, assets); err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "inserting mdm config assets")
|
||||
}
|
||||
} else {
|
||||
for _, a := range savedAssets {
|
||||
if a.Name == fleet.MDMAssetAPNSKey {
|
||||
block, _ := pem.Decode(a.Value)
|
||||
apnsKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "unmarshaling saved apns key")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate new APNS CSR every time this is called
|
||||
appConfig, err := svc.ds.AppConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "get app config")
|
||||
}
|
||||
|
||||
apnsCSR, err := apple_mdm.GenerateAPNSCSR(appConfig.OrgInfo.OrgName, vc.Email(), apnsKey)
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "generate APNS cert and key")
|
||||
}
|
||||
|
||||
// Submit CSR to fleetdm.com for signing
|
||||
websiteClient := fleethttp.NewClient(fleethttp.WithTimeout(10 * time.Second))
|
||||
|
||||
signedCSRB64, err := apple_mdm.GetSignedAPNSCSRNoEmail(websiteClient, apnsCSR)
|
||||
if err != nil {
|
||||
var fwe apple_mdm.FleetWebsiteError
|
||||
if errors.As(err, &fwe) {
|
||||
return nil, ctxerr.Wrap(
|
||||
ctx,
|
||||
fleet.NewUserMessageError(
|
||||
fmt.Errorf("FleetDM CSR request failed: %w", err),
|
||||
http.StatusBadGateway,
|
||||
),
|
||||
)
|
||||
}
|
||||
return nil, ctxerr.Wrap(ctx, err, "get signed CSR")
|
||||
}
|
||||
|
||||
// Return signed CSR; these bytes are already base64 encoded
|
||||
return signedCSRB64, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,16 @@ func TestMDMAppleAuthorization(t *testing.T) {
|
|||
license := &fleet.LicenseInfo{Tier: fleet.TierPremium}
|
||||
svc, ctx := newTestService(t, ds, nil, nil, &TestServerOpts{License: license, SkipCreateTestUsers: true})
|
||||
|
||||
ds.GetMDMConfigAssetsByNameFunc = func(ctx context.Context, assetNames []fleet.MDMAssetName) ([]fleet.MDMConfigAsset, error) {
|
||||
return []fleet.MDMConfigAsset{}, nil
|
||||
}
|
||||
|
||||
ds.InsertMDMConfigAssetsFunc = func(ctx context.Context, assets []fleet.MDMConfigAsset) error { return nil }
|
||||
|
||||
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
|
||||
return &fleet.AppConfig{OrgInfo: fleet.OrgInfo{OrgName: "Nurv"}}, nil
|
||||
}
|
||||
|
||||
// use a custom implementation of checkAuthErr as the service call will fail
|
||||
// with a not found error (given that MDM is not really configured) in case
|
||||
// of success, and the package-wide checkAuthErr requires no error.
|
||||
|
|
@ -82,6 +92,9 @@ func TestMDMAppleAuthorization(t *testing.T) {
|
|||
_, err = svc.RequestMDMAppleCSR(ctx, "not-an-email", "")
|
||||
require.Error(t, err) // it *will* always fail, but not necessarily due to authorization
|
||||
checkAuthErr(t, shouldFailWithAuth, err)
|
||||
|
||||
_, err = svc.GetMDMAppleCSR(ctx)
|
||||
checkAuthErr(t, shouldFailWithAuth, err)
|
||||
}
|
||||
|
||||
// Only global admins can access the endpoints.
|
||||
|
|
|
|||
Loading…
Reference in a new issue