From 4e57bcff6dcf3571863aea1e0d855b7d4847093d Mon Sep 17 00:00:00 2001 From: Joanne Stableford <59930035+JoStableford@users.noreply.github.com> Date: Tue, 23 Jul 2024 11:46:43 -0400 Subject: [PATCH 1/5] Add clarity on the report format for quarterly quirks (#20582) --- handbook/business-operations/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/handbook/business-operations/README.md b/handbook/business-operations/README.md index 42fde0e9be..07148c4af0 100644 --- a/handbook/business-operations/README.md +++ b/handbook/business-operations/README.md @@ -375,7 +375,7 @@ No later than the second month of every quarter, we check [Delaware divison of c ### Check finances for quirks Every quarter, we check Quickbooks Online (QBO) for discrepancies and follow up on quirks. 1. Check to make sure [bookkeeping quirks](https://docs.google.com/spreadsheets/d/1nuUPMZb1z_lrbaQEcgjnxppnYv_GWOTTo4FMqLOlsWg/edit?usp=sharing) are all accounted for and resolved or in progress toward resolution. -2. Check balance sheet and profit and loss statements (P&Ls) in QBO against the latest [monthly workbooks](https://drive.google.com/drive/folders/1ben-xJgL5MlMJhIl2OeQpDjbk-pF6eJM) in Google Drive. +2. Check balance sheet and profit and loss statements (P&Ls) in QBO against the latest [monthly workbooks](https://drive.google.com/drive/folders/1ben-xJgL5MlMJhIl2OeQpDjbk-pF6eJM) in Google Drive. Ensure reports are in the "accural" accounting method. 3. Reach out to Pilot with any differences or quirks, and ask them to resolve/provide clarity. This often will need to happen over a call to review sycnhronously. 4. Once quirks are resolved, note the day it was resolved in the spreadsheet. From f4b9d1f6d80e58d340df2d8d94553872ba913df6 Mon Sep 17 00:00:00 2001 From: RachelElysia <71795832+RachelElysia@users.noreply.github.com> Date: Tue, 23 Jul 2024 12:13:09 -0400 Subject: [PATCH 2/5] Fleet UI: Add iOS, iPadOS to Apple Profile activity updates (#20578) --- ...x-profile-activities-to-include-ios-ipados | 1 + frontend/interfaces/activity.ts | 9 ++-- .../ActivityItem/ActivityItem.tsx | 48 ++++++++++--------- 3 files changed, 32 insertions(+), 26 deletions(-) create mode 100644 changes/20575-fix-profile-activities-to-include-ios-ipados diff --git a/changes/20575-fix-profile-activities-to-include-ios-ipados b/changes/20575-fix-profile-activities-to-include-ios-ipados new file mode 100644 index 0000000000..bf089bf489 --- /dev/null +++ b/changes/20575-fix-profile-activities-to-include-ios-ipados @@ -0,0 +1 @@ +- Update profile activities to include iOS and iPadOS diff --git a/frontend/interfaces/activity.ts b/frontend/interfaces/activity.ts index 06732e90ef..2ca026aa47 100644 --- a/frontend/interfaces/activity.ts +++ b/frontend/interfaces/activity.ts @@ -36,9 +36,12 @@ export enum ActivityType { MdmUnenrolled = "mdm_unenrolled", EditedMacosMinVersion = "edited_macos_min_version", ReadHostDiskEncryptionKey = "read_host_disk_encryption_key", - CreatedMacOSProfile = "created_macos_profile", - DeletedMacOSProfile = "deleted_macos_profile", - EditedMacOSProfile = "edited_macos_profile", + /** Note: BE not renamed (yet) from macOS even though activity is also used for iOS and iPadOS */ + CreatedAppleOSProfile = "created_macos_profile", + /** Note: BE not renamed (yet) from macOS even though activity is also used for iOS and iPadOS */ + DeletedAppleOSProfile = "deleted_macos_profile", + /** Note: BE not renamed (yet) from macOS even though activity is also used for iOS and iPadOS */ + EditedAppleOSProfile = "edited_macos_profile", CreatedWindowsProfile = "created_windows_profile", DeletedWindowsProfile = "deleted_windows_profile", EditedWindowsProfile = "edited_windows_profile", diff --git a/frontend/pages/DashboardPage/cards/ActivityFeed/ActivityItem/ActivityItem.tsx b/frontend/pages/DashboardPage/cards/ActivityFeed/ActivityItem/ActivityItem.tsx index d8deaf0fe7..9889bf98a5 100644 --- a/frontend/pages/DashboardPage/cards/ActivityFeed/ActivityItem/ActivityItem.tsx +++ b/frontend/pages/DashboardPage/cards/ActivityFeed/ActivityItem/ActivityItem.tsx @@ -36,10 +36,11 @@ const PREMIUM_ACTIVITIES = new Set([ const getProfileMessageSuffix = ( isPremiumTier: boolean, - platform: "darwin" | "windows", + platform: "apple" | "windows", teamName?: string | null ) => { - const platformDisplayName = platform === "darwin" ? "macOS" : "Windows"; + const platformDisplayName = + platform === "apple" ? "macOS, iOS, and iPadOS" : "Windows"; let messageSuffix = <>all {platformDisplayName} hosts; if (isPremiumTier) { messageSuffix = teamName ? ( @@ -345,7 +346,7 @@ const TAGGED_TEMPLATES = { ); }, - createMacOSProfile: (activity: IActivity, isPremiumTier: boolean) => { + createdAppleOSProfile: (activity: IActivity, isPremiumTier: boolean) => { const profileName = activity.details?.profile_name; return ( <> @@ -361,14 +362,14 @@ const TAGGED_TEMPLATES = { to{" "} {getProfileMessageSuffix( isPremiumTier, - "darwin", + "apple", activity.details?.team_name )} . ); }, - deleteMacOSProfile: (activity: IActivity, isPremiumTier: boolean) => { + deletedAppleOSProfile: (activity: IActivity, isPremiumTier: boolean) => { const profileName = activity.details?.profile_name; return ( <> @@ -384,28 +385,28 @@ const TAGGED_TEMPLATES = { from{" "} {getProfileMessageSuffix( isPremiumTier, - "darwin", + "apple", activity.details?.team_name )} . ); }, - editMacOSProfile: (activity: IActivity, isPremiumTier: boolean) => { + editedAppleOSProfile: (activity: IActivity, isPremiumTier: boolean) => { return ( <> {" "} edited configuration profiles for{" "} {getProfileMessageSuffix( isPremiumTier, - "darwin", + "apple", activity.details?.team_name )}{" "} via fleetctl. ); }, - createWindowsProfile: (activity: IActivity, isPremiumTier: boolean) => { + createdWindowsProfile: (activity: IActivity, isPremiumTier: boolean) => { const profileName = activity.details?.profile_name; return ( <> @@ -428,7 +429,7 @@ const TAGGED_TEMPLATES = { ); }, - deleteWindowsProfile: (activity: IActivity, isPremiumTier: boolean) => { + deletedWindowsProfile: (activity: IActivity, isPremiumTier: boolean) => { const profileName = activity.details?.profile_name; return ( <> @@ -451,7 +452,7 @@ const TAGGED_TEMPLATES = { ); }, - editWindowsProfile: (activity: IActivity, isPremiumTier: boolean) => { + editedWindowsProfile: (activity: IActivity, isPremiumTier: boolean) => { return ( <> {" "} @@ -781,7 +782,7 @@ const TAGGED_TEMPLATES = { to{" "} {getProfileMessageSuffix( isPremiumTier, - "darwin", + "apple", activity.details?.team_name )} . @@ -796,7 +797,7 @@ const TAGGED_TEMPLATES = { {activity.details?.profile_name} from{" "} {getProfileMessageSuffix( isPremiumTier, - "darwin", + "apple", activity.details?.team_name )} . @@ -811,7 +812,7 @@ const TAGGED_TEMPLATES = { {activity.details?.profile_name} for{" "} {getProfileMessageSuffix( isPremiumTier, - "darwin", + "apple", activity.details?.team_name )}{" "} via fleetctl. @@ -964,26 +965,27 @@ const getDetail = ( case ActivityType.EditedMacosMinVersion: { return TAGGED_TEMPLATES.editedMacosMinVersion(activity); } + case ActivityType.ReadHostDiskEncryptionKey: { return TAGGED_TEMPLATES.readHostDiskEncryptionKey(activity); } - case ActivityType.CreatedMacOSProfile: { - return TAGGED_TEMPLATES.createMacOSProfile(activity, isPremiumTier); + case ActivityType.CreatedAppleOSProfile: { + return TAGGED_TEMPLATES.createdAppleOSProfile(activity, isPremiumTier); } - case ActivityType.DeletedMacOSProfile: { - return TAGGED_TEMPLATES.deleteMacOSProfile(activity, isPremiumTier); + case ActivityType.DeletedAppleOSProfile: { + return TAGGED_TEMPLATES.deletedAppleOSProfile(activity, isPremiumTier); } - case ActivityType.EditedMacOSProfile: { - return TAGGED_TEMPLATES.editMacOSProfile(activity, isPremiumTier); + case ActivityType.EditedAppleOSProfile: { + return TAGGED_TEMPLATES.editedAppleOSProfile(activity, isPremiumTier); } case ActivityType.CreatedWindowsProfile: { - return TAGGED_TEMPLATES.createWindowsProfile(activity, isPremiumTier); + return TAGGED_TEMPLATES.createdWindowsProfile(activity, isPremiumTier); } case ActivityType.DeletedWindowsProfile: { - return TAGGED_TEMPLATES.deleteWindowsProfile(activity, isPremiumTier); + return TAGGED_TEMPLATES.deletedWindowsProfile(activity, isPremiumTier); } case ActivityType.EditedWindowsProfile: { - return TAGGED_TEMPLATES.editWindowsProfile(activity, isPremiumTier); + return TAGGED_TEMPLATES.editedWindowsProfile(activity, isPremiumTier); } // Note: Both "enabled_disk_encryption" and "enabled_macos_disk_encryption" display the same // message. The latter is deprecated in the API but it is retained here for backwards compatibility. From 02b88e69253e24b1f633240c8da937183f5f9a3f Mon Sep 17 00:00:00 2001 From: Lucas Manuel Rodriguez Date: Tue, 23 Jul 2024 14:57:27 -0300 Subject: [PATCH 3/5] Improvements to releaser script and adding arm64 to tuf.md (#20635) - Improvements to the releaser.sh script - Added arm64 https://github.com/fleetdm/fleet/blob/main/orbit/TUF.md. --- tools/tuf/releaser.sh | 43 +++++++++++++++++++--------------- tools/tuf/status/tuf-status.go | 25 +++++++++++--------- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/tools/tuf/releaser.sh b/tools/tuf/releaser.sh index cab40567d4..cf669577c2 100755 --- a/tools/tuf/releaser.sh +++ b/tools/tuf/releaser.sh @@ -58,9 +58,9 @@ setup () { cp -r "$KEYS_SOURCE_DIRECTORY" "$KEYS_DIRECTORY" if ! aws sts get-caller-identity &> /dev/null; then - prompt "You need to login to AWS using the cli, press any key to continue..." + prompt "You need to login to AWS using the cli." aws sso login - prompt "AWS SSO login was successful, press any key to continue..." + prompt "AWS SSO login was successful." fi # GITHUB_TOKEN is only necessary when releasing to edge. @@ -71,9 +71,9 @@ setup () { # We only need to be logged in to github when releasing to edge. if [[ $ACTION == "release-to-edge" ]]; then if ! gh auth status >/dev/null 2>&1; then - prompt "You need to login to Github using the cli, press any key to continue..." + prompt "You need to login to Github using the cli." gh auth login - prompt "Github login was successful, press any key to continue..." + prompt "Github login was successful." fi fi @@ -97,7 +97,7 @@ setup () { pull_from_remote () { echo "Pulling repository from tuf.fleetctl.com... (--dryrun first)" aws s3 sync s3://fleet-tuf-repo "$REPOSITORY_DIRECTORY" --exact-timestamps --dryrun - prompt "If the --dryrun looks good, press any key to continue... (no output means nothing to update)" + prompt "Check if the above --dry-run looks good (no output means nothing to update)." aws s3 sync s3://fleet-tuf-repo "$REPOSITORY_DIRECTORY" --exact-timestamps } @@ -157,7 +157,7 @@ release_fleetd_to_edge () { BRANCH_NAME="release-fleetd-v$VERSION" ORBIT_TAG="orbit-v$VERSION" if [[ "$SKIP_PR_AND_TAG_PUSH" != "1" ]]; then - prompt "A PR for bumping the fleetd version will be created to trigger a Github Action that will build 'Fleet Desktop'. Press any key to continue..." + prompt "A PR will be created to trigger a Github Action to build desktop." pushd "$GIT_REPOSITORY_DIRECTORY" git checkout -b "$BRANCH_NAME" make changelog-orbit version="$VERSION" @@ -166,10 +166,8 @@ release_fleetd_to_edge () { git add .github/workflows/generate-desktop-targets.yml "$ORBIT_CHANGELOG" git commit -m "Release fleetd $VERSION" git push origin "$BRANCH_NAME" - prompt "A PR will be created, press any key to continue..." gh pr create -f -B main -t "Release fleetd $VERSION" - prompt "Press any key to continue after the PR is created and you have made all the necessary edits to it..." - prompt "A 'git tag' will be created to trigger a Github Action to build orbit, press any key to continue..." + prompt "A 'git tag' will be created to trigger a Github Action to build orbit." git tag "$ORBIT_TAG" git push origin "$ORBIT_TAG" popd @@ -202,7 +200,7 @@ release_fleetd_to_edge () { release_osqueryd_to_edge () { echo "Releasing osqueryd to edge..." - prompt "A branch and PR for bumping the osquery version will be created. Press any key to continue..." + prompt "A branch and PR for bumping the osquery version will be created." BRANCH_NAME=release-osqueryd-v$VERSION if [[ "$SKIP_PR_AND_TAG_PUSH" != "1" ]]; then pushd "$GIT_REPOSITORY_DIRECTORY" @@ -211,8 +209,8 @@ release_osqueryd_to_edge () { git add .github/workflows/generate-osqueryd-targets.yml git commit -m "Bump osqueryd version to $VERSION" git push origin "$BRANCH_NAME" - open "https://github.com/fleetdm/fleet/pull/new/$BRANCH_NAME" - prompt "Press any key to continue after the PR is created..." + prompt "A PR will be created to trigger a Github Action to build osqueryd." + gh pr create -f -B main -t "Release osqueryd $VERSION" popd fi OSQUERYD_ARTIFACT_DOWNLOAD_DIRECTORY="$ARTIFACTS_DOWNLOAD_DIRECTORY/osqueryd" @@ -253,7 +251,7 @@ push_to_remote () { aws s3 sync "$REPOSITORY_DIRECTORY" s3://fleet-tuf-repo --dryrun if [[ $PUSH_TO_REMOTE == "1" ]]; then echo "WARNING: This step will push the release to tuf.fleetctl.com (production)..." - prompt "If the --dryrun looks good, press any key to continue..." + prompt "Check if the above --dry-run looks good." aws s3 sync "$REPOSITORY_DIRECTORY" s3://fleet-tuf-repo echo "Release has been pushed!" echo "NOTE: You might see some clients failing to upgrade due to some sha256 mismatches." @@ -265,7 +263,14 @@ push_to_remote () { prompt () { printf "%s\n" "$1" - read -r -s -n 1 + printf "Type 'yes' to continue... " + while read -r word; + do + if [[ "$word" == "yes" ]]; then + printf "\n" + return + fi + done } setup_to_become_publisher () { @@ -279,7 +284,7 @@ setup_to_become_publisher () { mkdir -p "$KEYS_DIRECTORY" if ! aws sts get-caller-identity &> /dev/null; then aws sso login - prompt "AWS SSO login was successful, press any key to continue..." + prompt "AWS SSO login was successful." fi # These need to be exported for use by `tuf` commands. FLEET_TARGETS_PASSPHRASE=$(op read "op://$TARGETS_PASSPHRASE_1PASSWORD_PATH") @@ -306,15 +311,15 @@ fi print_reminder () { if [[ $ACTION == "release-to-edge" ]]; then if [[ $COMPONENT == "fleetd" ]]; then - prompt "Make sure to install fleetd with '--orbit-channel=edge --desktop-channel=edge' on a Linux, Windows and macOS VM. (To smoke test the release.) Press any key to continue..." + prompt "Make sure to install fleetd with '--orbit-channel=edge --desktop-channel=edge' on a Linux, Windows and macOS VM. (To smoke test the release.)" elif [[ $COMPONENT == "osqueryd" ]]; then - prompt "Make sure to install fleetd with '--osqueryd-channel=edge' on a Linux, Windows and macOS VM. (To smoke test the release.) Press any key to continue..." + prompt "Make sure to install fleetd with '--osqueryd-channel=edge' on a Linux, Windows and macOS VM. (To smoke test the release.)" fi elif [[ $ACTION == "promote-edge-to-stable" ]]; then if [[ $COMPONENT == "fleetd" ]]; then - prompt "Make sure to install fleetd with '--orbit-channel=stable --desktop-channel=stable' on a Linux, Windows and macOS VM. (To smoke test the release.) Press any key to continue..." + prompt "Make sure to install fleetd with '--orbit-channel=stable --desktop-channel=stable' on a Linux, Windows and macOS VM. (To smoke test the release.)" elif [[ $COMPONENT == "osqueryd" ]]; then - prompt "Make sure to install fleetd with '--osqueryd-channel=stable' on a Linux, Windows and macOS VM. (To smoke test the release.) Press any key to continue..." + prompt "Make sure to install fleetd with '--osqueryd-channel=stable' on a Linux, Windows and macOS VM. (To smoke test the release.)" fi else echo "Unsupported action: $ACTION" diff --git a/tools/tuf/status/tuf-status.go b/tools/tuf/status/tuf-status.go index 56e57d5349..6f8aa6fd36 100644 --- a/tools/tuf/status/tuf-status.go +++ b/tools/tuf/status/tuf-status.go @@ -163,19 +163,22 @@ func byteCountSI(b int64) string { func channelVersionCommand() *cli.Command { componentFileMap := map[string]map[string]string{ "orbit": { - "linux": "orbit", - "macos": "orbit", - "windows": "orbit.exe", + "linux": "orbit", + "linux-arm64": "orbit", + "macos": "orbit", + "windows": "orbit.exe", }, "desktop": { - "linux": "desktop.tar.gz", - "macos": "desktop.app.tar.gz", - "windows": "fleet-desktop.exe", + "linux": "desktop.tar.gz", + "linux-arm64": "desktop.tar.gz", + "macos": "desktop.app.tar.gz", + "windows": "fleet-desktop.exe", }, "osqueryd": { - "linux": "osqueryd", - "macos-app": "osqueryd.app.tar.gz", - "windows": "osqueryd.exe", + "linux": "osqueryd", + "linux-arm64": "osqueryd", + "macos-app": "osqueryd.app.tar.gz", + "windows": "osqueryd.exe", }, "nudge": { "macos": "nudge.app.tar.gz", @@ -305,7 +308,7 @@ func channelVersionCommand() *cli.Command { fmt.Printf("%s\n", b) } else if format == "markdown" { table := tablewriter.NewWriter(os.Stdout) - table.SetHeader([]string{"Component\\OS", "macOS", "Linux", "Windows"}) + table.SetHeader([]string{"Component\\OS", "macOS", "Linux", "Windows", "Linux (arm64)"}) table.SetAutoFormatHeaders(false) table.SetCenterSeparator("|") table.SetHeaderLine(true) @@ -332,7 +335,7 @@ func channelVersionCommand() *cli.Command { for _, component := range componentsInOrder { oss := outputMap[component] row := []string{component} - for _, os := range []string{"macos", "linux", "windows"} { + for _, os := range []string{"macos", "linux", "windows", "linux-arm64"} { row = append(row, setIfEmpty(oss, os)) } rows = append(rows, row) From ea354ef479ecc0dce754738b9fd9f0fdbd905c39 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 15:01:15 -0300 Subject: [PATCH 4/5] Update versions of fleetd components in Fleet's TUF [automated] (#20647) Automated change from [GitHub action](https://github.com/fleetdm/fleet/actions/workflows/fleetd-tuf.yml). Co-authored-by: lucasmrod --- orbit/TUF.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/orbit/TUF.md b/orbit/TUF.md index dd965549b8..1bb2fbb7dc 100644 --- a/orbit/TUF.md +++ b/orbit/TUF.md @@ -5,20 +5,20 @@ Following are the currently deployed versions of fleetd components on the `stabl ## `stable` -| Component\OS | macOS | Linux | Windows | -|--------------|--------------|--------|---------| -| orbit | 1.27.0 | 1.27.0 | 1.27.0 | -| desktop | 1.27.0 | 1.27.0 | 1.27.0 | -| osqueryd | 5.12.1 | 5.12.1 | 5.12.1 | -| nudge | 1.1.10.81462 | - | - | -| swiftDialog | 2.1.0 | - | - | +| Component\OS | macOS | Linux | Windows | Linux (arm64) | +|--------------|--------------|--------|---------|---------------| +| orbit | 1.28.0 | 1.28.0 | 1.28.0 | 1.28.0 | +| desktop | 1.28.0 | 1.28.0 | 1.28.0 | 1.28.0 | +| osqueryd | 5.12.1 | 5.12.1 | 5.12.1 | 5.12.1 | +| nudge | 1.1.10.81462 | - | - | - | +| swiftDialog | 2.1.0 | - | - | - | ## `edge` -| Component\OS | macOS | Linux | Windows | -|--------------|--------|--------|---------| -| orbit | 1.28.0 | 1.28.0 | 1.28.0 | -| desktop | 1.28.0 | 1.28.0 | 1.28.0 | -| osqueryd | 5.12.2 | 5.12.2 | 5.12.2 | -| nudge | - | - | - | -| swiftDialog | - | - | - | +| Component\OS | macOS | Linux | Windows | Linux (arm64) | +|--------------|--------|--------|---------|---------------| +| orbit | 1.28.0 | 1.28.0 | 1.28.0 | 1.28.0 | +| desktop | 1.28.0 | 1.28.0 | 1.28.0 | 1.28.0 | +| osqueryd | 5.12.2 | 5.12.2 | 5.12.2 | 5.12.1 | +| nudge | - | - | - | - | +| swiftDialog | - | - | - | - | From 650914519dd07559034b97c705efe4ededdbe8f5 Mon Sep 17 00:00:00 2001 From: Roberto Dip Date: Tue, 23 Jul 2024 13:11:18 -0500 Subject: [PATCH 5/5] Add a tool to extract MDM assets from a Fleet database (#20659) --- tools/mdm/assets/README.md | 30 +++++++++++ tools/mdm/assets/main.go | 105 +++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 tools/mdm/assets/README.md create mode 100644 tools/mdm/assets/main.go diff --git a/tools/mdm/assets/README.md b/tools/mdm/assets/README.md new file mode 100644 index 0000000000..60788ce53f --- /dev/null +++ b/tools/mdm/assets/README.md @@ -0,0 +1,30 @@ +## MDM asset extractor + +The MDM Asset Extractor is a tool designed to extract all MDM assets from a +Fleet database. The assets are extracted unencrypted; hence, the key used for +encrypting the assets must be provided. + +### Usage + +During development, a typical usage example would be: + +``` +go run tools/mdm/assets/main.go -key=E6Ow1t2dbKARxEF6O9GFI3DDQRMROhI8 -dir=mdm_assets +``` + +Supported flags are: + +``` + -db-address string + Address used to connect to the MySQL instance (default "localhost:3306") + -db-name string + Name of the database with the asset information in the MySQL instance (default "fleet") + -db-password string + Password used to connect to the MySQL instance (default "insecure") + -db-user string + Username used to connect to the MySQL instance (default "fleet") + -dir string + Directory to put the exported assets + -key string + Key used to encrypt the assets +``` diff --git a/tools/mdm/assets/main.go b/tools/mdm/assets/main.go new file mode 100644 index 0000000000..c8ef62152b --- /dev/null +++ b/tools/mdm/assets/main.go @@ -0,0 +1,105 @@ +package main + +import ( + "context" + "database/sql" + "errors" + "flag" + "fmt" + "log" + "os" + "path/filepath" + "strings" + + "github.com/WatchBeam/clock" + "github.com/fleetdm/fleet/v4/server/config" + "github.com/fleetdm/fleet/v4/server/datastore/mysql" + "github.com/fleetdm/fleet/v4/server/fleet" +) + +const ( + testUsername = "fleet" + testPassword = "insecure" + testAddress = "localhost:3306" + testDatabase = "fleet" +) + +func main() { + flagKey := flag.String("key", "", "Key used to encrypt the assets") + flagDir := flag.String("dir", "", "Directory to put the exported assets") + flagDBUser := flag.String("db-user", testUsername, "Username used to connect to the MySQL instance") + flagDBPass := flag.String("db-password", testPassword, "Password used to connect to the MySQL instance") + flagDBAddress := flag.String("db-address", testAddress, "Address used to connect to the MySQL instance") + flagDBName := flag.String("db-name", testDatabase, "Name of the database with the asset information in the MySQL instance") + flag.Parse() + + if *flagKey == "" { + log.Fatal("-key flag is required") + } + + if *flagDir != "" { + if err := os.MkdirAll(*flagDir, os.ModePerm); err != nil { + log.Fatal("ensuring directory: ", err) + } + } + + db, err := sql.Open( + "mysql", + fmt.Sprintf("%s:%s@tcp(%s)/?multiStatements=true", testUsername, testPassword, testAddress), + ) + if err != nil { + log.Fatal("opening MySQL connection:", err) + } + defer db.Close() + + mysqlCfg := config.MysqlConfig{ + Username: *flagDBUser, + Password: *flagDBPass, + Address: *flagDBAddress, + Database: *flagDBName, + } + ds, err := mysql.New( + mysqlCfg, + clock.NewMockClock(), + mysql.LimitAttempts(1), + mysql.WithFleetConfig(&config.FleetConfig{ + Server: config.ServerConfig{ + PrivateKey: *flagKey, + }, + }), + ) + if err != nil { + log.Fatal("creating datastore instance:", err) + } + defer ds.Close() + + ctx := context.Background() + assets, err := ds.GetAllMDMConfigAssetsByName(ctx, []fleet.MDMAssetName{ + fleet.MDMAssetCACert, + fleet.MDMAssetCAKey, + fleet.MDMAssetAPNSKey, + fleet.MDMAssetAPNSCert, + fleet.MDMAssetABMCert, + fleet.MDMAssetABMKey, + fleet.MDMAssetABMToken, + fleet.MDMAssetSCEPChallenge, + }) + if err != nil && !errors.Is(err, mysql.ErrPartialResult) { + log.Fatal("retrieving assets from db:", err) + } + + for _, asset := range assets { + path := filepath.Join(*flagDir, string(asset.Name)) + switch { + case strings.Contains(path, "_key"): + path = path + ".key" + case strings.Contains(path, "_cert"): + path = path + ".crt" + } + if err := os.WriteFile(path, asset.Value, 0600); err != nil { + log.Fatal("writing asset:", err) + } + + log.Printf("wrote %s in %s", asset.Name, path) + } +}