Skip to content

Commit

Permalink
Merge branch 'main' into 8488-new-tuf-repository
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasmrod committed Jan 7, 2025
2 parents 135ed5d + d079b63 commit 9a5bfe0
Show file tree
Hide file tree
Showing 112 changed files with 1,573 additions and 358 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/dogfood-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
workflow_dispatch:
inputs:
DOCKER_IMAGE:
description: 'The full name of the docker image to be deployed. (e.g. fleetdm/fleet:v4.30.0). Note: do not use fleetdm/fleet:main directly. Use the short hash instead. If pull-rate limited, try using the quay.io/fleetdm/fleet mirror.'
description: "The full name of the docker image to be deployed. (e.g. fleetdm/fleet:v4.30.0). Note: do not use fleetdm/fleet:main directly. Use the short hash instead. If pull-rate limited, try using the quay.io/fleetdm/fleet mirror."
required: true

# This allows a subsequently queued workflow run to interrupt previous runs
Expand All @@ -26,7 +26,8 @@ env:
TF_WORKSPACE: fleet
TF_VAR_fleet_image: ${{ github.event.inputs.DOCKER_IMAGE || 'fleetdm/fleet:main' }}
TF_VAR_fleet_license: ${{ secrets.DOGFOOD_LICENSE_KEY }}
TF_VAR_slack_webhook: ${{ secrets.SLACK_G_HELP_P1_WEBHOOK_URL }}
TF_VAR_slack_p1_webhook: ${{ secrets.SLACK_G_HELP_P1_WEBHOOK_URL }}
TF_VAR_slack_p2_webhook: ${{ secrets.SLACK_G_HELP_P2_WEBHOOK_URL }}
TF_VAR_fleet_sentry_dsn: ${{ secrets.DOGFOOD_SENTRY_DSN }}
TF_VAR_elastic_url: ${{ secrets.ELASTIC_APM_SERVER_URL }}
TF_VAR_elastic_token: ${{ secrets.ELASTIC_APM_SECRET_TOKEN }}
Expand Down Expand Up @@ -64,7 +65,7 @@ jobs:

- uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 # v2.0.3
with:
terraform_version: 1.6.3
terraform_version: 1.10.2
terraform_wrapper: false
- name: Terraform Init
id: init
Expand Down
6 changes: 3 additions & 3 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ go.mod @fleetdm/go
#
# (see website/config/custom.js for DRIs of other paths not listed here)
##############################################################################################
/docs @eashaw
/docs/REST\ API/rest-api.md @iansltx # « REST API reference documentation
/docs/Contributing/API-for-contributors.md @iansltx # « Advanced / contributors-only API reference documentation
/docs @rachaelshaw
/docs/REST\ API/rest-api.md @rachaelshaw # « REST API reference documentation
/docs/Contributing/API-for-contributors.md @rachaelshaw # « Advanced / contributors-only API reference documentation
/schema @eashaw # « Data tables (osquery/fleetd schema) documentation
/render.yaml @edwardsb

