mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
add logic to configure FileVault + escrow (#10160)
Related to #9495, this adds the underlying methods to send a configuration profile that enables FileVault and FileVault Escrow, so we can fetch and decrypt the encryption key later on. These methods still need to be called somewhere, and they might need to be moved outside of `Service`, but at least this gives us a start.
This commit is contained in:
parent
f3ed6f3037
commit
164bb4bf5c
@ -1,7 +1,9 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
@ -111,3 +113,34 @@ func (svc *Service) MDMAppleEraseDevice(ctx context.Context, hostID uint) error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) MDMAppleEnableFileVaultAndEscrow(ctx context.Context, teamID uint) error {
|
||||
cert, _, _, err := svc.config.MDM.AppleSCEP()
|
||||
if err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "enabling FileVault")
|
||||
}
|
||||
|
||||
var contents bytes.Buffer
|
||||
params := fileVaultProfileOptions{
|
||||
PayloadIdentifier: apple_mdm.FleetFileVaultPayloadIdentifier,
|
||||
Base64DerCertificate: base64.StdEncoding.EncodeToString(cert.Leaf.Raw),
|
||||
}
|
||||
if err := fileVaultProfileTemplate.Execute(&contents, params); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "enabling FileVault")
|
||||
}
|
||||
|
||||
mc := fleet.Mobileconfig(contents.Bytes())
|
||||
cp, err := mc.ParseConfigProfile()
|
||||
if err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "enabling FileVault")
|
||||
}
|
||||
cp.TeamID = &teamID
|
||||
|
||||
_, err = svc.ds.NewMDMAppleConfigProfile(ctx, *cp)
|
||||
return ctxerr.Wrap(ctx, err, "enabling FileVault")
|
||||
}
|
||||
|
||||
func (svc *Service) MDMAppleDisableFileVaultAndEscrow(ctx context.Context, teamID uint) error {
|
||||
err := svc.ds.DeleteMDMAppleConfigProfileByTeamAndIdentifier(ctx, teamID, apple_mdm.FleetFileVaultPayloadIdentifier)
|
||||
return ctxerr.Wrap(ctx, err, "disabling FileVault")
|
||||
}
|
||||
|
78
ee/server/service/mdm_profiles.go
Normal file
78
ee/server/service/mdm_profiles.go
Normal file
@ -0,0 +1,78 @@
|
||||
package service
|
||||
|
||||
import "text/template"
|
||||
|
||||
type fileVaultProfileOptions struct {
|
||||
PayloadIdentifier string
|
||||
Base64DerCertificate string
|
||||
}
|
||||
|
||||
var fileVaultProfileTemplate = template.Must(template.New("").Option("missingkey=error").Parse(`<?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>Defer</key>
|
||||
<true/>
|
||||
<key>Enable</key>
|
||||
<string>On</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>FileVault 2</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.apple.MCX.FileVault2.3548D750-6357-4910-8DEA-D80ADCE2C787</string>
|
||||
<key>PayloadType</key>
|
||||
<string>com.apple.MCX.FileVault2</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>3548D750-6357-4910-8DEA-D80ADCE2C787</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
<key>ShowRecoveryKey</key>
|
||||
<false/>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>EncryptCertPayloadUUID</key>
|
||||
<string>A326B71F-EB80-41A5-A8CD-A6F932544281</string>
|
||||
<key>Location</key>
|
||||
<string>Fleet</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>FileVault Recovery Key Escrow</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.apple.security.FDERecoveryKeyEscrow.3690D771-DCB8-4D5D-97D6-209A138DF03E</string>
|
||||
<key>PayloadType</key>
|
||||
<string>com.apple.security.FDERecoveryKeyEscrow</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>3C329F2B-3D47-4141-A2B5-5C52A2FD74F8</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>PayloadCertificateFileName</key>
|
||||
<string>Fleet certificate</string>
|
||||
<key>PayloadContent</key>
|
||||
<data>{{ .Base64DerCertificate }}</data>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>Certificate Root</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.apple.security.root.A326B71F-EB80-41A5-A8CD-A6F932544281</string>
|
||||
<key>PayloadType</key>
|
||||
<string>com.apple.security.pkcs1</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>A326B71F-EB80-41A5-A8CD-A6F932544281</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>Disk encryption</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>{{ .PayloadIdentifier }}</string>
|
||||
<key>PayloadType</key>
|
||||
<string>Configuration</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>74FEAC88-B614-468E-A4B4-B4B0C93B5D52</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</plist>`))
|
139
ee/server/service/mdm_test.go
Normal file
139
ee/server/service/mdm_test.go
Normal file
@ -0,0 +1,139 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/config"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
apple_mdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
|
||||
"github.com/fleetdm/fleet/v4/server/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func setup() (*mock.Store, *Service) {
|
||||
ds := new(mock.Store)
|
||||
svc := &Service{
|
||||
ds: ds,
|
||||
config: config.FleetConfig{
|
||||
MDM: config.MDMConfig{
|
||||
AppleSCEPCertBytes: testCert,
|
||||
AppleSCEPKeyBytes: testKey,
|
||||
},
|
||||
},
|
||||
}
|
||||
return ds, svc
|
||||
}
|
||||
|
||||
func TestMDMAppleEnableFileVaultAndEscrow(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("fails if SCEP is not configured", func(t *testing.T) {
|
||||
ds := new(mock.Store)
|
||||
svc := &Service{ds: ds, config: config.FleetConfig{}}
|
||||
err := svc.MDMAppleEnableFileVaultAndEscrow(ctx, 0)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("fails if the profile can't be saved in the db", func(t *testing.T) {
|
||||
ds, svc := setup()
|
||||
testErr := errors.New("test")
|
||||
ds.NewMDMAppleConfigProfileFunc = func(ctx context.Context, p fleet.MDMAppleConfigProfile) (*fleet.MDMAppleConfigProfile, error) {
|
||||
return nil, testErr
|
||||
}
|
||||
err := svc.MDMAppleEnableFileVaultAndEscrow(ctx, 0)
|
||||
require.ErrorIs(t, err, testErr)
|
||||
require.True(t, ds.NewMDMAppleConfigProfileFuncInvoked)
|
||||
})
|
||||
|
||||
t.Run("happy path", func(t *testing.T) {
|
||||
var teamID uint = 4
|
||||
ds, svc := setup()
|
||||
ds.NewMDMAppleConfigProfileFunc = func(ctx context.Context, p fleet.MDMAppleConfigProfile) (*fleet.MDMAppleConfigProfile, error) {
|
||||
require.Equal(t, &teamID, p.TeamID)
|
||||
require.Equal(t, p.Identifier, apple_mdm.FleetFileVaultPayloadIdentifier)
|
||||
require.Equal(t, p.Name, "Disk encryption")
|
||||
require.Contains(t, string(p.Mobileconfig), `MIID6DCCAdACFGX99Sw4aF2qKGLucoIWQRAXHrs1MA0GCSqGSIb3DQEBCwUAMDUxEzARBgNVBAoMClJlZGlzIFRlc3QxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0yMTEwMTkxNzM0MzlaFw0yMjEwMTkxNzM0MzlaMCwxEzARBgNVBAoMClJlZGlzIFRlc3QxFTATBgNVBAMMDEdlbmVyaWMtY2VydDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKSHcH8EjSvp3Nm4IHAFxG9DZm8+0h1BwU0OX0VHcJ+Cf+f6h0XYMcMo9LFEpnUJRRMjKrM4mkI75NIIufNBN+GrtqqTPTid8wfOGu/Ufa5EEU1hb2j7AiMlpM6i0+ZysXSNo+Vc/cNZT0PXfyOtJnYm6p9WZM84ID1t2ea0bLwC12cTKv5oybVGtJHh76TRxAR3FeQ9+SY30vUAxYm6oWyYho8rRdKtUSe11pXj6OhxxfTZnsSWn4lo0uBpXai63XtieTVpz74htSNC1bunIGv7//m5F60sH5MrF5JSkPxfCfgqski84ICDSRNlvpT+eMPiygAAJ8zY8wYUXRYFYTUCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAAAw+6Uz2bAcXgQ7fQfdOm+T6FLRBcr8PD4ajOvSu/T+HhVVjE26Qt2IBwFEYve2FvDxrBCF8aQYZcyQqnP8bdKebnWAaqL8BbTwLWW+fDuZLO2b4QHjAEdEKKdZC5/FRpQrkerf5CCPTHE+5M17OZg41wdVYnCEwJOkP5pUAVsmwtrSwVeIquy20TZO0qbscDQETf7NIJgW0IXg82wBe53Rv4/wL3Ybq13XVRGYiJrwpaNTfUNgsDWqgwlQ5L2GOLDgg8S2NoF9mWVgCGSp3a2eHW+EmBRQ1OP6EYQtIhKdGLrSndAOMJ2ER1pgHWUFKkWQaZ9i37Dx2j7P5c4/XNeVozcRQcLwKwN+n8k+bwIYcTX0HMOVFYm+WiFi/gjI860Tx853Sc0nkpOXmBCeHSXigGUscgjBYbmJz4iExXuwgawLXKLDKs0yyhLDnKEjmx/Vhz03JpsVFJ84kSWkTZkYsXiG306TxuJCX9zAt1z+6ClieTTGiFY+D8DfkC4H82rlPEtImpZ6rInsMUlAykImpd58e4PMSa+w/wSHXDvwFP7py1Gvz3XvcbGLmpBXblxTUpToqC7zSQJhHOMBBt6XnhcRwd6G9Vj/mQM3FvJIrxtKk8O7FwMJloGivS85OEzCIur5A+bObXbM2pcI8y4ueHE4NtElRBwn859AdB2k=`)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
err := svc.MDMAppleEnableFileVaultAndEscrow(ctx, teamID)
|
||||
require.NoError(t, err)
|
||||
require.True(t, ds.NewMDMAppleConfigProfileFuncInvoked)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMDMAppleDisableFileVaultAndEscrow(t *testing.T) {
|
||||
var wantTeamID uint
|
||||
ds, svc := setup()
|
||||
ds.DeleteMDMAppleConfigProfileByTeamAndIdentifierFunc = func(ctx context.Context, teamID uint, profileIdentifier string) error {
|
||||
require.Equal(t, wantTeamID, teamID)
|
||||
require.Equal(t, apple_mdm.FleetFileVaultPayloadIdentifier, profileIdentifier)
|
||||
return nil
|
||||
}
|
||||
|
||||
err := svc.MDMAppleDisableFileVaultAndEscrow(context.Background(), wantTeamID)
|
||||
require.NoError(t, err)
|
||||
require.True(t, ds.DeleteMDMAppleConfigProfileByTeamAndIdentifierFuncInvoked)
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
testCert = `-----BEGIN CERTIFICATE-----
|
||||
MIID6DCCAdACFGX99Sw4aF2qKGLucoIWQRAXHrs1MA0GCSqGSIb3DQEBCwUAMDUx
|
||||
EzARBgNVBAoMClJlZGlzIFRlc3QxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhv
|
||||
cml0eTAeFw0yMTEwMTkxNzM0MzlaFw0yMjEwMTkxNzM0MzlaMCwxEzARBgNVBAoM
|
||||
ClJlZGlzIFRlc3QxFTATBgNVBAMMDEdlbmVyaWMtY2VydDCCASIwDQYJKoZIhvcN
|
||||
AQEBBQADggEPADCCAQoCggEBAKSHcH8EjSvp3Nm4IHAFxG9DZm8+0h1BwU0OX0VH
|
||||
cJ+Cf+f6h0XYMcMo9LFEpnUJRRMjKrM4mkI75NIIufNBN+GrtqqTPTid8wfOGu/U
|
||||
fa5EEU1hb2j7AiMlpM6i0+ZysXSNo+Vc/cNZT0PXfyOtJnYm6p9WZM84ID1t2ea0
|
||||
bLwC12cTKv5oybVGtJHh76TRxAR3FeQ9+SY30vUAxYm6oWyYho8rRdKtUSe11pXj
|
||||
6OhxxfTZnsSWn4lo0uBpXai63XtieTVpz74htSNC1bunIGv7//m5F60sH5MrF5JS
|
||||
kPxfCfgqski84ICDSRNlvpT+eMPiygAAJ8zY8wYUXRYFYTUCAwEAATANBgkqhkiG
|
||||
9w0BAQsFAAOCAgEAAAw+6Uz2bAcXgQ7fQfdOm+T6FLRBcr8PD4ajOvSu/T+HhVVj
|
||||
E26Qt2IBwFEYve2FvDxrBCF8aQYZcyQqnP8bdKebnWAaqL8BbTwLWW+fDuZLO2b4
|
||||
QHjAEdEKKdZC5/FRpQrkerf5CCPTHE+5M17OZg41wdVYnCEwJOkP5pUAVsmwtrSw
|
||||
VeIquy20TZO0qbscDQETf7NIJgW0IXg82wBe53Rv4/wL3Ybq13XVRGYiJrwpaNTf
|
||||
UNgsDWqgwlQ5L2GOLDgg8S2NoF9mWVgCGSp3a2eHW+EmBRQ1OP6EYQtIhKdGLrSn
|
||||
dAOMJ2ER1pgHWUFKkWQaZ9i37Dx2j7P5c4/XNeVozcRQcLwKwN+n8k+bwIYcTX0H
|
||||
MOVFYm+WiFi/gjI860Tx853Sc0nkpOXmBCeHSXigGUscgjBYbmJz4iExXuwgawLX
|
||||
KLDKs0yyhLDnKEjmx/Vhz03JpsVFJ84kSWkTZkYsXiG306TxuJCX9zAt1z+6Clie
|
||||
TTGiFY+D8DfkC4H82rlPEtImpZ6rInsMUlAykImpd58e4PMSa+w/wSHXDvwFP7py
|
||||
1Gvz3XvcbGLmpBXblxTUpToqC7zSQJhHOMBBt6XnhcRwd6G9Vj/mQM3FvJIrxtKk
|
||||
8O7FwMJloGivS85OEzCIur5A+bObXbM2pcI8y4ueHE4NtElRBwn859AdB2k=
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
testKey = testingKey(`-----BEGIN RSA TESTING KEY-----
|
||||
MIIEogIBAAKCAQEApIdwfwSNK+nc2bggcAXEb0Nmbz7SHUHBTQ5fRUdwn4J/5/qH
|
||||
Rdgxwyj0sUSmdQlFEyMqsziaQjvk0gi580E34au2qpM9OJ3zB84a79R9rkQRTWFv
|
||||
aPsCIyWkzqLT5nKxdI2j5Vz9w1lPQ9d/I60mdibqn1ZkzzggPW3Z5rRsvALXZxMq
|
||||
/mjJtUa0keHvpNHEBHcV5D35JjfS9QDFibqhbJiGjytF0q1RJ7XWlePo6HHF9Nme
|
||||
xJafiWjS4GldqLrde2J5NWnPviG1I0LVu6cga/v/+bkXrSwfkysXklKQ/F8J+Cqy
|
||||
SLzggINJE2W+lP54w+LKAAAnzNjzBhRdFgVhNQIDAQABAoIBAAtUbFHC3XnVq+iu
|
||||
PkWYkBNdX9NvTwbGvWnyAGuD5OSHFwnBfck4fwzCaD9Ay/mpPsF3nXwj/LNs7m/s
|
||||
O+ndZty6d2S9qOyaK98wuTgkuNbkRxC+Ee73wgjrkbLNEax/32p4Sn4D7lGid8vj
|
||||
LhUl2k0ult+MEnsWkVnJk8TITeiQaT2AHhMr3HKdaI86hJJfam3wEBiLBglnnKqA
|
||||
TInMqHoudnFOn/C8iVCFuHCE0oo1dMalbc4rlZuRBqezVhbSMWPLypMVXQb7eixM
|
||||
ScJ3m8+DooGDSIe+EW/afhN2VnFbrhQC9/DlxGfwTwsUseWv7pgp53ufyyAzzydn
|
||||
2plW/4ECgYEA1Va5RzSUDxr75JX003YZiBcYrG268vosiNYWRhE7frvn5EorZBRW
|
||||
t4R70Y2gcXA10aPHzpbq40t6voWtpkfynU3fyRzbBmwfiWLEgckrYMwtcNz8nhG2
|
||||
ETAg4LXO9CufbwuDa66h76TpkBzQVNc5TSbBUr/apLDWjKPMz6qW7VUCgYEAxW4K
|
||||
Yqp3NgJkC5DhuD098jir9AH96hGhUryOi2CasCvmbjWCgWdolD7SRZJfxOXFOtHv
|
||||
7Dkp9glA1Cg/nSmEHKslaTJfBIWK+5rqVD6k6kZE/+4QQWQtUxXXVgGINnGrnPvo
|
||||
6MlRJxqGUtYJ0GRTFJP4Py0gwuzf5BMIwe+fpGECgYAOhLRfMCjTTlbOG5ZpvaPH
|
||||
Kys2sNEEMBpPxaIGaq3N1iPV2WZSjT/JhW6XuDevAJ/pAGhcmtCpXz2fMaG7qzHL
|
||||
mr0cBqaxLTKIOvx8iKA3Gi4NfDyE1Ve6m7fhEv5eh4l2GSZ8cYn7sRFkCVH0NCFm
|
||||
KrkFVKEgjBhNwefySf2zcQKBgHDVPgw7nlv4q9LMX6RbI98eMnAG/2XZ45gUeWcA
|
||||
tAeBX3WXEVoBjoxDBwuJ5z/xjXHbb8JSvT+G9E0MH6cjhgSYb44aoqFD7TV0yP2S
|
||||
u8/Ej0SxewrURO8aKXJW99Edz9WtRuRbwgyWJTSMbRlzbOPy2UrJ8NJWbHK9yiCE
|
||||
YXmhAoGAA3QUiCCl11c1C4VsF68Fa2i7qwnty3fvFidZpW3ds0tzZdIvkpRLp5+u
|
||||
XAJ5+zStdEGdnu0iXALQlY7ektawXguT/zYKg3nfS9RMGW6CxZotn4bqfQwDuttf
|
||||
b1xn1jGQd/o0xFf9ojpDNy6vNojidQGHh6E3h0GYvxbnQmVNq5U=
|
||||
-----END RSA TESTING KEY-----`)
|
||||
)
|
||||
|
||||
// prevent static analysis tools from raising issues due to detection of
|
||||
// private key in code.
|
||||
func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
|
@ -140,6 +140,20 @@ func (ds *Datastore) DeleteMDMAppleConfigProfile(ctx context.Context, profileID
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) DeleteMDMAppleConfigProfileByTeamAndIdentifier(ctx context.Context, teamID uint, profileIdentifier string) error {
|
||||
res, err := ds.writer.ExecContext(ctx, `DELETE FROM mdm_apple_configuration_profiles WHERE team_id = ? AND identifier = ?`, teamID, profileIdentifier)
|
||||
if err != nil {
|
||||
return ctxerr.Wrap(ctx, err)
|
||||
}
|
||||
|
||||
if deleted, _ := res.RowsAffected(); deleted == 0 {
|
||||
message := fmt.Sprintf("identifier: %s, team_id: %d", profileIdentifier, teamID)
|
||||
return ctxerr.Wrap(ctx, notFound("MDMAppleConfigProfile").WithMessage(message))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) GetHostMDMProfiles(ctx context.Context, hostUUID string) ([]fleet.HostMDMAppleProfile, error) {
|
||||
stmt := fmt.Sprintf(`
|
||||
SELECT
|
||||
|
@ -26,6 +26,7 @@ func TestMDMAppleConfigProfile(t *testing.T) {
|
||||
{"TestNewMDMAppleConfigProfileDuplicateName", testNewMDMAppleConfigProfileDuplicateName},
|
||||
{"TestNewMDMAppleConfigProfileDuplicateIdentifier", testNewMDMAppleConfigProfileDuplicateIdentifier},
|
||||
{"TestDeleteMDMAppleConfigProfile", testDeleteMDMAppleConfigProfile},
|
||||
{"TestDeleteMDMAppleConfigProfileByTeamAndIdentifier", testDeleteMDMAppleConfigProfileByTeamAndIdentifier},
|
||||
{"TestListMDMAppleConfigProfiles", testListMDMAppleConfigProfiles},
|
||||
{"TestHostDetailsMDMProfiles", testHostDetailsMDMProfiles},
|
||||
{"TestBatchSetMDMAppleProfiles", testBatchSetMDMAppleProfiles},
|
||||
@ -166,6 +167,20 @@ func testDeleteMDMAppleConfigProfile(t *testing.T, ds *Datastore) {
|
||||
require.ErrorIs(t, err, sql.ErrNoRows)
|
||||
}
|
||||
|
||||
func testDeleteMDMAppleConfigProfileByTeamAndIdentifier(t *testing.T, ds *Datastore) {
|
||||
ctx := context.Background()
|
||||
initialCP := storeDummyConfigProfileForTest(t, ds)
|
||||
|
||||
err := ds.DeleteMDMAppleConfigProfileByTeamAndIdentifier(ctx, *initialCP.TeamID, initialCP.Identifier)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = ds.GetMDMAppleConfigProfile(ctx, initialCP.ProfileID)
|
||||
require.ErrorIs(t, err, sql.ErrNoRows)
|
||||
|
||||
err = ds.DeleteMDMAppleConfigProfileByTeamAndIdentifier(ctx, *initialCP.TeamID, initialCP.Identifier)
|
||||
require.ErrorIs(t, err, sql.ErrNoRows)
|
||||
}
|
||||
|
||||
func storeDummyConfigProfileForTest(t *testing.T, ds *Datastore) *fleet.MDMAppleConfigProfile {
|
||||
dummyMC := fleet.Mobileconfig([]byte("DummyTestMobileconfigBytes"))
|
||||
dummyCP := fleet.MDMAppleConfigProfile{
|
||||
|
@ -717,10 +717,14 @@ type Datastore interface {
|
||||
// For global config profiles, specify zero as the team id.
|
||||
ListMDMAppleConfigProfiles(ctx context.Context, teamID *uint) ([]*MDMAppleConfigProfile, error)
|
||||
|
||||
// DeleteMDMAppleConfigProfile deleted the mdm config profile corresponding to the specified
|
||||
// profile id.
|
||||
// DeleteMDMAppleConfigProfile deletes the mdm config profile corresponding
|
||||
// to the specified profile id.
|
||||
DeleteMDMAppleConfigProfile(ctx context.Context, profileID uint) error
|
||||
|
||||
// DeleteMDMAppleConfigProfileByTeamAndIdentifier deletes a configuration
|
||||
// profile using the unique key defined by `team_id` and `identifier`
|
||||
DeleteMDMAppleConfigProfileByTeamAndIdentifier(ctx context.Context, teamID uint, profileIdentifier string) error
|
||||
|
||||
// GetHostMDMProfiles returns the MDM profile information for the specified host UUID.
|
||||
GetHostMDMProfiles(ctx context.Context, hostUUID string) ([]HostMDMAppleProfile, error)
|
||||
|
||||
|
@ -624,6 +624,15 @@ type Service interface {
|
||||
// MMDAppleEraseDevice erases a host
|
||||
MDMAppleEraseDevice(ctx context.Context, hostID uint) error
|
||||
|
||||
// MDMAppleEnableFileVaultAndEscrow adds a configuration profile for the
|
||||
// given team that enables FileVault with a config that allows Fleet to
|
||||
// escrow the recovery key.
|
||||
MDMAppleEnableFileVaultAndEscrow(ctx context.Context, teamID uint) error
|
||||
|
||||
// MDMAppleDisableFileVaultAndEscrow removes the FileVault configuration
|
||||
// profile for the given team.
|
||||
MDMAppleDisableFileVaultAndEscrow(ctx context.Context, teamID uint) error
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CronSchedulesService
|
||||
|
||||
|
@ -39,6 +39,10 @@ const (
|
||||
// used by Fleet MDM on the enrollment profile.
|
||||
FleetPayloadIdentifier = "com.fleetdm.fleet.mdm.apple"
|
||||
|
||||
// FleetFileVaultPayloadIdentifier is the value for the PayloadIdentifier
|
||||
// used by Fleet to configure FileVault and FileVault Escrow.
|
||||
FleetFileVaultPayloadIdentifier = "com.fleetdm.fleet.mdm.filevault"
|
||||
|
||||
// FleetdConfigPayloadIdentifier is the value for the PayloadIdentifier used
|
||||
// by fleetd to read configuration values from the system.
|
||||
FleetdConfigPayloadIdentifier = "com.fleetdm.fleetd.config"
|
||||
|
@ -515,6 +515,8 @@ type ListMDMAppleConfigProfilesFunc func(ctx context.Context, teamID *uint) ([]*
|
||||
|
||||
type DeleteMDMAppleConfigProfileFunc func(ctx context.Context, profileID uint) error
|
||||
|
||||
type DeleteMDMAppleConfigProfileByTeamAndIdentifierFunc func(ctx context.Context, teamID uint, profileIdentifier string) error
|
||||
|
||||
type GetHostMDMProfilesFunc func(ctx context.Context, hostUUID string) ([]fleet.HostMDMAppleProfile, error)
|
||||
|
||||
type NewMDMAppleEnrollmentProfileFunc func(ctx context.Context, enrollmentPayload fleet.MDMAppleEnrollmentProfilePayload) (*fleet.MDMAppleEnrollmentProfile, error)
|
||||
@ -1314,6 +1316,9 @@ type DataStore struct {
|
||||
DeleteMDMAppleConfigProfileFunc DeleteMDMAppleConfigProfileFunc
|
||||
DeleteMDMAppleConfigProfileFuncInvoked bool
|
||||
|
||||
DeleteMDMAppleConfigProfileByTeamAndIdentifierFunc DeleteMDMAppleConfigProfileByTeamAndIdentifierFunc
|
||||
DeleteMDMAppleConfigProfileByTeamAndIdentifierFuncInvoked bool
|
||||
|
||||
GetHostMDMProfilesFunc GetHostMDMProfilesFunc
|
||||
GetHostMDMProfilesFuncInvoked bool
|
||||
|
||||
@ -3139,6 +3144,13 @@ func (s *DataStore) DeleteMDMAppleConfigProfile(ctx context.Context, profileID u
|
||||
return s.DeleteMDMAppleConfigProfileFunc(ctx, profileID)
|
||||
}
|
||||
|
||||
func (s *DataStore) DeleteMDMAppleConfigProfileByTeamAndIdentifier(ctx context.Context, teamID uint, profileIdentifier string) error {
|
||||
s.mu.Lock()
|
||||
s.DeleteMDMAppleConfigProfileByTeamAndIdentifierFuncInvoked = true
|
||||
s.mu.Unlock()
|
||||
return s.DeleteMDMAppleConfigProfileByTeamAndIdentifierFunc(ctx, teamID, profileIdentifier)
|
||||
}
|
||||
|
||||
func (s *DataStore) GetHostMDMProfiles(ctx context.Context, hostUUID string) ([]fleet.HostMDMAppleProfile, error) {
|
||||
s.mu.Lock()
|
||||
s.GetHostMDMProfilesFuncInvoked = true
|
||||
|
@ -1518,6 +1518,18 @@ func (svc *Service) BatchSetMDMAppleProfiles(ctx context.Context, tmID *uint, tm
|
||||
return nil
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FileVault-related free version implementation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func (svc *Service) MDMAppleEnableFileVaultAndEscrow(ctx context.Context, teamID uint) error {
|
||||
return fleet.ErrMissingLicense
|
||||
}
|
||||
|
||||
func (svc *Service) MDMAppleDisableFileVaultAndEscrow(ctx context.Context, teamID uint) error {
|
||||
return fleet.ErrMissingLicense
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of nanomdm's CheckinAndCommandService interface
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1421,6 +1421,16 @@ func TestMDMAppleReconcileProfiles(t *testing.T) {
|
||||
require.True(t, ds.BulkUpsertMDMAppleHostProfilesFuncInvoked)
|
||||
}
|
||||
|
||||
func TestAppleMDMFileVaultEscrowFunctions(t *testing.T) {
|
||||
svc := Service{}
|
||||
|
||||
err := svc.MDMAppleEnableFileVaultAndEscrow(context.Background(), uint(1))
|
||||
require.ErrorIs(t, fleet.ErrMissingLicense, err)
|
||||
|
||||
err = svc.MDMAppleDisableFileVaultAndEscrow(context.Background(), uint(1))
|
||||
require.ErrorIs(t, fleet.ErrMissingLicense, 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">
|
||||
|
Loading…
Reference in New Issue
Block a user