Create new Fleet osquery extension table to read escrowed FileVault key (#12198)
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
- Fixed bug when reading filevault key in osquery and created new Fleet osquery
|
||||
extension table to read the file directly rather than via filelines table.
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/diskutil/apfs"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/diskutil/corestorage"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/dscl"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/filevault_prk"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/firmware_eficheck_integrity_check"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/nvram_info"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/pmset"
|
||||
@@ -44,6 +45,7 @@ func PlatformTables() []osquery.OsqueryPlugin {
|
||||
table.NewPlugin("apfs_physical_stores", apfs.PhysicalStoresColumns(), apfs.PhysicalStoresGenerate),
|
||||
table.NewPlugin("corestorage_logical_volumes", corestorage.LogicalVolumesColumns(), corestorage.LogicalVolumesGenerate),
|
||||
table.NewPlugin("corestorage_logical_volume_families", corestorage.LogicalVolumeFamiliesColumns(), corestorage.LogicalVolumeFamiliesGenerate),
|
||||
table.NewPlugin("filevault_prk", filevault_prk.Columns(), filevault_prk.Generate),
|
||||
|
||||
// Macadmins extension tables
|
||||
table.NewPlugin("filevault_users", filevaultusers.FileVaultUsersColumns(), filevaultusers.FileVaultUsersGenerate),
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
package filevault_prk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
|
||||
"github.com/osquery/osquery-go/plugin/table"
|
||||
)
|
||||
|
||||
// Columns is the schema of the table.
|
||||
func Columns() []table.ColumnDefinition {
|
||||
return []table.ColumnDefinition{
|
||||
table.TextColumn("base64_encrypted"),
|
||||
}
|
||||
}
|
||||
|
||||
// Generate is called to return the results for the table at query time.
|
||||
//
|
||||
// Constraints for generating can be retrieved from the queryContext.
|
||||
func Generate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
|
||||
encryptedKey, err := os.ReadFile("/var/db/FileVaultPRK.dat")
|
||||
if err != nil {
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("generate failed: %w", err)
|
||||
}
|
||||
encoded := base64.StdEncoding.EncodeToString(encryptedKey)
|
||||
|
||||
return []map[string]string{{"base64_encrypted": encoded}}, nil
|
||||
}
|
||||
+316
-297
@@ -27212,73 +27212,6 @@
|
||||
],
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/yum_sources.yml"
|
||||
},
|
||||
{
|
||||
"name": "apfs_physical_stores",
|
||||
"platforms": [
|
||||
"darwin"
|
||||
],
|
||||
"description": "Information about APFS physical stores from the `diskutil apfs list -plist` command.",
|
||||
"columns": [
|
||||
{
|
||||
"name": "container_uuid",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "The UUID of the APFS Contianer"
|
||||
},
|
||||
{
|
||||
"name": "container_designated_physical_store",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "The disk displayed as the backing store of the container. There may be multiple,\nuse `apfs_physical_stores` to see all actual physical stores\n"
|
||||
},
|
||||
{
|
||||
"name": "container_reference",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "The current reference for the APFS container, e.g. \"disk3\""
|
||||
},
|
||||
{
|
||||
"name": "container_fusion",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "Whether this container is on a \"fusion drive\" (i.e. SSHD)"
|
||||
},
|
||||
{
|
||||
"name": "container_capacity_ceiling",
|
||||
"type": "bigint",
|
||||
"required": false,
|
||||
"description": "The total amount of space in the container"
|
||||
},
|
||||
{
|
||||
"name": "container_capacity_free",
|
||||
"type": "bigint",
|
||||
"required": false,
|
||||
"description": "The amount of remaining free space in the container"
|
||||
},
|
||||
{
|
||||
"name": "uuid",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "The UUID of the physical store"
|
||||
},
|
||||
{
|
||||
"name": "identifier",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "The current identifier of the physical store (e.g. disk1s2)"
|
||||
},
|
||||
{
|
||||
"name": "size",
|
||||
"type": "bigint",
|
||||
"required": false,
|
||||
"description": "The size of the physical store in byptes"
|
||||
}
|
||||
],
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).",
|
||||
"evented": false,
|
||||
"url": "https://fleetdm.com/tables/apfs_physical_stores",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/apfs_physical_stores.yml"
|
||||
},
|
||||
{
|
||||
"name": "apfs_volumes",
|
||||
"platforms": [
|
||||
@@ -27394,6 +27327,73 @@
|
||||
"url": "https://fleetdm.com/tables/apfs_volumes",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/apfs_volumes.yml"
|
||||
},
|
||||
{
|
||||
"name": "apfs_physical_stores",
|
||||
"platforms": [
|
||||
"darwin"
|
||||
],
|
||||
"description": "Information about APFS physical stores from the `diskutil apfs list -plist` command.",
|
||||
"columns": [
|
||||
{
|
||||
"name": "container_uuid",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "The UUID of the APFS Contianer"
|
||||
},
|
||||
{
|
||||
"name": "container_designated_physical_store",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "The disk displayed as the backing store of the container. There may be multiple,\nuse `apfs_physical_stores` to see all actual physical stores\n"
|
||||
},
|
||||
{
|
||||
"name": "container_reference",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "The current reference for the APFS container, e.g. \"disk3\""
|
||||
},
|
||||
{
|
||||
"name": "container_fusion",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "Whether this container is on a \"fusion drive\" (i.e. SSHD)"
|
||||
},
|
||||
{
|
||||
"name": "container_capacity_ceiling",
|
||||
"type": "bigint",
|
||||
"required": false,
|
||||
"description": "The total amount of space in the container"
|
||||
},
|
||||
{
|
||||
"name": "container_capacity_free",
|
||||
"type": "bigint",
|
||||
"required": false,
|
||||
"description": "The amount of remaining free space in the container"
|
||||
},
|
||||
{
|
||||
"name": "uuid",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "The UUID of the physical store"
|
||||
},
|
||||
{
|
||||
"name": "identifier",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "The current identifier of the physical store (e.g. disk1s2)"
|
||||
},
|
||||
{
|
||||
"name": "size",
|
||||
"type": "bigint",
|
||||
"required": false,
|
||||
"description": "The size of the physical store in byptes"
|
||||
}
|
||||
],
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).",
|
||||
"evented": false,
|
||||
"url": "https://fleetdm.com/tables/apfs_physical_stores",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/apfs_physical_stores.yml"
|
||||
},
|
||||
{
|
||||
"name": "authdb",
|
||||
"platforms": [
|
||||
@@ -27820,6 +27820,51 @@
|
||||
"url": "https://fleetdm.com/tables/dscl",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/dscl.yml"
|
||||
},
|
||||
{
|
||||
"name": "filevault_prk",
|
||||
"platforms": [
|
||||
"darwin"
|
||||
],
|
||||
"description": "Returns contents of `/var/db/FileVaultPRK.dat`.",
|
||||
"columns": [
|
||||
{
|
||||
"name": "base64_encrypted",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "The base64-encoded contents of the encrypted FileVault personal recovery key stored at `/var/db/FileVaultPRK.dat` (see also https://developer.apple.com/documentation/devicemanagement/fderecoverykeyescrow)"
|
||||
}
|
||||
],
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).",
|
||||
"evented": false,
|
||||
"url": "https://fleetdm.com/tables/filevault_prk",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/filevault_prk.yml"
|
||||
},
|
||||
{
|
||||
"name": "filevault_users",
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).",
|
||||
"description": "Information on the users able to unlock the current boot volume if protected with FileVault.",
|
||||
"platforms": [
|
||||
"darwin"
|
||||
],
|
||||
"evented": false,
|
||||
"examples": "List the usernames able to unlock and boot a computer protected by FileVault, joined to [users.username](http://fleetdm.com/tables/users) to obtain the description of the operating system account that owns it.\n```\nSELECT fu.username, u.description FROM filevault_users fu JOIN users u ON fu.uuid=u.uuid;\n```",
|
||||
"columns": [
|
||||
{
|
||||
"name": "username",
|
||||
"description": "Username of the FileVault user.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "uuid",
|
||||
"description": "UUID of the FileVault user, which can be joined to [users.uuid](http://fleetdm.com/tables/users).",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"url": "https://fleetdm.com/tables/filevault_users",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/filevault_users.yml"
|
||||
},
|
||||
{
|
||||
"name": "file_lines",
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).",
|
||||
@@ -27849,30 +27894,65 @@
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/file_lines.yml"
|
||||
},
|
||||
{
|
||||
"name": "filevault_users",
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).",
|
||||
"description": "Information on the users able to unlock the current boot volume if protected with FileVault.",
|
||||
"name": "firmware_eficheck_integrity_check",
|
||||
"platforms": [
|
||||
"darwin"
|
||||
],
|
||||
"evented": false,
|
||||
"examples": "List the usernames able to unlock and boot a computer protected by FileVault, joined to [users.username](http://fleetdm.com/tables/users) to obtain the description of the operating system account that owns it.\n```\nSELECT fu.username, u.description FROM filevault_users fu JOIN users u ON fu.uuid=u.uuid;\n```",
|
||||
"description": "Performs eficheck's integrity check on macOS Intel T1 chips (CIS 5.9).",
|
||||
"columns": [
|
||||
{
|
||||
"name": "username",
|
||||
"description": "Username of the FileVault user.",
|
||||
"name": "chip",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
"description": "Contains the chip type, values are \"apple\", \"intel-t1\" and \"intel-t2\".\nIf chip type is \"apple\" or \"intel-t2\" then no eficheck integrity check is executed.\n"
|
||||
},
|
||||
{
|
||||
"name": "uuid",
|
||||
"description": "UUID of the FileVault user, which can be joined to [users.uuid](http://fleetdm.com/tables/users).",
|
||||
"name": "output",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
"description": "Output of the `/usr/libexec/firmwarecheckers/eficheck/eficheck --integrity-check` command.\nThis value is only valid when chip is \"intel-t1\".\n"
|
||||
}
|
||||
],
|
||||
"url": "https://fleetdm.com/tables/filevault_users",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/filevault_users.yml"
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).",
|
||||
"evented": false,
|
||||
"url": "https://fleetdm.com/tables/firmware_eficheck_integrity_check",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/firmware_eficheck_integrity_check.yml"
|
||||
},
|
||||
{
|
||||
"name": "geolocation",
|
||||
"evented": false,
|
||||
"platforms": [
|
||||
"chrome"
|
||||
],
|
||||
"description": "Last reported geolocation",
|
||||
"columns": [
|
||||
{
|
||||
"name": "ip",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "IP address"
|
||||
},
|
||||
{
|
||||
"name": "city",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "City"
|
||||
},
|
||||
{
|
||||
"name": "country",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "Country"
|
||||
},
|
||||
{
|
||||
"name": "region",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "Region"
|
||||
}
|
||||
],
|
||||
"url": "https://fleetdm.com/tables/geolocation",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/geolocation.yml"
|
||||
},
|
||||
{
|
||||
"name": "google_chrome_profiles",
|
||||
@@ -27914,42 +27994,6 @@
|
||||
"url": "https://fleetdm.com/tables/google_chrome_profiles",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/google_chrome_profiles.yml"
|
||||
},
|
||||
{
|
||||
"name": "geolocation",
|
||||
"evented": false,
|
||||
"platforms": [
|
||||
"chrome"
|
||||
],
|
||||
"description": "Last reported geolocation",
|
||||
"columns": [
|
||||
{
|
||||
"name": "ip",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "IP address"
|
||||
},
|
||||
{
|
||||
"name": "city",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "City"
|
||||
},
|
||||
{
|
||||
"name": "country",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "Country"
|
||||
},
|
||||
{
|
||||
"name": "region",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "Region"
|
||||
}
|
||||
],
|
||||
"url": "https://fleetdm.com/tables/geolocation",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/geolocation.yml"
|
||||
},
|
||||
{
|
||||
"name": "icloud_private_relay",
|
||||
"platforms": [
|
||||
@@ -27969,31 +28013,6 @@
|
||||
"url": "https://fleetdm.com/tables/icloud_private_relay",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/icloud_private_relay.yml"
|
||||
},
|
||||
{
|
||||
"name": "firmware_eficheck_integrity_check",
|
||||
"platforms": [
|
||||
"darwin"
|
||||
],
|
||||
"description": "Performs eficheck's integrity check on macOS Intel T1 chips (CIS 5.9).",
|
||||
"columns": [
|
||||
{
|
||||
"name": "chip",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "Contains the chip type, values are \"apple\", \"intel-t1\" and \"intel-t2\".\nIf chip type is \"apple\" or \"intel-t2\" then no eficheck integrity check is executed.\n"
|
||||
},
|
||||
{
|
||||
"name": "output",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"description": "Output of the `/usr/libexec/firmwarecheckers/eficheck/eficheck --integrity-check` command.\nThis value is only valid when chip is \"intel-t1\".\n"
|
||||
}
|
||||
],
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).",
|
||||
"evented": false,
|
||||
"url": "https://fleetdm.com/tables/firmware_eficheck_integrity_check",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/firmware_eficheck_integrity_check.yml"
|
||||
},
|
||||
{
|
||||
"name": "macadmins_unified_log",
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).",
|
||||
@@ -28344,44 +28363,6 @@
|
||||
"url": "https://fleetdm.com/tables/mdm_bridge",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/mdm_bridge.yml"
|
||||
},
|
||||
{
|
||||
"name": "munki_installs",
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).<p> Code based on work by [Kolide](https://github.com/kolide/launcher).",
|
||||
"description": "Software packages and other items [Munki](https://github.com/munki/munki) is managing.",
|
||||
"platforms": [
|
||||
"darwin"
|
||||
],
|
||||
"evented": false,
|
||||
"examples": "See the version of software that has been deployed by Munki.\n```\nSELECT name, installed_version FROM munki_installs WHERE installed='true';\n```",
|
||||
"columns": [
|
||||
{
|
||||
"name": "end_time",
|
||||
"description": "The end time of the last Munki run.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "installed",
|
||||
"description": "Shows if Munki installed an item (true) or if it is simply available but not installed (false).",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "installed_version",
|
||||
"description": "The version number of installed items.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"description": "The name of items managed by Munki.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"url": "https://fleetdm.com/tables/munki_installs",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/munki_installs.yml"
|
||||
},
|
||||
{
|
||||
"name": "munki_info",
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).<p> Code based on work by [Kolide](https://github.com/kolide/launcher).",
|
||||
@@ -28450,6 +28431,44 @@
|
||||
"url": "https://fleetdm.com/tables/munki_info",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/munki_info.yml"
|
||||
},
|
||||
{
|
||||
"name": "munki_installs",
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).<p> Code based on work by [Kolide](https://github.com/kolide/launcher).",
|
||||
"description": "Software packages and other items [Munki](https://github.com/munki/munki) is managing.",
|
||||
"platforms": [
|
||||
"darwin"
|
||||
],
|
||||
"evented": false,
|
||||
"examples": "See the version of software that has been deployed by Munki.\n```\nSELECT name, installed_version FROM munki_installs WHERE installed='true';\n```",
|
||||
"columns": [
|
||||
{
|
||||
"name": "end_time",
|
||||
"description": "The end time of the last Munki run.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "installed",
|
||||
"description": "Shows if Munki installed an item (true) or if it is simply available but not installed (false).",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "installed_version",
|
||||
"description": "The version number of installed items.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"description": "The name of items managed by Munki.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"url": "https://fleetdm.com/tables/munki_installs",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/munki_installs.yml"
|
||||
},
|
||||
{
|
||||
"name": "network_interfaces",
|
||||
"evented": false,
|
||||
@@ -28582,6 +28601,124 @@
|
||||
"url": "https://fleetdm.com/tables/pmset",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/pmset.yml"
|
||||
},
|
||||
{
|
||||
"name": "puppet_info",
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).",
|
||||
"description": "Information on the last [Puppet](https://puppet.com/) run. This table uses data from the `last_run_report` that Puppet creates.",
|
||||
"platforms": [
|
||||
"darwin",
|
||||
"windows",
|
||||
"linux"
|
||||
],
|
||||
"evented": false,
|
||||
"examples": "List all the information available about the last Puppet run.\n```\nSELECT * FROM puppet_info;\n```",
|
||||
"columns": [
|
||||
{
|
||||
"name": "cached_catalog_status",
|
||||
"description": "The status of Puppet catalogs cached on the system.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "catalog_uuid",
|
||||
"description": "The [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) of the catalog downloaded by Puppet.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "code_id",
|
||||
"description": "The `code_id` links the catalog with the compile-time version of file resources using the `puppet:///` URI.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "configuration_version",
|
||||
"description": "The version of the Puppet configuration.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "corrective_change",
|
||||
"description": "A corrective change is triggered when Puppet detects a discrepency between the current state and the expected state of a value.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "environment",
|
||||
"description": "The environment name.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "host",
|
||||
"description": "The host on which Puppet is used.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "kind",
|
||||
"description": "Kind of Puppet run.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "master_used",
|
||||
"description": "The Puppet server used.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "noop",
|
||||
"description": "Indicates if Puppet was run in [noop](https://puppet.com/docs/puppet/latest/metaparameter.html#noop) mode.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "noop_prending",
|
||||
"description": "Items pending from a [noop](https://puppet.com/docs/puppet/latest/metaparameter.html#noop) run.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "puppet_version",
|
||||
"description": "The version of Puppet used during the last run.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "report_format",
|
||||
"description": "The format the Puppet report was exported as.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "status",
|
||||
"description": "The status of Puppet on this system.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "time",
|
||||
"description": "The time of the last Puppet run.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "transaction_completed",
|
||||
"description": "Indicates if the transaction completed or not.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "transaction_uuid",
|
||||
"description": "The [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) of the transaction.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"url": "https://fleetdm.com/tables/puppet_info",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/puppet_info.yml"
|
||||
},
|
||||
{
|
||||
"name": "puppet_logs",
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).",
|
||||
@@ -28728,124 +28865,6 @@
|
||||
"url": "https://fleetdm.com/tables/puppet_state",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/puppet_state.yml"
|
||||
},
|
||||
{
|
||||
"name": "puppet_info",
|
||||
"notes": "This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).",
|
||||
"description": "Information on the last [Puppet](https://puppet.com/) run. This table uses data from the `last_run_report` that Puppet creates.",
|
||||
"platforms": [
|
||||
"darwin",
|
||||
"windows",
|
||||
"linux"
|
||||
],
|
||||
"evented": false,
|
||||
"examples": "List all the information available about the last Puppet run.\n```\nSELECT * FROM puppet_info;\n```",
|
||||
"columns": [
|
||||
{
|
||||
"name": "cached_catalog_status",
|
||||
"description": "The status of Puppet catalogs cached on the system.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "catalog_uuid",
|
||||
"description": "The [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) of the catalog downloaded by Puppet.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "code_id",
|
||||
"description": "The `code_id` links the catalog with the compile-time version of file resources using the `puppet:///` URI.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "configuration_version",
|
||||
"description": "The version of the Puppet configuration.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "corrective_change",
|
||||
"description": "A corrective change is triggered when Puppet detects a discrepency between the current state and the expected state of a value.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "environment",
|
||||
"description": "The environment name.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "host",
|
||||
"description": "The host on which Puppet is used.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "kind",
|
||||
"description": "Kind of Puppet run.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "master_used",
|
||||
"description": "The Puppet server used.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "noop",
|
||||
"description": "Indicates if Puppet was run in [noop](https://puppet.com/docs/puppet/latest/metaparameter.html#noop) mode.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "noop_prending",
|
||||
"description": "Items pending from a [noop](https://puppet.com/docs/puppet/latest/metaparameter.html#noop) run.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "puppet_version",
|
||||
"description": "The version of Puppet used during the last run.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "report_format",
|
||||
"description": "The format the Puppet report was exported as.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "status",
|
||||
"description": "The status of Puppet on this system.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "time",
|
||||
"description": "The time of the last Puppet run.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "transaction_completed",
|
||||
"description": "Indicates if the transaction completed or not.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"name": "transaction_uuid",
|
||||
"description": "The [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) of the transaction.",
|
||||
"required": false,
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"url": "https://fleetdm.com/tables/puppet_info",
|
||||
"fleetRepoUrl": "https://github.com/fleetdm/fleet/blob/main/schema/tables/puppet_info.yml"
|
||||
},
|
||||
{
|
||||
"name": "pwd_policy",
|
||||
"platforms": [
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
name: filevault_prk
|
||||
platforms:
|
||||
- darwin
|
||||
description: Returns contents of `/var/db/FileVaultPRK.dat`.
|
||||
columns:
|
||||
- name: base64_encrypted
|
||||
type: text
|
||||
required: false
|
||||
description: The base64-encoded contents of the encrypted FileVault personal recovery key stored at `/var/db/FileVaultPRK.dat` (see also https://developer.apple.com/documentation/devicemanagement/fderecoverykeyescrow)
|
||||
notes: This table is not a core osquery table. It is included as part of [Fleetd](https://fleetdm.com/docs/using-fleet/orbit), the osquery manager from Fleet. Fleetd can be built with [fleetctl](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).
|
||||
evented: false
|
||||
@@ -1433,7 +1433,8 @@ func TestMDMQueries(t *testing.T) {
|
||||
discoveryTable string
|
||||
}{
|
||||
{"fleet_detail_query_mdm_config_profiles_darwin", "macos_profiles"},
|
||||
{"fleet_detail_query_mdm_disk_encryption_key_darwin", "file_lines"},
|
||||
{"fleet_detail_query_mdm_disk_encryption_key_file_darwin", "filevault_prk"},
|
||||
{"fleet_detail_query_mdm_disk_encryption_key_file_lines_darwin", "file_lines"},
|
||||
}
|
||||
|
||||
mdmEnabled := true
|
||||
|
||||
@@ -2,6 +2,8 @@ package osquery_utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
@@ -575,37 +577,57 @@ var extraDetailQueries = map[string]DetailQuery{
|
||||
// They are only sent to the device when Fleet's MDM is on and properly
|
||||
// configured
|
||||
var mdmQueries = map[string]DetailQuery{
|
||||
"mdm_disk_encryption_key_darwin": {
|
||||
// This query has two pre-requisites:
|
||||
//
|
||||
// 1. FileVault must be enabled with a personal recovery key.
|
||||
// 2. The "FileVault Recovery Key Escrow" profile must be configured
|
||||
// in the host.
|
||||
//
|
||||
// This file is safe to access and well [documented by Apple][1]:
|
||||
//
|
||||
// > If FileVault is enabled after this payload is installed on the system,
|
||||
// > the FileVault PRK will be encrypted with the specified certificate,
|
||||
// > wrapped with a CMS envelope and stored at /var/db/FileVaultPRK.dat. The
|
||||
// > encrypted data will be made available to the MDM server as part of the
|
||||
// > SecurityInfo command.
|
||||
// >
|
||||
// > Alternatively, if a site uses its own administration
|
||||
// > software, it can extract the PRK from the foregoing
|
||||
// > location at any time.
|
||||
//
|
||||
// [1]: https://developer.apple.com/documentation/devicemanagement/fderecoverykeyescrow
|
||||
Query: fmt.Sprintf(`SELECT to_base64(group_concat(line, x'0a')) as filevault_key, COALESCE((%s), 0) as encrypted FROM file_lines WHERE path='/var/db/FileVaultPRK.dat'`, usesMacOSDiskEncryptionQuery),
|
||||
Platforms: []string{"darwin"},
|
||||
DirectIngestFunc: directIngestDiskEncryptionKeyDarwin,
|
||||
Discovery: discoveryTable("file_lines"),
|
||||
},
|
||||
"mdm_config_profiles_darwin": {
|
||||
Query: `SELECT display_name, identifier, install_date FROM macos_profiles where type = "Configuration";`,
|
||||
Platforms: []string{"darwin"},
|
||||
DirectIngestFunc: directIngestMacOSProfiles,
|
||||
Discovery: discoveryTable("macos_profiles"),
|
||||
},
|
||||
// There are two mutually-exclusive queries used to read the FileVaultPRK depending on which
|
||||
// extension tables are discovered on the agent. The preferred query uses the newer custom
|
||||
// `filevault_prk` extension table rather than the macadmins `file_lines` table. It is preferred
|
||||
// because the `file_lines` implementation uses bufio.ScanLines which drops end of line
|
||||
// characters.
|
||||
//
|
||||
// Both queries depend on the same pre-requisites:
|
||||
//
|
||||
// 1. FileVault must be enabled with a personal recovery key.
|
||||
// 2. The "FileVault Recovery Key Escrow" profile must be configured
|
||||
// in the host.
|
||||
//
|
||||
// This file is safe to access and well [documented by Apple][1]:
|
||||
//
|
||||
// > If FileVault is enabled after this payload is installed on the system,
|
||||
// > the FileVault PRK will be encrypted with the specified certificate,
|
||||
// > wrapped with a CMS envelope and stored at /var/db/FileVaultPRK.dat. The
|
||||
// > encrypted data will be made available to the MDM server as part of the
|
||||
// > SecurityInfo command.
|
||||
// >
|
||||
// > Alternatively, if a site uses its own administration
|
||||
// > software, it can extract the PRK from the foregoing
|
||||
// > location at any time.
|
||||
//
|
||||
// [1]: https://developer.apple.com/documentation/devicemanagement/fderecoverykeyescrow
|
||||
"mdm_disk_encryption_key_file_lines_darwin": {
|
||||
Query: fmt.Sprintf(`
|
||||
WITH
|
||||
de AS (SELECT IFNULL((%s), 0) as encrypted),
|
||||
fl AS (SELECT line FROM file_lines WHERE path = '/var/db/FileVaultPRK.dat')
|
||||
SELECT encrypted, hex(line) as hex_line FROM de LEFT JOIN fl;`, usesMacOSDiskEncryptionQuery),
|
||||
Platforms: []string{"darwin"},
|
||||
DirectIngestFunc: directIngestDiskEncryptionKeyFileLinesDarwin,
|
||||
Discovery: fmt.Sprintf(`SELECT 1 WHERE EXISTS (%s) AND NOT EXISTS (%s);`, strings.Trim(discoveryTable("file_lines"), ";"), strings.Trim(discoveryTable("filevault_prk"), ";")),
|
||||
},
|
||||
"mdm_disk_encryption_key_file_darwin": {
|
||||
Query: fmt.Sprintf(`
|
||||
WITH
|
||||
de AS (SELECT IFNULL((%s), 0) as encrypted),
|
||||
fv AS (SELECT base64_encrypted as filevault_key FROM filevault_prk)
|
||||
SELECT encrypted, filevault_key FROM de LEFT JOIN fv;`, usesMacOSDiskEncryptionQuery),
|
||||
Platforms: []string{"darwin"},
|
||||
DirectIngestFunc: directIngestDiskEncryptionKeyFileDarwin,
|
||||
Discovery: discoveryTable("filevault_prk"),
|
||||
},
|
||||
}
|
||||
|
||||
// discoveryTable returns a query to determine whether a table exists or not.
|
||||
@@ -1373,7 +1395,9 @@ func directIngestDiskEncryption(ctx context.Context, logger log.Logger, host *fl
|
||||
return ds.SetOrUpdateHostDisksEncryption(ctx, host.ID, encrypted)
|
||||
}
|
||||
|
||||
func directIngestDiskEncryptionKeyDarwin(
|
||||
// directIngestDiskEncryptionKeyFileDarwin ingests the FileVault key from the `filevault_prk`
|
||||
// extension table. It is the preferred method when a host has the extension table available.
|
||||
func directIngestDiskEncryptionKeyFileDarwin(
|
||||
ctx context.Context,
|
||||
logger log.Logger,
|
||||
host *fleet.Host,
|
||||
@@ -1384,7 +1408,7 @@ func directIngestDiskEncryptionKeyDarwin(
|
||||
// assume the extension is not there
|
||||
level.Debug(logger).Log(
|
||||
"component", "service",
|
||||
"method", "directIngestDiskEncryptionKeyDarwin",
|
||||
"method", "directIngestDiskEncryptionKeyFileDarwin",
|
||||
"msg", "no rows or failed",
|
||||
"host", host.Hostname,
|
||||
)
|
||||
@@ -1394,16 +1418,16 @@ func directIngestDiskEncryptionKeyDarwin(
|
||||
if len(rows) > 1 {
|
||||
level.Debug(logger).Log(
|
||||
"component", "service",
|
||||
"method", "directIngestDiskEncryptionKeyDarwin",
|
||||
"msg", fmt.Sprintf("/var/db/FileVaultPRK.dat should have a single line, but got %d", len(rows)),
|
||||
"method", "directIngestDiskEncryptionKeyFileDarwin",
|
||||
"msg", fmt.Sprintf("filevault_prk should have a single row, but got %d", len(rows)),
|
||||
"host", host.Hostname,
|
||||
)
|
||||
}
|
||||
|
||||
if rows[0]["encrypted"] == "0" {
|
||||
if rows[0]["encrypted"] != "1" {
|
||||
level.Debug(logger).Log(
|
||||
"component", "service",
|
||||
"method", "directIngestDiskEncryptionKeyDarwin",
|
||||
"method", "directIngestDiskEncryptionKeyFileDarwin",
|
||||
"msg", "host does not use disk encryption",
|
||||
"host", host.Hostname,
|
||||
)
|
||||
@@ -1415,6 +1439,57 @@ func directIngestDiskEncryptionKeyDarwin(
|
||||
return ds.SetOrUpdateHostDiskEncryptionKey(ctx, host.ID, rows[0]["filevault_key"])
|
||||
}
|
||||
|
||||
// directIngestDiskEncryptionKeyFileLinesDarwin ingests the FileVault key from the `file_lines`
|
||||
// extension table. It is the fallback method in cases where the preferred `filevault_prk` extension
|
||||
// table is not available on the host.
|
||||
func directIngestDiskEncryptionKeyFileLinesDarwin(
|
||||
ctx context.Context,
|
||||
logger log.Logger,
|
||||
host *fleet.Host,
|
||||
ds fleet.Datastore,
|
||||
rows []map[string]string,
|
||||
) error {
|
||||
if len(rows) == 0 {
|
||||
// assume the extension is not there
|
||||
level.Debug(logger).Log(
|
||||
"component", "service",
|
||||
"method", "directIngestDiskEncryptionKeyFileLinesDarwin",
|
||||
"msg", "no rows or failed",
|
||||
"host", host.Hostname,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
var hexLines []string
|
||||
for _, row := range rows {
|
||||
if row["encrypted"] != "1" {
|
||||
level.Debug(logger).Log(
|
||||
"component", "service",
|
||||
"method", "directIngestDiskEncryptionKeyDarwin",
|
||||
"msg", "host does not use disk encryption",
|
||||
"host", host.Hostname,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
hexLines = append(hexLines, row["hex_line"])
|
||||
}
|
||||
// We concatenate the lines in Go rather than using SQL `group_concat` because the order in
|
||||
// which SQL appends the lines is not deterministic, nor guaranteed to be the right order.
|
||||
// We assume that hexadecimal 0A (i.e. new line) was the delimiter used to split all lines;
|
||||
// however, there are edge cases where this will not be true. It is a known limitation
|
||||
// with the `file_lines` extension table and its reliance on bufio.ScanLines that carriage
|
||||
// returns will be lost if the source file contains hexadecimal 0D0A (i.e. carriage
|
||||
// return preceding new line). In such cases, the stored key will be incorrect.
|
||||
b, err := hex.DecodeString(strings.Join(hexLines, "0A"))
|
||||
if err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "decoding hex string")
|
||||
}
|
||||
|
||||
// it's okay if the key comes empty, this can happen and if the disk is
|
||||
// encrypted it means we need to reset the encryption key
|
||||
return ds.SetOrUpdateHostDiskEncryptionKey(ctx, host.ID, base64.StdEncoding.EncodeToString(b))
|
||||
}
|
||||
|
||||
func directIngestMacOSProfiles(
|
||||
ctx context.Context,
|
||||
logger log.Logger,
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package osquery_utils
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -541,7 +545,6 @@ func TestDirectIngestMDMMac(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestDirectIngestMDMWindows(t *testing.T) {
|
||||
@@ -1007,37 +1010,111 @@ func TestDirectIngestDiskEncryptionKeyDarwin(t *testing.T) {
|
||||
ds := new(mock.Store)
|
||||
ctx := context.Background()
|
||||
logger := log.NewNopLogger()
|
||||
wantKey := "OTM5ODRDQTYtOUY1Mi00NERELTkxOUEtMDlBN0ZBOUUzNUY5Cg=="
|
||||
host := &fleet.Host{ID: 1}
|
||||
|
||||
var wantKey string
|
||||
|
||||
mockFileLines := func(wantKey string, wantEncrypted string) []map[string]string {
|
||||
var output []map[string]string
|
||||
scanner := bufio.NewScanner(bytes.NewBuffer([]byte(wantKey)))
|
||||
scanner.Split(bufio.ScanLines)
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
item := make(map[string]string)
|
||||
item["hex_line"] = hex.EncodeToString([]byte(line))
|
||||
item["encrypted"] = wantEncrypted
|
||||
output = append(output, item)
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
mockFilevaultPRK := func(wantKey string, wantEncrypted string) []map[string]string {
|
||||
return []map[string]string{
|
||||
{"filevault_key": base64.StdEncoding.EncodeToString([]byte(wantKey)), "encrypted": wantEncrypted},
|
||||
}
|
||||
}
|
||||
|
||||
ds.SetOrUpdateHostDiskEncryptionKeyFunc = func(ctx context.Context, hostID uint, encryptedBase64Key string) error {
|
||||
require.Empty(t, encryptedBase64Key)
|
||||
require.Equal(t, host.ID, hostID)
|
||||
if base64.StdEncoding.EncodeToString([]byte(wantKey)) != encryptedBase64Key {
|
||||
return errors.New("key mismatch")
|
||||
}
|
||||
if host.ID != hostID {
|
||||
return errors.New("host ID mismatch")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
err := directIngestDiskEncryptionKeyDarwin(ctx, logger, host, ds, []map[string]string{})
|
||||
require.NoError(t, err)
|
||||
require.False(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
t.Run("empty key", func(t *testing.T) {
|
||||
err := directIngestDiskEncryptionKeyFileLinesDarwin(ctx, logger, host, ds, []map[string]string{})
|
||||
require.NoError(t, err)
|
||||
require.False(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
|
||||
err = directIngestDiskEncryptionKeyDarwin(ctx, logger, host, ds, []map[string]string{{"encrypted": "0"}})
|
||||
require.NoError(t, err)
|
||||
require.False(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
err = directIngestDiskEncryptionKeyFileDarwin(ctx, logger, host, ds, []map[string]string{})
|
||||
require.NoError(t, err)
|
||||
require.False(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
|
||||
err = directIngestDiskEncryptionKeyDarwin(ctx, logger, host, ds, []map[string]string{{"filevault_key": ""}})
|
||||
require.NoError(t, err)
|
||||
require.True(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked = false
|
||||
err = directIngestDiskEncryptionKeyFileLinesDarwin(ctx, logger, host, ds, []map[string]string{{"encrypted": "0"}})
|
||||
require.NoError(t, err)
|
||||
require.False(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
|
||||
ds.SetOrUpdateHostDiskEncryptionKeyFunc = func(ctx context.Context, hostID uint, encryptedBase64Key string) error {
|
||||
require.Equal(t, wantKey, encryptedBase64Key)
|
||||
require.Equal(t, host.ID, hostID)
|
||||
return nil
|
||||
}
|
||||
err = directIngestDiskEncryptionKeyFileDarwin(ctx, logger, host, ds, []map[string]string{{"encrypted": "0"}})
|
||||
require.NoError(t, err)
|
||||
require.False(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
|
||||
err = directIngestDiskEncryptionKeyDarwin(ctx, logger, host, ds, []map[string]string{{"filevault_key": wantKey}})
|
||||
require.NoError(t, err)
|
||||
require.True(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
err = directIngestDiskEncryptionKeyFileLinesDarwin(ctx, logger, host, ds, []map[string]string{{"encrypted": "1"}})
|
||||
require.NoError(t, err)
|
||||
require.True(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked = false
|
||||
|
||||
err = directIngestDiskEncryptionKeyFileDarwin(ctx, logger, host, ds, []map[string]string{{"encrypted": "1"}})
|
||||
require.NoError(t, err)
|
||||
require.True(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked = false
|
||||
|
||||
err = directIngestDiskEncryptionKeyFileLinesDarwin(ctx, logger, host, ds, []map[string]string{{"encrypted": "1", "hex_line": ""}})
|
||||
require.NoError(t, err)
|
||||
require.True(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked = false
|
||||
|
||||
err = directIngestDiskEncryptionKeyFileDarwin(ctx, logger, host, ds, []map[string]string{{"encrypted": "1", "filevault_key": ""}})
|
||||
require.NoError(t, err)
|
||||
require.True(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked = false
|
||||
})
|
||||
|
||||
t.Run("key contains new lines and carriage return", func(t *testing.T) {
|
||||
wantKey = "This is only a \n\r\n\n test."
|
||||
|
||||
err := directIngestDiskEncryptionKeyFileLinesDarwin(ctx, logger, host, ds, mockFileLines(wantKey, "1"))
|
||||
// it is a known limitation with the current file_lines implementation that causes this to fail
|
||||
// because it relies on bufio.ScanLines, which drops "\r" from "\r\n"
|
||||
require.ErrorContains(t, err, "key mismatch")
|
||||
require.True(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked = false
|
||||
|
||||
err = directIngestDiskEncryptionKeyFileDarwin(ctx, logger, host, ds, mockFilevaultPRK(wantKey, "1"))
|
||||
// filevault_prk does not have the scan lines limitation
|
||||
require.NoError(t, err)
|
||||
require.True(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked = false
|
||||
})
|
||||
|
||||
t.Run("key contains new lines", func(t *testing.T) {
|
||||
wantKey = "This is only a \n\n\n test."
|
||||
|
||||
err := directIngestDiskEncryptionKeyFileLinesDarwin(ctx, logger, host, ds, mockFileLines(wantKey, "1"))
|
||||
// new lines are not a problem if they are not preceded by carriage return
|
||||
require.NoError(t, err)
|
||||
require.True(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked = false
|
||||
|
||||
err = directIngestDiskEncryptionKeyFileDarwin(ctx, logger, host, ds, mockFilevaultPRK(wantKey, "1"))
|
||||
// filevault_prk does not have the scan lines limitation
|
||||
require.NoError(t, err)
|
||||
require.True(t, ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked)
|
||||
ds.SetOrUpdateHostDiskEncryptionKeyFuncInvoked = false
|
||||
})
|
||||
}
|
||||
|
||||
func TestDirectIngestHostMacOSProfiles(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user