Expand Down
4 changes: 3 additions & 1 deletion articles/enforce-os-updates.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ OS version enforcement options are declared within the [controls](https://fleetd

### macOS

When a minimum version is enforced, end users see a native macOS notification (DDM) once per day. Users can choose to update ahead of the deadline or schedule it for that night. 24 hours before the deadline, the notification appears hourly and ignores Do Not Disturb. One hour before the deadline, the notification appears every 30 minutes and then every 10 minutes.
When a minimum version is enforced, end users see a native macOS notification (DDM) once per day. Users can choose to update ahead of the deadline or schedule it for that night. 24 hours before the deadline, the notification appears hourly and ignores Do Not Disturb. One hour before the deadline, the notification appears every 30 minutes and then every 10 minutes.

> Certain user preferences may suppress macOS update notifications. To prevent users from being surprised by a forced update or unexpected restart, consider communicating OS update deadlines through additional channels.
If the host was turned off when the deadline passed, the update will be scheduled an hour after it’s turned on.

Expand Down
4 changes: 2 additions & 2 deletions articles/role-based-access.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ GitOps is an API-only and write-only role that can be used on CI/CD pipelines.
## User permissions

| **Action** | Observer | Observer+* | Maintainer | Admin | GitOps* |
| ------------------------------------------------------------------------------------------------------------------------------------------ | -------- | ---------- | ---------- | ----- | ------- |
| ------------------------------------------------------------------------------------------------------------------------------------------ | :------: | :--------: | :--------: | :---: | :-----: |
| View all [activity](https://fleetdm.com/docs/using-fleet/rest-api#activities) ||||| |
| Manage [activity automations](https://fleetdm.com/docs/using-fleet/audit-logs) | | | |||
| View all hosts ||||| |
Expand Down Expand Up @@ -123,7 +123,7 @@ Users can be assigned to multiple teams in Fleet.
Users with access to multiple teams can be assigned different roles for each team. For example, a user can be given access to the "Workstations" team and assigned the "Observer" role. This same user can be given access to the "Servers" team and assigned the "Maintainer" role.

| **Action** | Team observer | Team observer+ | Team maintainer | Team admin | Team GitOps |
| -------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------------- | --------------- | ---------- | ----------- |
| -------------------------------------------------------------------------------------------------------------------------------- | :-----------: | :------------: | :-------------: | :--------: | :---------: |
| View hosts ||||| |
| View a host by identifier ||||||
| Filter hosts using [labels](https://fleetdm.com/docs/using-fleet/rest-api#labels) ||||| |
Expand Down
2 changes: 2 additions & 0 deletions changes/23512-clarify-expected-behavior-of-host-counts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Clarify expected behavior of policy host counts, dashboard controls software count, and controls
os updates versions count.
4 changes: 4 additions & 0 deletions changes/23823-cloudfront-cdn
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Allow delivery of bootstrap packages and software installers using signed URLs from CloudFront CDN. To enable, configure server settings:
- s3_software_installers_cloudfront_url
- s3_software_installers_cloudfront_url_signing_public_key_id
- s3_software_installers_cloudfront_url_signing_private_key
1 change: 1 addition & 0 deletions changes/24366-success-email-message
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Improve readability of success message on email update by never including the sender address.
2 changes: 2 additions & 0 deletions changes/24653-live-query-from-edit-affects-performance-stats
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- When running a live query from the edit query form, consider the results of the run in calculating
an existing query's performance impact if the user didn't change the query from the stored version.
1 change: 1 addition & 0 deletions changes/24795-host-count
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Fleet UI: Added timestamp for software, OS, and vulnerability detail pages for host count last update time
1 change: 1 addition & 0 deletions changes/24804-deleted-profiles
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed issue where deleted Apple config profiles were installing on devices because devices were offline when the profile was added.
1 change: 1 addition & 0 deletions changes/25004-fleetctl-packge-cli-instructions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Display command line installation instructions when a package is generated
1 change: 1 addition & 0 deletions changes/25144-uninstall-after-mdm-action
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Fixed reporting of software uninstall results after a host has been locked/unlocked
37 changes: 19 additions & 18 deletions cmd/fleet/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,24 +104,25 @@ func applyDevFlags(cfg *config.FleetConfig) {
cfg.Prometheus.BasicAuth.Password = "insecure"
}

cfg.S3 = config.S3Config{
CarvesBucket: "carves-dev",
CarvesRegion: "minio",
CarvesPrefix: "dev-prefix",
CarvesEndpointURL: "localhost:9000",
CarvesAccessKeyID: "minio",
CarvesSecretAccessKey: "minio123!",
CarvesDisableSSL: true,
CarvesForceS3PathStyle: true,

SoftwareInstallersBucket: "software-installers-dev",
SoftwareInstallersRegion: "minio",
SoftwareInstallersPrefix: "dev-prefix",
SoftwareInstallersEndpointURL: "localhost:9000",
SoftwareInstallersAccessKeyID: "minio",
SoftwareInstallersSecretAccessKey: "minio123!",
SoftwareInstallersDisableSSL: true,
SoftwareInstallersForceS3PathStyle: true,
cfg.S3.CarvesBucket = "carves-dev"
cfg.S3.CarvesRegion = "minio"
cfg.S3.CarvesPrefix = "dev-prefix"
cfg.S3.CarvesEndpointURL = "localhost:9000"
cfg.S3.CarvesAccessKeyID = "minio"
cfg.S3.CarvesSecretAccessKey = "minio123!"
cfg.S3.CarvesDisableSSL = true
cfg.S3.CarvesForceS3PathStyle = true

// Allow the software installers bucket to be overridden in dev mode
if cfg.S3.SoftwareInstallersBucket == "" {
cfg.S3.SoftwareInstallersBucket = "software-installers-dev"
cfg.S3.SoftwareInstallersRegion = "minio"
cfg.S3.SoftwareInstallersPrefix = "dev-prefix"
cfg.S3.SoftwareInstallersEndpointURL = "localhost:9000"
cfg.S3.SoftwareInstallersAccessKeyID = "minio"
cfg.S3.SoftwareInstallersSecretAccessKey = "minio123!"
cfg.S3.SoftwareInstallersDisableSSL = true
cfg.S3.SoftwareInstallersForceS3PathStyle = true
}

cfg.Packaging.S3 = config.S3Config{
Expand Down
2 changes: 2 additions & 0 deletions cmd/fleet/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,8 @@ the way that the Fleet server works.
}
bootstrapPackageStore = bstore
level.Info(logger).Log("msg", "using S3 bootstrap package store", "bucket", config.S3.SoftwareInstallersBucket)

config.S3.ValidateCloudfrontURL(initFatal)
} else {
installerDir := os.TempDir()
if dir := os.Getenv("FLEET_SOFTWARE_INSTALLER_STORE_DIR"); dir != "" {
Expand Down
22 changes: 20 additions & 2 deletions cmd/fleetctl/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,13 +378,31 @@ func packageCommand() *cli.Command {
}

path, _ = filepath.Abs(path)
pathBase := filepath.Base(path)
var installInstructions = "double-click the installer"
var deviceType string
switch c.String("type") {
case "pkg":
installInstructions += fmt.Sprintf(" or run the command `sudo installer -pkg \"%s\" -target /`", pathBase)
deviceType = "macOS"
case "deb":
installInstructions += fmt.Sprintf(" or run the command `sudo apt install \"%s\"`", pathBase)
deviceType = "Debian-based Linux"
case "rpm":
installInstructions += fmt.Sprintf(" or run the command `sudo dnf install \"%s\"`", pathBase)
deviceType = "RPM-based Linux"
case "msi":
installInstructions += fmt.Sprintf(" or run the command `msiexec /i \"%s\"` as administrator", pathBase)
deviceType = "Windows"
}

fmt.Printf(`
Success! You generated fleetd at %s
To add this device to Fleet, double-click to install fleetd.
To add a new %s device to Fleet, %s.
To add other devices to Fleet, distribute fleetd using Chef, Ansible, Jamf, or Puppet. Learn how: https://fleetdm.com/learn-more-about/enrolling-hosts
`, path)
`, path, deviceType, installInstructions)
if !disableOpenFolder {
open.Start(filepath.Dir(path)) //nolint:errcheck
}
Expand Down
34 changes: 33 additions & 1 deletion ee/server/service/software_installers.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,10 +438,41 @@ func (svc *Service) UpdateSoftwareInstaller(ctx context.Context, payload *fleet.
payload.SelfService = &existingInstaller.SelfService
}

// Get the hosts that are NOT in label scope currently (before the update happens)
var hostsNotInScope map[uint]struct{}
if dirty["Labels"] {
hostsNotInScope, err = svc.ds.GetExcludedHostIDMapForSoftwareInstaller(ctx, payload.InstallerID)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "getting hosts not in scope for installer")
}
}

if err := svc.ds.SaveInstallerUpdates(ctx, payload); err != nil {
return nil, ctxerr.Wrap(ctx, err, "saving installer updates")
}

if dirty["Labels"] {
// Get the hosts that are now IN label scope (after the update)
hostsInScope, err := svc.ds.GetIncludedHostIDMapForSoftwareInstaller(ctx, payload.InstallerID)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "getting hosts in scope for installer")
}

var hostsToClear []uint
for id := range hostsInScope {
if _, ok := hostsNotInScope[id]; ok {
// it was not in scope but now it is, so we should clear policy status
hostsToClear = append(hostsToClear, id)
}
}

// We clear the policy status here because otherwise the policy automation machinery
// won't pick this up and the software won't install.
if err := svc.ds.ClearAutoInstallPolicyStatusForHosts(ctx, payload.InstallerID, hostsToClear); err != nil {
return nil, ctxerr.Wrap(ctx, err, "failed to clear auto install policy status for host")
}
}

// if we're updating anything other than self-service, we cancel pending installs/uninstalls,
// and if we're updating the package we reset counts. This is run in its own transaction internally
// for consistency, but independent of the installer update query as the main update should stick
Expand Down Expand Up @@ -484,7 +515,8 @@ func (svc *Service) UpdateSoftwareInstaller(ctx context.Context, payload *fleet.
}

func (svc *Service) validateEmbeddedSecretsOnScript(ctx context.Context, scriptName string, script *string,
argErr *fleet.InvalidArgumentError) *fleet.InvalidArgumentError {
argErr *fleet.InvalidArgumentError,
) *fleet.InvalidArgumentError {
if script != nil {
if errScript := svc.ds.ValidateEmbeddedSecrets(ctx, []string{*script}); errScript != nil {
if argErr != nil {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Meta, StoryObj } from "@storybook/react";

import LastUpdatedHostCount from "./LastUpdatedHostCount";

const meta: Meta<typeof LastUpdatedHostCount> = {
title: "Components/LastUpdatedHostCount",
component: LastUpdatedHostCount,
args: {
hostCount: 40,
},
};

export default meta;

type Story = StoryObj<typeof LastUpdatedHostCount>;

export const Basic: Story = {};

export const WithLastUpdatedAt: Story = {
args: {
lastUpdatedAt: "2021-01-01T00:00:00Z",
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from "react";
import { fireEvent, render, screen } from "@testing-library/react";

import LastUpdatedHostCount from ".";

describe("Last updated host count", () => {
it("renders host count and updated text", () => {
const currentDate = new Date();
currentDate.setDate(currentDate.getDate() - 2);
const twoDaysAgo = currentDate.toISOString();

render(<LastUpdatedHostCount hostCount={40} lastUpdatedAt={twoDaysAgo} />);

const hostCount = screen.getByText(/40/i);
const updateText = screen.getByText("Updated 2 days ago");

expect(hostCount).toBeInTheDocument();
expect(updateText).toBeInTheDocument();
});
it("renders never if missing timestamp", () => {
render(<LastUpdatedHostCount />);

const text = screen.getByText("Updated never");

expect(text).toBeInTheDocument();
});

it("renders tooltip on hover", async () => {
render(<LastUpdatedHostCount hostCount={0} />);

await fireEvent.mouseEnter(screen.getByText("Updated never"));

expect(
screen.getByText(/last time host data was updated/i)
).toBeInTheDocument();
});
});
34 changes: 34 additions & 0 deletions frontend/components/LastUpdatedHostCount/LastUpdatedHostCount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from "react";
import LastUpdatedText from "components/LastUpdatedText";

const baseClass = "last-updated-host-count";

interface ILastUpdatedHostCount {
hostCount?: string | number;
lastUpdatedAt?: string;
}

const LastUpdatedHostCount = ({
hostCount,
lastUpdatedAt,
}: ILastUpdatedHostCount): JSX.Element => {
const tooltipContent = (
<>
The last time host data was updated. <br />
Click <b>View all hosts</b> to see the most
<br /> up-to-date host count.
</>
);

return (
<div className={baseClass}>
<>{hostCount}</>
<LastUpdatedText
lastUpdatedAt={lastUpdatedAt}
customTooltipText={tooltipContent}
/>
</div>
);
};

export default LastUpdatedHostCount;
6 changes: 6 additions & 0 deletions frontend/components/LastUpdatedHostCount/_styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.last-updated-host-count {
display: flex;
align-items: baseline;
gap: $pad-small;
font-size: $x-small;
}
1 change: 1 addition & 0 deletions frontend/components/LastUpdatedHostCount/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./LastUpdatedHostCount";
1 change: 1 addition & 0 deletions frontend/components/LastUpdatedText/_styles.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.component__last-updated-text {
font-size: $xx-small;
font-weight: $regular;
color: $ui-fleet-black-75;

.tooltip {
Expand Down
Loading

0 comments on commit 9a5bfe0

Please sign in to comment.