Skip to content

Commit

Permalink
Merge branch 'main' into allenhouchins-personally-owned-iphones
Browse files Browse the repository at this point in the history
  • Loading branch information
allenhouchins authored Dec 20, 2024
2 parents c711167 + ccb44a3 commit 0a41c1a
Show file tree
Hide file tree
Showing 13 changed files with 482 additions and 158 deletions.
103 changes: 103 additions & 0 deletions articles/deploying-cloudflare-warp-with-fleet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Deploying Cloudflare WARP with Fleet

Cloudflare WARP is a secure VPN-like service that encrypts internet traffic and routes it through Cloudflare's network, improving privacy and security without compromising speed.

## MacOS

1. Create custom MDM Config
a. Download the example `.mobileconfig` file
b. Tailor the payload with the [desired parameters](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/deployment/mdm-deployment/parameters/) to satisfy your deployment

2. Upload `.mobileconfig` to Fleet
a. In the Fleet admin console, navigate to **Controls**
b. Select the **Team** that requires Cloudflare WARP
c. Select **OS settings** > **Custom settings**
d. Select **Add profile** and upload the `.mobileconfig` from step 1
e. Select the hosts which require Cloudflare WARP:
- **All hosts:** Deploys WARP to all hosts in selected Team
- **Custom:** Deploys WARP to a subset of the hosts in the Team using [labels](https://fleetdm.com/guides/managing-labels-in-fleet)

> Note that the payload will be installed on all targeted hosts, but the WARP agent is not yet installed. Proceed to step 3 to complete the process.
3. Install WARP on hosts
a. In the Fleet admin console, navigate to **Software**
b. Select the **Team** that requires Cloudflare WARP
c. Select **Add software**
- Either add Cloudflare WARP from the **Fleet-maintained** library or
- Upload a custom `.pkg` obtained from [Cloudflare.](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/download-warp/#macos) If deploying with this approach, WARP will still need to be installed on select hosts via the UI, API or GitOps. Learn more about deploying software from this [article.](https://fleetdm.com/guides/deploy-software-packages)

> If using Fleet-maintained app, you can choose to install on hosts automatically or manually. To allow users to install WARP from Fleet Desktop, check the box for Self-service.
## Windows

1. Download the WARP installer for Windows
a. Visit the [Download](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/download-warp/#windows) page to review system requirements and download the installer for your OS.

2. Upload WARP installer to Fleet
a. In the Fleet admin console, navigate to **Software**
b. Select the **Team** that requires Cloudflare WARP
c. Select **Add software** > **Custom Package** and upload the `.msi` file downloaded from step 1
- To allow users to install WARP from Fleet Desktop, select Self-service. (Optional)
d. Select **Advanced options**
e. In **Install script**, replace the default script:

```
$logFile = "${env:TEMP}/fleet-install-software.log"
try {
$installProcess = Start-Process msiexec.exe `
-ArgumentList "/quiet /norestart ORGANIZATION=your-team-name SUPPORT_URL=https://example.com /lv ${logFile} /i `"${env:INSTALLER_PATH}`"" `
-PassThru -Verb RunAs -Wait
Get-Content $logFile -Tail 500
Exit $installProcess.ExitCode
} catch {
Write-Host "Error: $_"
Exit 1
}
```

> Refer to Cloudflare's [deployment parameters](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/deployment/mdm-deployment/parameters/) for a description of each argument and adjust your script as needed.
4. Install WARP on hosts
a. In the Fleet admin console, navigate to **Hosts**
b. Select the host that requires the WARP client
c. Go to **Software** and search for **Cloudflare WARP**
d. Select **Actions** > **Install**

> Learn more about ways to deploy software via the UI, API or GitOps from this [article.](https://fleetdm.com/guides/deploy-software-packages)
## Linux

Fleet allows admins to execute custom scripts on Linux hosts. The following example script creates an [MDM file](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/deployment/mdm-deployment/#linux) and installs WARP on an Ubuntu host:

```
#!/bin/sh
# Write the mdm.xml file
touch /var/lib/cloudflare-warp/mdm.xml
echo -e "<dict>\n <key>organization</key>\n <string>your-team-name</string>\n</dict>
" > /var/lib/cloudflare-warp/mdm.xml
# Add cloudflare gpg key
curl -fsSL https://pkg.cloudflareclient.com/pubkey.gpg | sudo gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg
# Add this repo to your apt repositories
echo "deb [signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list
# Install
sudo apt-get -y update && sudo apt-get -y install cloudflare-warp
```

> To learn about deploying scripts across multiple hosts, check out this [article.](https://fleetdm.com/guides/policy-automation-run-script)
To install WARP on other Linux distributions, refer to the [package repository](https://pkg.cloudflareclient.com/)

<meta name="articleTitle" value="Deploying Cloudflare WARP with Fleet">
<meta name="authorFullName" value="Harrison Ravazzolo">
<meta name="authorGitHubUsername" value="harrisonravazzolo">
<meta name="category" value="guides">
<meta name="publishedOn" value="2024-12-20">
1 change: 1 addition & 0 deletions changes/23783-controls-subnav-pagination
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Fixed UI bug involving pagination of subsections within the "Controls" page.
63 changes: 40 additions & 23 deletions cmd/osquery-perf/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -514,8 +514,7 @@ type agent struct {
MDMCheckInInterval time.Duration
DiskEncryptionEnabled bool

scheduledQueriesMu sync.Mutex // protects the below members
scheduledQueryData map[string]scheduledQuery
scheduledQueryData *sync.Map
// bufferedResults contains result logs that are buffered when
// /api/v1/osquery/log requests to the Fleet server fail.
//
Expand Down Expand Up @@ -668,6 +667,7 @@ func newAgent(
disableFleetDesktop: disableFleetDesktop,
loggerTLSMaxLines: loggerTLSMaxLines,
bufferedResults: make(map[resultLog]int),
scheduledQueryData: new(sync.Map),
}
}

Expand Down Expand Up @@ -777,28 +777,38 @@ func (a *agent) runLoop(i int, onlyAlreadyEnrolled bool) {
// check if we have any scheduled queries that should be returning results
var results []resultLog
now := time.Now().Unix()
a.scheduledQueriesMu.Lock()
prevCount := a.countBuffered()
for queryName, query := range a.scheduledQueryData {

// NOTE The goroutine that pulls in new configurations
// MAY replace this map if it happens to run at the
// exact same time. The result would be. The result
// would be that the query lastRun does not get
// updated and cause the query to run more times than
// expected.
queryData := a.scheduledQueryData
queryData.Range(func(key, value any) bool {
queryName := key.(string)
query := value.(scheduledQuery)

if query.lastRun == 0 || now >= (query.lastRun+int64(query.ScheduleInterval)) {
results = append(results, resultLog{
packName: query.packName,
queryName: query.Name,
numRows: int(query.numRows),
})
// Update lastRun
v := a.scheduledQueryData[queryName]
v.lastRun = now
a.scheduledQueryData[queryName] = v
query.lastRun = now
queryData.Store(queryName, query)
}
}

return true
})
if prevCount+len(results) < 1_000_000 { // osquery buffered_log_max is 1M
a.addToBuffer(results)
}
a.sendLogsBatch()
newBufferedCount := a.countBuffered() - prevCount
a.stats.UpdateBufferedLogs(newBufferedCount)
a.scheduledQueriesMu.Unlock()
}
}

Expand Down Expand Up @@ -1518,7 +1528,16 @@ func (a *agent) config() error {
return fmt.Errorf("json parse at config: %w", err)
}

scheduledQueryData := make(map[string]scheduledQuery)
existingLastRunData := make(map[string]int64)

a.scheduledQueryData.Range(func(key, value any) bool {
existingLastRunData[key.(string)] = value.(scheduledQuery).lastRun

return true
})

newScheduledQueryData := new(sync.Map)

for packName, pack := range parsedResp.Packs {
for queryName, query := range pack.Queries {
m, ok := query.(map[string]interface{})
Expand Down Expand Up @@ -1546,17 +1565,14 @@ func (a *agent) config() error {
q.Query = m["query"].(string)

scheduledQueryName := packName + "_" + queryName
if existingEntry, ok := a.scheduledQueryData[scheduledQueryName]; ok {
// Keep lastRun if the query is already scheduled.
q.lastRun = existingEntry.lastRun
if lastRun, ok := existingLastRunData[scheduledQueryName]; ok {
q.lastRun = lastRun
}
scheduledQueryData[scheduledQueryName] = q
newScheduledQueryData.Store(scheduledQueryName, q)
}
}

a.scheduledQueriesMu.Lock()
a.scheduledQueryData = scheduledQueryData
a.scheduledQueriesMu.Unlock()
a.scheduledQueryData = newScheduledQueryData

return nil
}
Expand Down Expand Up @@ -1852,13 +1868,12 @@ func (a *agent) runPolicy(query string) []map[string]string {
}

func (a *agent) randomQueryStats() []map[string]string {
a.scheduledQueriesMu.Lock()
defer a.scheduledQueriesMu.Unlock()

var stats []map[string]string
for scheduledQuery := range a.scheduledQueryData {
a.scheduledQueryData.Range(func(key, value any) bool {
queryName := key.(string)

stats = append(stats, map[string]string{
"name": scheduledQuery,
"name": queryName,
"delimiter": "_",
"average_memory": fmt.Sprint(rand.Intn(200) + 10),
"denylisted": "false",
Expand All @@ -1871,7 +1886,9 @@ func (a *agent) randomQueryStats() []map[string]string {
"wall_time": fmt.Sprint(rand.Intn(4) + 1),
"wall_time_ms": fmt.Sprint(rand.Intn(4000) + 10),
})
}

return true
})
return stats
}

Expand Down
1 change: 1 addition & 0 deletions frontend/components/AvatarTopNav/AvatarTopNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const Avatar = ({ className, size, user }: IAvatarInterface): JSX.Element => {
src={gravatar_url_dark || DEFAULT_GRAVATAR_LINK_DARK}
onError={onError}
onLoad={onLoad}
data-testid="user-avatar"
/>
</div>
);
Expand Down
1 change: 0 additions & 1 deletion frontend/components/AvatarTopNav/_styles.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
.avatar-wrapper-top-nav {
margin-right: 8px;
svg {
display: block;
}
Expand Down
Loading

0 comments on commit 0a41c1a

Please sign in to comment.