mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 00:45:19 +00:00
Move external dependency osquery-in-a-box
to monorepo (#15871)
#15563 - [X] Manual QA for all new/changed functionality Tested by running the following: If the changes haven't been merged to `main`: ```sh fleetctl preview --preview-config 15563-move-external-dep-osquery-in-a-box-to-monorepo fleetctl preview stop fleetctl preview reset ``` If the changes were already merged to `main`: ```sh fleetctl preview fleetctl preview stop fleetctl preview reset ```
This commit is contained in:
parent
edaa7acac3
commit
4627a92447
12
.github/workflows/fleetctl-preview-latest.yml
vendored
12
.github/workflows/fleetctl-preview-latest.yml
vendored
@ -17,6 +17,7 @@ on:
|
||||
- 'orbit/**.go'
|
||||
- 'ee/fleetctl/**.go'
|
||||
- 'docs/01-Using-Fleet/standard-query-library/standard-query-library.yml'
|
||||
- 'tools/osquery/in-a-box'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'cmd/fleetctl/**.go'
|
||||
@ -26,6 +27,7 @@ on:
|
||||
- 'orbit/**.go'
|
||||
- 'ee/fleetctl/**.go'
|
||||
- 'docs/01-Using-Fleet/standard-query-library/standard-query-library.yml'
|
||||
- 'tools/osquery/in-a-box'
|
||||
workflow_dispatch: # Manual
|
||||
|
||||
# This allows a subsequently queued workflow run to interrupt previous runs
|
||||
@ -68,16 +70,22 @@ jobs:
|
||||
|
||||
- name: Run fleetctl preview
|
||||
run: |
|
||||
./build/fleetctl preview --std-query-lib-file-path $(pwd)/docs/01-Using-Fleet/standard-query-library/standard-query-library.yml
|
||||
./build/fleetctl preview \
|
||||
--preview-config-path ./tools/osquery/in-a-box \
|
||||
--std-query-lib-file-path $(pwd)/docs/01-Using-Fleet/standard-query-library/standard-query-library.yml
|
||||
sleep 10
|
||||
./build/fleetctl get hosts | tee hosts.txt
|
||||
[ $( cat hosts.txt | grep online | wc -l) -eq 9 ]
|
||||
|
||||
- name: Get fleet logs
|
||||
if: always()
|
||||
run: |
|
||||
FLEET_LICENSE_KEY=foo docker compose -f ~/.fleet/preview/docker-compose.yml logs fleet01 fleet02 > fleet-logs.txt
|
||||
# Copying logs, otherwise the upload-artifact action uploads the logs in a hidden folder (.fleet)
|
||||
cp ~/.fleet/preview/orbit.log orbit.log
|
||||
# Old location of orbit logs before v4.43.0
|
||||
cp ~/.fleet/preview/orbit.log orbit.log || true
|
||||
# New location of orbit logs since v4.43.0
|
||||
cp ~/.fleet/preview/orbit/orbit.log orbit.log || true
|
||||
cp -r ~/.fleet/preview/logs osquery_result_status_logs
|
||||
|
||||
- name: Upload logs
|
||||
|
11
.github/workflows/fleetctl-preview.yml
vendored
11
.github/workflows/fleetctl-preview.yml
vendored
@ -27,12 +27,6 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
||||
- name: Start tunnel
|
||||
run: |
|
||||
npm install -g localtunnel
|
||||
lt --port 1337 &
|
||||
sleep 5
|
||||
|
||||
- name: Test fleetctl preview
|
||||
run: |
|
||||
npm install -g fleetctl
|
||||
@ -47,7 +41,10 @@ jobs:
|
||||
run: |
|
||||
FLEET_LICENSE_KEY=foo docker compose -f ~/.fleet/preview/docker-compose.yml logs fleet01 fleet02 > fleet-logs.txt
|
||||
# Copying logs, otherwise the upload-artifact action uploads the logs in a hidden folder (.fleet)
|
||||
cp ~/.fleet/preview/orbit.log orbit.log
|
||||
# Old location of orbit logs before v4.43.0
|
||||
cp ~/.fleet/preview/orbit.log orbit.log || true
|
||||
# New location of orbit logs since v4.43.0
|
||||
cp ~/.fleet/preview/orbit/orbit.log orbit.log || true
|
||||
cp -r ~/.fleet/preview/logs osquery_result_status_logs
|
||||
shell: bash
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -10,12 +9,14 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/constant"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/packaging"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/update"
|
||||
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
|
||||
@ -24,6 +25,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/service"
|
||||
"github.com/google/go-github/v37/github"
|
||||
"github.com/mitchellh/go-ps"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@ -31,18 +33,18 @@ import (
|
||||
type dockerComposeVersion int
|
||||
|
||||
const (
|
||||
downloadUrl = "https://github.com/fleetdm/osquery-in-a-box/archive/%s.zip"
|
||||
standardQueryLibraryUrl = "https://raw.githubusercontent.com/fleetdm/fleet/main/docs/01-Using-Fleet/standard-query-library/standard-query-library.yml"
|
||||
licenseKeyFlagName = "license-key"
|
||||
tagFlagName = "tag"
|
||||
previewConfigFlagName = "preview-config"
|
||||
noHostsFlagName = "no-hosts"
|
||||
orbitChannel = "orbit-channel"
|
||||
osquerydChannel = "osqueryd-channel"
|
||||
updateURL = "update-url"
|
||||
updateRootKeys = "update-roots"
|
||||
stdQueryLibFilePath = "std-query-lib-file-path"
|
||||
disableOpenBrowser = "disable-open-browser"
|
||||
standardQueryLibraryUrl = "https://raw.githubusercontent.com/fleetdm/fleet/main/docs/01-Using-Fleet/standard-query-library/standard-query-library.yml"
|
||||
licenseKeyFlagName = "license-key"
|
||||
tagFlagName = "tag"
|
||||
previewConfigFlagName = "preview-config"
|
||||
noHostsFlagName = "no-hosts"
|
||||
orbitChannel = "orbit-channel"
|
||||
osquerydChannel = "osqueryd-channel"
|
||||
updateURL = "update-url"
|
||||
updateRootKeys = "update-roots"
|
||||
stdQueryLibFilePath = "std-query-lib-file-path"
|
||||
previewConfigPathFlagName = "preview-config-path"
|
||||
disableOpenBrowser = "disable-open-browser"
|
||||
|
||||
dockerComposeV1 dockerComposeVersion = 1
|
||||
dockerComposeV2 dockerComposeVersion = 2
|
||||
@ -110,7 +112,7 @@ Use the stop and reset subcommands to manage the server and dependencies once st
|
||||
&cli.StringFlag{
|
||||
Name: previewConfigFlagName,
|
||||
Usage: "Run a specific branch of the preview repository",
|
||||
Value: "production",
|
||||
Value: "main",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: noHostsFlagName,
|
||||
@ -139,9 +141,15 @@ Use the stop and reset subcommands to manage the server and dependencies once st
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: stdQueryLibFilePath,
|
||||
Usage: "Use custom standard query library yml file",
|
||||
Usage: "Use custom standard query library yml file (used for development/testing)",
|
||||
Value: "",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: previewConfigPathFlagName,
|
||||
Usage: "Use custom local directory for the pulling configuration from fleetdm/fleet (used for development/testing)",
|
||||
Value: "",
|
||||
Hidden: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: disableOpenBrowser,
|
||||
Usage: "Disable opening the browser",
|
||||
@ -157,12 +165,32 @@ Use the stop and reset subcommands to manage the server and dependencies once st
|
||||
return err
|
||||
}
|
||||
|
||||
// Download files every time to ensure the user gets the most up to date versions
|
||||
previewDir := previewDirectory()
|
||||
osqueryBranch := c.String(previewConfigFlagName)
|
||||
fmt.Printf("Downloading dependencies from %s into %s...\n", osqueryBranch, previewDir)
|
||||
if err := downloadFiles(osqueryBranch); err != nil {
|
||||
return fmt.Errorf("downloading dependencies: %w", err)
|
||||
|
||||
if previewConfigDir := c.String(previewConfigPathFlagName); previewConfigDir != "" {
|
||||
fmt.Printf("Copying dependencies from %s...\n", previewConfigDir)
|
||||
if err := os.MkdirAll(previewDir, 0o777); err != nil {
|
||||
return fmt.Errorf("create directory %q: %w", previewDir, err)
|
||||
}
|
||||
if err := copyDirectory(previewDir, previewConfigDir); err != nil {
|
||||
return fmt.Errorf("copying directories: %w", err)
|
||||
}
|
||||
} else {
|
||||
// Download files every time to ensure the user gets the most up to date versions
|
||||
fleetBranch := c.String(previewConfigFlagName)
|
||||
fmt.Printf("Downloading dependencies from fleetdm/fleet:%s into %s...\n", fleetBranch, previewDir)
|
||||
githubHTTPClient := fleethttp.NewGithubClient()
|
||||
githubClient := github.NewClient(githubHTTPClient)
|
||||
if err := downloadFromFleetRepo(
|
||||
context.Background(),
|
||||
githubHTTPClient,
|
||||
githubClient,
|
||||
"tools/osquery/in-a-box",
|
||||
fleetBranch,
|
||||
previewDirectory(),
|
||||
); err != nil {
|
||||
return fmt.Errorf("downloading dependencies: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.Chdir(previewDir); err != nil {
|
||||
@ -172,14 +200,19 @@ Use the stop and reset subcommands to manage the server and dependencies once st
|
||||
return fmt.Errorf("docker-compose file not found in preview directory: %w", err)
|
||||
}
|
||||
|
||||
// Make sure the logs directory is writable, otherwise the Fleet
|
||||
// Make sure directories are writable, otherwise the Fleet
|
||||
// server errors on startup. This can be a problem when running on
|
||||
// Linux with a non-root user inside the container.
|
||||
if err := os.Chmod(filepath.Join(previewDir, "logs"), 0o777); err != nil {
|
||||
return fmt.Errorf("make logs writable: %w", err)
|
||||
}
|
||||
if err := os.Chmod(filepath.Join(previewDir, "vulndb"), 0o777); err != nil {
|
||||
return fmt.Errorf("make vulndb writable: %w", err)
|
||||
for _, item := range []string{
|
||||
filepath.Join(previewDir, "logs"),
|
||||
filepath.Join(previewDir, "vulndb"),
|
||||
} {
|
||||
if err := os.MkdirAll(item, 0o777); err != nil {
|
||||
return fmt.Errorf("create directory %q: %w", item, err)
|
||||
}
|
||||
if err := os.Chmod(item, 0o777); err != nil {
|
||||
return fmt.Errorf("make %s writable: %w", item, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.Setenv("FLEET_VERSION", c.String(tagFlagName)); err != nil {
|
||||
@ -348,7 +381,8 @@ Use the stop and reset subcommands to manage the server and dependencies once st
|
||||
if !c.Bool(noHostsFlagName) {
|
||||
fmt.Println("Enrolling local host...")
|
||||
|
||||
if err := downloadOrbitAndStart(previewDir, secrets.Secrets[0].Secret, address, c.String(orbitChannel), c.String(osquerydChannel), c.String(updateURL), c.String(updateRootKeys)); err != nil {
|
||||
orbitDir := filepath.Join(previewDir, "orbit")
|
||||
if err := downloadOrbitAndStart(orbitDir, secrets.Secrets[0].Secret, address, c.String(orbitChannel), c.String(osquerydChannel), c.String(updateURL), c.String(updateRootKeys)); err != nil {
|
||||
return fmt.Errorf("downloading orbit and osqueryd: %w", err)
|
||||
}
|
||||
|
||||
@ -391,6 +425,27 @@ Use the stop and reset subcommands to manage the server and dependencies once st
|
||||
}
|
||||
}
|
||||
|
||||
func copyDirectory(destDir, sourceDir string) error {
|
||||
sourceDir, err := filepath.Abs(sourceDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("absolute path could not be determined for %q: %w", sourceDir, err)
|
||||
}
|
||||
return filepath.Walk(sourceDir, func(path string, info os.FileInfo, err error) error {
|
||||
relPath := strings.Replace(path, sourceDir, "", 1)
|
||||
if relPath == "" {
|
||||
return nil
|
||||
}
|
||||
if info.IsDir() {
|
||||
return os.MkdirAll(filepath.Join(destDir, relPath), 0o777)
|
||||
}
|
||||
data, err1 := os.ReadFile(filepath.Join(sourceDir, relPath))
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
return os.WriteFile(filepath.Join(destDir, relPath), data, 0o777)
|
||||
})
|
||||
}
|
||||
|
||||
var testOverridePreviewDirectory string
|
||||
|
||||
func previewDirectory() string {
|
||||
@ -405,32 +460,63 @@ func previewDirectory() string {
|
||||
return filepath.Join(homeDir, ".fleet", "preview")
|
||||
}
|
||||
|
||||
func downloadFiles(branch string) error {
|
||||
resp, err := http.Get(fmt.Sprintf(downloadUrl, branch))
|
||||
// downloadFromFleetRepo downloads a specific directory from the fleetdm/fleet repository.
|
||||
// It creates files and folders as world writable as this is mainly used for testing.
|
||||
func downloadFromFleetRepo(
|
||||
ctx context.Context,
|
||||
client *http.Client,
|
||||
githubClient *github.Client,
|
||||
repoDirectory string,
|
||||
branch string,
|
||||
outputDirectory string,
|
||||
) error {
|
||||
if err := os.MkdirAll(outputDirectory, 0o777); err != nil {
|
||||
return fmt.Errorf("create directory %q: %w", outputDirectory, err)
|
||||
}
|
||||
|
||||
_, contents, response, err := githubClient.Repositories.GetContents(ctx,
|
||||
"fleetdm",
|
||||
"fleet",
|
||||
repoDirectory,
|
||||
&github.RepositoryContentGetOptions{
|
||||
Ref: branch,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("get contents request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("download got status %d", resp.StatusCode)
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("request failed: %s", response.Status)
|
||||
}
|
||||
|
||||
zipContents, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("read download contents: %w", err)
|
||||
for _, content := range contents {
|
||||
if content.GetType() == "file" {
|
||||
if downloadURL := content.GetDownloadURL(); downloadURL != "" {
|
||||
response, err := client.Get(downloadURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("download file: %q: %w", downloadURL, err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("download file response: %q: %s", downloadURL, response.Status)
|
||||
}
|
||||
b, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("read file body: %w", err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(outputDirectory, content.GetName()), b, 0o777); err != nil {
|
||||
return fmt.Errorf("write file: %w", err)
|
||||
}
|
||||
}
|
||||
} else if content.GetType() == "dir" {
|
||||
return downloadFromFleetRepo(ctx,
|
||||
client,
|
||||
githubClient,
|
||||
path.Join(repoDirectory, content.GetName()),
|
||||
branch,
|
||||
filepath.Join(outputDirectory, content.GetName()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
zipReader, err := zip.NewReader(bytes.NewReader(zipContents), int64(len(zipContents)))
|
||||
if err != nil {
|
||||
return fmt.Errorf("open download contents for unzip: %w", err)
|
||||
}
|
||||
// zip.NewReader does not need to be closed (and cannot be)
|
||||
|
||||
if err := unzip(zipReader, branch); err != nil {
|
||||
return fmt.Errorf("unzip download contents: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -449,59 +535,6 @@ func downloadStandardQueryLibrary() ([]byte, error) {
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// Adapted from https://stackoverflow.com/a/24792688/491710
|
||||
func unzip(r *zip.Reader, branch string) error {
|
||||
previewDir := previewDirectory()
|
||||
|
||||
// Closure to address file descriptors issue with all the deferred .Close()
|
||||
// methods
|
||||
replacePath := fmt.Sprintf("osquery-in-a-box-%s", branch)
|
||||
extractAndWriteFile := func(f *zip.File) error {
|
||||
rc, err := f.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
path := f.Name
|
||||
path = strings.Replace(path, replacePath, previewDir, 1)
|
||||
|
||||
if f.FileInfo().IsDir() {
|
||||
if err := os.MkdirAll(path, f.Mode()); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := os.MkdirAll(filepath.Dir(path), f.Mode()); err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
_, err = io.Copy(f, rc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, f := range r.File {
|
||||
// Prevent zip-slip attack.
|
||||
if strings.Contains(f.Name, "..") {
|
||||
return fmt.Errorf("invalid path in zip: %q", f.Name)
|
||||
}
|
||||
err := extractAndWriteFile(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func waitStartup() error {
|
||||
retryStrategy := backoff.NewExponentialBackOff()
|
||||
retryStrategy.MaxInterval = 1 * time.Second
|
||||
@ -612,7 +645,8 @@ func previewStopCommand() *cli.Command {
|
||||
return fmt.Errorf("Failed to run %d stop for simulated hosts", compose)
|
||||
}
|
||||
|
||||
if err := stopOrbit(previewDir); err != nil {
|
||||
orbitDir := filepath.Join(previewDir, "orbit")
|
||||
if err := stopOrbit(orbitDir); err != nil {
|
||||
return fmt.Errorf("Failed to stop orbit: %w", err)
|
||||
}
|
||||
|
||||
@ -670,14 +704,15 @@ func previewResetCommand() *cli.Command {
|
||||
return fmt.Errorf("Failed to run %s rm -sf for simulated hosts.", compose)
|
||||
}
|
||||
|
||||
if err := stopOrbit(previewDir); err != nil {
|
||||
orbitDir := filepath.Join(previewDir, "orbit")
|
||||
if err := stopOrbit(orbitDir); err != nil {
|
||||
return fmt.Errorf("Failed to stop orbit: %w", err)
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(filepath.Join(previewDir, "tuf-metadata.json")); err != nil {
|
||||
if err := os.RemoveAll(filepath.Join(orbitDir, "tuf-metadata.json")); err != nil {
|
||||
return fmt.Errorf("failed to remove preview update metadata file: %w", err)
|
||||
}
|
||||
if err := os.RemoveAll(filepath.Join(previewDir, "bin")); err != nil {
|
||||
if err := os.RemoveAll(filepath.Join(orbitDir, "bin")); err != nil {
|
||||
return fmt.Errorf("failed to remove preview bin directory: %w", err)
|
||||
}
|
||||
|
||||
@ -722,6 +757,10 @@ func processNameMatches(pid int, expectedPrefix string) (bool, error) {
|
||||
}
|
||||
|
||||
func downloadOrbitAndStart(destDir, enrollSecret, address, orbitChannel, osquerydChannel, updateURL, updateRoots string) error {
|
||||
if err := os.MkdirAll(destDir, constant.DefaultDirMode); err != nil {
|
||||
return fmt.Errorf("create orbit directory %q: %w", destDir, err)
|
||||
}
|
||||
|
||||
// Stop any current intance of orbit running, otherwise the configured enroll secret
|
||||
// won't match the generated in the preview run.
|
||||
if err := stopOrbit(destDir); err != nil {
|
||||
@ -733,7 +772,7 @@ func downloadOrbitAndStart(destDir, enrollSecret, address, orbitChannel, osquery
|
||||
if err := os.RemoveAll(filepath.Join(destDir, "osquery.db")); err != nil {
|
||||
fmt.Println("Warning: clearing osquery db dir:", err)
|
||||
}
|
||||
if err := os.RemoveAll(filepath.Join(destDir, "orbit.db")); err != nil {
|
||||
if err := os.RemoveAll(filepath.Join(destDir, "secret-orbit-node-key.txt")); err != nil {
|
||||
fmt.Println("Warning: clearing orbit db dir:", err)
|
||||
}
|
||||
if err := cleanUpSocketFiles(destDir); err != nil {
|
||||
|
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
@ -27,7 +28,9 @@ func TestPreview(t *testing.T) {
|
||||
require.NoError(t, nettest.RunWithNetRetry(t, func() error {
|
||||
var err error
|
||||
output, err = runAppNoChecks([]string{
|
||||
"preview", "--config", configPath,
|
||||
"preview",
|
||||
"--config", configPath,
|
||||
"--preview-config-path", filepath.Join(gitRootPath(t), "tools", "osquery", "in-a-box"),
|
||||
"--tag", "main",
|
||||
"--disable-open-browser",
|
||||
})
|
||||
@ -64,6 +67,12 @@ func TestPreview(t *testing.T) {
|
||||
require.True(t, ok, appConf)
|
||||
}
|
||||
|
||||
func gitRootPath(t *testing.T) string {
|
||||
path, err := exec.Command("git", "rev-parse", "--show-toplevel").Output()
|
||||
require.NoError(t, err)
|
||||
return strings.TrimSpace(string(path))
|
||||
}
|
||||
|
||||
func TestDockerCompose(t *testing.T) {
|
||||
t.Run("returns the right command according to the version", func(t *testing.T) {
|
||||
v1 := dockerCompose{dockerComposeV1}
|
||||
|
6
tools/osquery/in-a-box/README.md
Normal file
6
tools/osquery/in-a-box/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# Osquery in a box
|
||||
|
||||
The contents in this repository are used by `fleetctl preview`.
|
||||
They contain docker compose and configuration files to start a test instance of Fleet and simulated osquery hosts.
|
||||
|
||||
> IMPORTANT: By updating files in this directory on the `main` branch you are releasing the changes to all users using `fleetctl preview`.
|
114
tools/osquery/in-a-box/docker-compose.yml
Normal file
114
tools/osquery/in-a-box/docker-compose.yml
Normal file
@ -0,0 +1,114 @@
|
||||
volumes:
|
||||
data01:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
fleet-preview:
|
||||
name: fleet-preview
|
||||
|
||||
services:
|
||||
mysql01:
|
||||
image: mysql:5.7
|
||||
platform: linux/x86_64
|
||||
volumes:
|
||||
- .:/data
|
||||
command: mysqld --datadir=/tmp/data --event-scheduler=ON
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: toor
|
||||
MYSQL_DATABASE: fleet
|
||||
MYSQL_USER: fleet
|
||||
MYSQL_PASSWORD: fleet
|
||||
ports:
|
||||
- "3308:3306"
|
||||
networks:
|
||||
- fleet-preview
|
||||
|
||||
redis01:
|
||||
image: redis:6
|
||||
networks:
|
||||
- fleet-preview
|
||||
|
||||
# Normal Fleet server running TLS with a self-signed cert to handle the
|
||||
# osquery connections.
|
||||
fleet01:
|
||||
image: fleetdm/fleet:${FLEET_VERSION:-latest}
|
||||
platform: linux/x86_64
|
||||
command: sh -c "/usr/bin/fleet prepare db --no-prompt && /usr/bin/fleet serve"
|
||||
environment:
|
||||
FLEET_MYSQL_ADDRESS: mysql01:3306
|
||||
FLEET_MYSQL_DATABASE: fleet
|
||||
FLEET_MYSQL_USERNAME: fleet
|
||||
FLEET_MYSQL_PASSWORD: fleet
|
||||
FLEET_REDIS_ADDRESS: redis01:6379
|
||||
FLEET_SERVER_ADDRESS: 0.0.0.0:8412
|
||||
FLEET_SERVER_CERT: /fleet/osquery/fleet.crt
|
||||
FLEET_SERVER_KEY: /fleet/osquery/fleet.key
|
||||
FLEET_LOGGING_JSON: 'true'
|
||||
FLEET_OSQUERY_STATUS_LOG_PLUGIN: filesystem
|
||||
FLEET_FILESYSTEM_STATUS_LOG_FILE: /logs/osqueryd.status.log
|
||||
FLEET_OSQUERY_RESULT_LOG_PLUGIN: filesystem
|
||||
FLEET_FILESYSTEM_RESULT_LOG_FILE: /logs/osqueryd.results.log
|
||||
FLEET_BETA_SOFTWARE_INVENTORY: 1
|
||||
FLEET_LICENSE_KEY: ${FLEET_LICENSE_KEY}
|
||||
FLEET_OSQUERY_LABEL_UPDATE_INTERVAL: 1m
|
||||
FLEET_VULNERABILITIES_CURRENT_INSTANCE_CHECKS: "yes"
|
||||
FLEET_VULNERABILITIES_DATABASES_PATH: /vulndb
|
||||
FLEET_VULNERABILITIES_PERIODICITY: 5m
|
||||
FLEET_LOGGING_DEBUG: 'true'
|
||||
# This can be configured for testing purposes but otherwise uses the
|
||||
# typical default of provided.
|
||||
FLEET_OSQUERY_HOST_IDENTIFIER: ${FLEET_OSQUERY_HOST_IDENTIFIER:-provided}
|
||||
depends_on:
|
||||
- mysql01
|
||||
- redis01
|
||||
volumes:
|
||||
- .:/fleet/
|
||||
- ./logs:/logs
|
||||
- ./vulndb:/vulndb
|
||||
ports:
|
||||
- "8412:8412"
|
||||
networks:
|
||||
fleet-preview:
|
||||
aliases:
|
||||
# Kind of a funny hack, this allows host.docker.internal to point
|
||||
# to the Fleet server on Linux hosts where host.docker.internal is not
|
||||
# yet added as a host by default in Docker.
|
||||
- host.docker.internal
|
||||
# Another strange hack, this allows the UI Fleet server to see
|
||||
# this server as though it were on localhost, thereby allowing it to
|
||||
# download the TLS certificate.
|
||||
- localhost
|
||||
|
||||
# Run another Fleet server listening over plain HTTP bound to port 1337.
|
||||
# This is expected to receive UI requests only and not connections from
|
||||
# agents.
|
||||
fleet02:
|
||||
image: fleetdm/fleet:${FLEET_VERSION:-latest}
|
||||
platform: linux/x86_64
|
||||
command: sh -c "/usr/bin/fleet prepare db --no-prompt && /usr/bin/fleet serve"
|
||||
environment:
|
||||
FLEET_MYSQL_ADDRESS: mysql01:3306
|
||||
FLEET_MYSQL_DATABASE: fleet
|
||||
FLEET_MYSQL_USERNAME: fleet
|
||||
FLEET_MYSQL_PASSWORD: fleet
|
||||
FLEET_REDIS_ADDRESS: redis01:6379
|
||||
FLEET_SERVER_ADDRESS: 0.0.0.0:1337
|
||||
FLEET_SERVER_TLS: 'false'
|
||||
FLEET_LOGGING_JSON: 'true'
|
||||
FLEET_SESSION_DURATION: 720h
|
||||
FLEET_OSQUERY_STATUS_LOG_PLUGIN: stdout
|
||||
FLEET_OSQUERY_RESULT_LOG_PLUGIN: stdout
|
||||
FLEET_BETA_SOFTWARE_INVENTORY: 1
|
||||
FLEET_LICENSE_KEY: ${FLEET_LICENSE_KEY}
|
||||
FLEET_OSQUERY_LABEL_UPDATE_INTERVAL: 1m
|
||||
FLEET_VULNERABILITIES_CURRENT_INSTANCE_CHECKS: "no"
|
||||
# This can be configured for testing purposes but otherwise uses the
|
||||
# typical default of provided.
|
||||
FLEET_OSQUERY_HOST_IDENTIFIER: ${FLEET_OSQUERY_HOST_IDENTIFIER:-provided}
|
||||
depends_on:
|
||||
- mysql01
|
||||
- redis01
|
||||
ports:
|
||||
- "1337:1337"
|
||||
networks:
|
||||
- fleet-preview
|
1
tools/osquery/in-a-box/osquery/.env
Normal file
1
tools/osquery/in-a-box/osquery/.env
Normal file
@ -0,0 +1 @@
|
||||
COMPOSE_PROJECT_NAME=fleet-preview-devices
|
127
tools/osquery/in-a-box/osquery/docker-compose.yml
Normal file
127
tools/osquery/in-a-box/osquery/docker-compose.yml
Normal file
@ -0,0 +1,127 @@
|
||||
version: '3.7'
|
||||
|
||||
networks:
|
||||
fleet-preview:
|
||||
name: fleet-preview
|
||||
external: true
|
||||
|
||||
services:
|
||||
ubuntu22-osquery:
|
||||
image: "osquery/osquery:5.8.2-ubuntu22.04"
|
||||
volumes:
|
||||
- ./fleet.crt:/etc/osquery/fleet.crt
|
||||
- ./example_osquery.flags:/etc/osquery/osquery.flags
|
||||
environment:
|
||||
ENROLL_SECRET: "${ENROLL_SECRET:?ENROLL_SECRET must be set for server authentication}"
|
||||
command: osqueryd --flagfile=/etc/osquery/osquery.flags --tls_hostname=${FLEET_SERVER-host.docker.internal:8412}
|
||||
ulimits:
|
||||
core:
|
||||
hard: 1000000000
|
||||
soft: 1000000000
|
||||
networks:
|
||||
- fleet-preview
|
||||
|
||||
ubuntu20-osquery:
|
||||
image: "osquery/osquery:5.8.2-ubuntu20.04"
|
||||
volumes:
|
||||
- ./fleet.crt:/etc/osquery/fleet.crt
|
||||
- ./example_osquery.flags:/etc/osquery/osquery.flags
|
||||
environment:
|
||||
ENROLL_SECRET: "${ENROLL_SECRET:?ENROLL_SECRET must be set for server authentication}"
|
||||
command: osqueryd --flagfile=/etc/osquery/osquery.flags --tls_hostname=${FLEET_SERVER-host.docker.internal:8412}
|
||||
ulimits:
|
||||
core:
|
||||
hard: 1000000000
|
||||
soft: 1000000000
|
||||
networks:
|
||||
- fleet-preview
|
||||
|
||||
ubuntu18-osquery:
|
||||
image: "osquery/osquery:5.8.2-ubuntu18.04"
|
||||
volumes:
|
||||
- ./fleet.crt:/etc/osquery/fleet.crt
|
||||
- ./example_osquery.flags:/etc/osquery/osquery.flags
|
||||
environment:
|
||||
ENROLL_SECRET: "${ENROLL_SECRET:?ENROLL_SECRET must be set for server authentication}"
|
||||
command: osqueryd --flagfile=/etc/osquery/osquery.flags --tls_hostname=${FLEET_SERVER-host.docker.internal:8412}
|
||||
ulimits:
|
||||
core:
|
||||
hard: 1000000000
|
||||
soft: 1000000000
|
||||
networks:
|
||||
- fleet-preview
|
||||
|
||||
ubuntu16-osquery:
|
||||
image: "osquery/osquery:5.8.2-ubuntu16.04"
|
||||
volumes:
|
||||
- ./fleet.crt:/etc/osquery/fleet.crt
|
||||
- ./example_osquery.flags:/etc/osquery/osquery.flags
|
||||
environment:
|
||||
ENROLL_SECRET: "${ENROLL_SECRET:?ENROLL_SECRET must be set for server authentication}"
|
||||
command: osqueryd --flagfile=/etc/osquery/osquery.flags --tls_hostname=${FLEET_SERVER-host.docker.internal:8412}
|
||||
ulimits:
|
||||
core:
|
||||
hard: 1000000000
|
||||
soft: 1000000000
|
||||
networks:
|
||||
- fleet-preview
|
||||
|
||||
ubuntu14-osquery:
|
||||
image: "osquery/osquery:4.6.0-ubuntu14.04"
|
||||
volumes:
|
||||
- ./fleet.crt:/etc/osquery/fleet.crt
|
||||
- ./example_osquery.flags:/etc/osquery/osquery.flags
|
||||
environment:
|
||||
ENROLL_SECRET: "${ENROLL_SECRET:?ENROLL_SECRET must be set for server authentication}"
|
||||
command: osqueryd --flagfile=/etc/osquery/osquery.flags --tls_hostname=${FLEET_SERVER-host.docker.internal:8412}
|
||||
ulimits:
|
||||
core:
|
||||
hard: 1000000000
|
||||
soft: 1000000000
|
||||
networks:
|
||||
- fleet-preview
|
||||
|
||||
centos8-osquery:
|
||||
image: "osquery/osquery:5.8.2-centos8"
|
||||
volumes:
|
||||
- ./fleet.crt:/etc/osquery/fleet.crt
|
||||
- ./example_osquery.flags:/etc/osquery/osquery.flags
|
||||
environment:
|
||||
ENROLL_SECRET: "${ENROLL_SECRET:?ENROLL_SECRET must be set for server authentication}"
|
||||
command: osqueryd --flagfile=/etc/osquery/osquery.flags --tls_hostname=${FLEET_SERVER-host.docker.internal:8412}
|
||||
ulimits:
|
||||
core:
|
||||
hard: 1000000000
|
||||
soft: 1000000000
|
||||
networks:
|
||||
- fleet-preview
|
||||
|
||||
centos7-osquery:
|
||||
image: "osquery/osquery:5.8.2-centos7"
|
||||
volumes:
|
||||
- ./fleet.crt:/etc/osquery/fleet.crt
|
||||
- ./example_osquery.flags:/etc/osquery/osquery.flags
|
||||
environment:
|
||||
ENROLL_SECRET: "${ENROLL_SECRET:?ENROLL_SECRET must be set for server authentication}"
|
||||
command: osqueryd --flagfile=/etc/osquery/osquery.flags --tls_hostname=${FLEET_SERVER-host.docker.internal:8412}
|
||||
ulimits:
|
||||
core:
|
||||
hard: 1000000000
|
||||
soft: 1000000000
|
||||
networks:
|
||||
- fleet-preview
|
||||
|
||||
centos6-osquery:
|
||||
image: "osquery/osquery:5.8.2-centos6"
|
||||
volumes:
|
||||
- ./fleet.crt:/etc/osquery/fleet.crt
|
||||
- ./example_osquery.flags:/etc/osquery/osquery.flags
|
||||
environment:
|
||||
ENROLL_SECRET: "${ENROLL_SECRET:?ENROLL_SECRET must be set for server authentication}"
|
||||
command: osqueryd --flagfile=/etc/osquery/osquery.flags --tls_hostname=${FLEET_SERVER-host.docker.internal:8412}
|
||||
ulimits:
|
||||
core:
|
||||
hard: 1000000000
|
||||
soft: 1000000000
|
||||
networks:
|
||||
- fleet-preview
|
28
tools/osquery/in-a-box/osquery/example_osquery.flags
Normal file
28
tools/osquery/in-a-box/osquery/example_osquery.flags
Normal file
@ -0,0 +1,28 @@
|
||||
--force=true
|
||||
--host_identifier=hostname
|
||||
--verbose=true
|
||||
--debug
|
||||
|
||||
--tls_server_certs=/etc/osquery/fleet.crt
|
||||
|
||||
--enroll_secret_env=ENROLL_SECRET
|
||||
--enroll_tls_endpoint=/api/v1/osquery/enroll
|
||||
|
||||
--config_plugin=tls
|
||||
--config_tls_endpoint=/api/v1/osquery/config
|
||||
--config_refresh=10
|
||||
|
||||
--disable_distributed=false
|
||||
--distributed_plugin=tls
|
||||
--distributed_interval=10
|
||||
--distributed_tls_max_attempts=3
|
||||
--distributed_tls_read_endpoint=/api/v1/osquery/distributed/read
|
||||
--distributed_tls_write_endpoint=/api/v1/osquery/distributed/write
|
||||
|
||||
--logger_plugin=tls
|
||||
--logger_tls_endpoint=/api/v1/osquery/log
|
||||
--logger_tls_period=10
|
||||
|
||||
--disable_carver=false
|
||||
--carver_start_endpoint=/api/v1/osquery/carve/begin
|
||||
--carver_continue_endpoint=/api/v1/osquery/carve/block
|
29
tools/osquery/in-a-box/osquery/fleet.crt
Normal file
29
tools/osquery/in-a-box/osquery/fleet.crt
Normal file
@ -0,0 +1,29 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE5jCCAs6gAwIBAgIJAKq0+FAVArUhMA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV
|
||||
BAMMCkZsZWV0IFRlc3QwHhcNMjAxMDE1MTg1ODE5WhcNMzAwNzE1MTg1ODE5WjAV
|
||||
MRMwEQYDVQQDDApGbGVldCBUZXN0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
|
||||
CgKCAgEAttQ62lpMq48/XjQFxYg47D2fgKgTBMjDNSfCt9VpqE3xPnybmWo8VZtk
|
||||
jmrFM50IhagyYSjvl9iqdrnsl3ZV8KYbWEy6849zDYF1SudmC7/pJyH7QvpKgL7V
|
||||
4McM62jM905hyFy9KZTAlFiaeezWSWJre7kHsK2u5tsqS6ElatEZmF59sInixaRw
|
||||
RqVxOhtDm7Sl1c5xKWM6phWoJfykspFpu5J6N2jRQXCfzBYoQWN76OohGouit/BQ
|
||||
C1xvm+f7wgGZgbbfDjUoHAe9Yhd3XzZsYTgMDt/SRJRDnxFZwo8BAkY9yJm7f3dQ
|
||||
AEhgJ66KbyoxITdgma1hgmeWibZY4hVymcRxB1B3RNN2at19RNy2J+brMxlG0KZk
|
||||
nD77EqidrwLAlYcdeU3yLjt0vYPxT+RW7l1jiZlVi/oaykAmVfOhWnTnTwbsYs7O
|
||||
UMyMyYHQECEs98ex7wrjThIBJScqhsSN1ipAxr5RgaDr+U5IR+tLhMewBy8So+nf
|
||||
2YuMhLfkCgoY80ELhz5F8avts5hksB0hqnNYr+Nlwm6eXqEPZSzFJmdc1IbmWzq2
|
||||
7UH1OQmBFF2qr2j/8dcM+oPNgjrEEQjtyW0S4j2PhjSEbINgcwu0AaABssLI80Vm
|
||||
Gp1TjUGA92rMwIjlAtcUUB5FOKSS8vAXb1VcDWMkybh9sHj4Z0ECAwEAAaM5MDcw
|
||||
NQYDVR0RBC4wLIIJbG9jYWxob3N0ghRob3N0LmRvY2tlci5pbnRlcm5hbIIJMTI3
|
||||
LjAuMC4xMA0GCSqGSIb3DQEBCwUAA4ICAQBZOY++LNRTVG8XlQGVlOloEKA2WY3P
|
||||
gXKJLSM7xWSxj2co0v+noyhoInHT7ysub8en59Et+vN53/0OobxNIdEKDUdqs38R
|
||||
F++Oy6s/MhFHSo87F06t+W91/60ub4iFRHfev1qeNFV6Yzv9sFJ5LpXLFk+qVDb8
|
||||
pPyFFE1bXjctDPjD5gUj+Y34XikVKzMb7xddWCNs34v1KCaCBW7kkfefxiZiDR6g
|
||||
lCEkDzp6xaLS898oCbfFakjr4bvOgBP1IqXLIDLPMhivaxNAooHTtu/3ezp7puix
|
||||
TSDkjlkStDtEFw/wjyaMcEkk51Gs1ponBbADLRxQ50AHDWk/4vy8GcIVc6CdVEOA
|
||||
Zw12FN06C4Jviiiv6uCXZ6iZ+V+pjGiGmSNYF+kruUs8BfrJIB89lqxpdQ4Kx01j
|
||||
AuSFvjRRvIPmvApSdKEjLcY3AYRivXsB/hASMBbjh/p1f/JzSJdxoqSvONhNQJuh
|
||||
+wcdNVQhGAv3kkLn/HMHTBl2Ur+9tQaJrnR1tWl1IzwLRJIi0Soyp/q5ZjQyFglj
|
||||
32xW83DZhtpQ2SI1QGy4AvWIPnGHZhMfav02KnKRhZdOMW4oekXRMrwiyXCqIazc
|
||||
xXzAlCq8dHdP2Y9uvfFxVFyE+uSfkcPxX+DG/ZnpgCS27oKA/qLCybJamlqtveNs
|
||||
RSjNe5qwGi0ifA==
|
||||
-----END CERTIFICATE-----
|
52
tools/osquery/in-a-box/osquery/fleet.key
Normal file
52
tools/osquery/in-a-box/osquery/fleet.key
Normal file
@ -0,0 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
mWZen+G8ANnds10V7TmcpoaPSSoJMF0=
|
||||
-----END PRIVATE KEY-----
|
Loading…
Reference in New Issue
Block a user