fleet/.github/workflows/fleet-and-orbit.yml
Marcos Oviedo 381f628be7
Bug 7874: Adding SCM calls to register Orbit as a windows service (#7934)
* Bug 7874: Adding SCM calls to register Orbit as a windows service
2022-09-27 11:52:41 -03:00

439 lines
14 KiB
YAML

name: Test Fleetctl Package, Orbit & Fleet
# This workflow tests orbit code changes (compiles orbit from source).
# It uses a fleet instance also built and executed from source.
#
# It tests that orbit osquery agents enroll successfully to Fleet.
on:
push:
branches:
- main
- patch-*
paths:
- 'orbit/**.go'
pull_request:
paths:
- 'orbit/**.go'
workflow_dispatch: # Manual
permissions:
contents: read
jobs:
gen:
runs-on: ubuntu-latest
outputs:
subdomain: ${{ steps.gen.outputs.subdomain }}
domain: ${{ steps.gen.outputs.domain }}
address: ${{ steps.gen.outputs.address }}
enroll_secret: ${{ steps.gen.outputs.enroll_secret }}
steps:
- id: gen
run: |
UUID=$(uuidgen)
echo "::set-output name=subdomain::fleet-test-$UUID"
echo "::set-output name=domain::fleet-test-$UUID.fleetuem.com"
echo "::set-output name=address::https://fleet-test-$UUID.fleetuem.com"
ENROLL=$(uuidgen)
echo "::set-output name=enroll_secret::$ENROLL"
run-server:
timeout-minutes: 60
strategy:
matrix:
go-version: ['^1.19.1']
mysql: ['mysql:5.7']
runs-on: ubuntu-latest
needs: gen
steps:
- name: Install Go
uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a # v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout Code
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v2
- name: Start tunnel
env:
CERT_PEM: ${{ secrets.CLOUDFLARE_TUNNEL_FLEETUEM_CERT_B64 }}
run: |
# Install cloudflared
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb
# Add secret
echo "$CERT_PEM" | base64 -d > cert.pem
# Start tunnel
cloudflared tunnel --origincert cert.pem --hostname ${{ needs.gen.outputs.subdomain }} --url http://localhost:1337 --name ${{ needs.gen.outputs.subdomain }} &
until [[ $(cloudflared tunnel --origincert cert.pem info -o json ${{ needs.gen.outputs.subdomain }} | jq '.conns[0].conns[0].is_pending_reconnect') = false ]]; do
echo "Awaiting tunnel ready..."
sleep 5
done
- name: Start Infra Dependencies
run: FLEET_MYSQL_IMAGE=${{ matrix.mysql }} docker-compose up -d mysql redis &
- name: Install JS Dependencies
run: make deps-js
- name: Generate and bundle go & js code
run: make generate
- name: Build fleet and fleetctl
# fleet-dev builds fleet with "race" enabled.
run: make fleet-dev fleetctl
- name: Run Fleet server
env:
FLEET_OSQUERY_HOST_IDENTIFIER: instance # use instance identifier to allow for duplicate UUIDs
FLEET_SERVER_ADDRESS: 0.0.0.0:1337
FLEET_SERVER_TLS: false
FLEET_LOGGING_DEBUG: true
run: |
mkdir ./fleet_log
make db-reset
./build/fleet serve --dev --dev_license 1>./fleet_log/stdout.log 2>./fleet_log/stderr.log &
./build/fleetctl config set --address http://localhost:1337 --tls-skip-verify
until ./build/fleetctl setup --email admin@example.com --name Admin --password preview1337# --org-name Example
do
echo "Retrying setup in 5s..."
sleep 5
done
# Wait for all of the hosts to be enrolled
EXPECTED=3
until [ $(./build/fleetctl get hosts --json | grep "hostname" | wc -l | tee hostcount) -ge $EXPECTED ]; do
echo -n "Waiting for hosts to enroll: "
cat hostcount | xargs echo -n
echo " / $EXPECTED"
sleep 30
done
./build/fleetctl get hosts
echo "Success! $EXPECTED hosts enrolled."
- name: Cleanup tunnel
if: always()
run: cloudflared tunnel --origincert cert.pem delete --force ${{ needs.gen.outputs.subdomain }}
- name: Upload fleet logs
if: always()
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v2
with:
name: fleet-logs
path: |
fleet_log
# Sets the enroll secret of the Fleet server.
#
# This job also makes sure the Fleet server is up and running.
set-enroll-secret:
timeout-minutes: 60
strategy:
matrix:
go-version: ['^1.19.1']
runs-on: ubuntu-latest
needs: gen
steps:
- name: Install Go
uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a # v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout Code
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v2
- name: Build Fleetctl
run: make fleetctl
- id: enroll
name: Set enroll secret
run: |
./build/fleetctl config set --address ${{ needs.gen.outputs.address }}
until ./build/fleetctl login --email admin@example.com --password preview1337#
do
echo "Retrying in 30s..."
sleep 30
done
echo '---
apiVersion: v1
kind: enroll_secret
spec:
secrets:
- secret: ${{ needs.gen.outputs.enroll_secret }}
' > secrets.yml
./build/fleetctl apply -f secrets.yml
# TODO(lucas): Currently, to simplify the workflow we do all in one job:
# 1. Generate TUF repository (compile Orbit from source).
# 2. Run TUF server on localhost.
# 3. Generate packages using localhost TUF server.
#
# When installing the generated packages, Orbit will log "update errors"
# because the TUF URL is set to http://localhost:8081.
#
# TODO(lucas): Test the generated RPM package on a CentOS docker image.
run-tuf-and-gen-pkgs:
timeout-minutes: 60
strategy:
matrix:
go-version: ['^1.19.1']
# We can only generate all (PKG, MSI, DEB, RPM) packages from a macOS host.
runs-on: macos-latest
needs: gen
steps:
- name: Install Go
uses: actions/setup-go@84cbf8094393cdc5fe1fe1671ff2647332956b1a # v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout Code
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v2
# Docker needs to be installed manually on macOS.
# From https://github.com/docker/for-mac/issues/2359#issuecomment-943131345
# FIXME: lock Docker version to 4.10.0 as newer versions fail to initialize
- name: Install Docker
timeout-minutes: 20
run: |
curl -L https://raw.githubusercontent.com/Homebrew/homebrew-cask/c65030146a5cf2070c2499b6c68e2c3495c99731/Casks/docker.rb > docker.rb
brew install --cask docker.rb
sudo /Applications/Docker.app/Contents/MacOS/Docker --unattended --install-privileged-components
open -a /Applications/Docker.app --args --unattended --accept-license
echo "Waiting for Docker to start up..."
while ! /Applications/Docker.app/Contents/Resources/bin/docker info &>/dev/null; do
sleep 1;
done
echo "Docker is ready."
- name: Build Repository and run TUF server
env:
SYSTEMS: "macos windows linux"
PKG_FLEET_URL: ${{ needs.gen.outputs.address }}
PKG_TUF_URL: http://localhost:8081
DEB_FLEET_URL: ${{ needs.gen.outputs.address }}
DEB_TUF_URL: http://localhost:8081
RPM_FLEET_URL: ${{ needs.gen.outputs.address }}
RPM_TUF_URL: http://localhost:8081
MSI_FLEET_URL: ${{ needs.gen.outputs.address }}
MSI_TUF_URL: http://localhost:8081
ENROLL_SECRET: ${{ needs.gen.outputs.enroll_secret }}
GENERATE_PKG: 1
GENERATE_DEB: 1
GENERATE_RPM: 1
GENERATE_MSI: 1
FLEET_DESKTOP: 1
run: |
./tools/tuf/test/main.sh
- name: Upload PKG installer
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v2
with:
name: fleet-osquery.pkg
path: |
fleet-osquery.pkg
- name: Upload DEB installer
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v2
with:
name: fleet-osquery_42.0.0_amd64.deb
path: |
fleet-osquery_42.0.0_amd64.deb
- name: Upload MSI installer
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v2
with:
name: fleet-osquery.msi
path: |
fleet-osquery.msi
orbit-macos:
timeout-minutes: 60
runs-on: macos-latest
needs: [gen, run-tuf-and-gen-pkgs]
steps:
- name: Checkout Code
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v2
- name: Download pkg
id: download
uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741 # v2
with:
name: fleet-osquery.pkg
- name: Install pkg
run: |
sudo hostname orbit-macos
sudo installer -pkg ${{ steps.download.outputs.download-path }}/fleet-osquery.pkg -target /
- name: Wait enroll
run: |
# Wait until fleet server goes down.
while curl --fail ${{ needs.gen.outputs.address }};
do
echo "Retrying in 10s..."
sleep 10
done
- name: Run orbit shell
run:
sudo orbit shell -- --json "select * from osquery_info;" | jq -e 'if (.[0]) then true else false end'
- name: Collect orbit logs
if: always()
run: |
mkdir orbit-logs
sudo cp /var/log/orbit/* orbit-logs/
- name: Upload orbit logs
if: always()
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v2
with:
name: orbit-logs
path: |
orbit-logs
- name: Uninstall pkg
run: |
./orbit/tools/cleanup/cleanup_macos.sh
orbit-ubuntu:
timeout-minutes: 60
runs-on: ubuntu-latest
needs: [gen, run-tuf-and-gen-pkgs]
steps:
- name: Download deb
id: download
uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741 # v2
with:
name: fleet-osquery_42.0.0_amd64.deb
- name: Install deb
run: |
sudo hostname orbit-ubuntu
sudo dpkg --install ${{ steps.download.outputs.download-path }}/fleet-osquery_42.0.0_amd64.deb
- name: Wait enroll
run: |
# Wait until fleet server goes down.
while curl --fail ${{ needs.gen.outputs.address }};
do
echo "Retrying in 10s..."
sleep 10
done
- name: Run orbit shell
run:
sudo orbit shell -- --json "select * from osquery_info;" | jq -e 'if (.[0]) then true else false end'
- name: Collect orbit logs
if: always()
run: |
mkdir orbit-logs
sudo journalctl -u orbit.service > orbit-logs/orbit_service.log
- name: Upload orbit logs
if: always()
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v2
with:
name: orbit-logs
path: |
orbit-logs
- name: Uninstall deb
run: |
sudo apt remove fleet-osquery -y
orbit-windows:
timeout-minutes: 60
needs: [run-tuf-and-gen-pkgs]
runs-on: windows-latest
steps:
- name: Download msi
id: download
uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741 # v2
with:
name: fleet-osquery.msi
- name: Install msi
run: |
msiexec /i ${{ steps.download.outputs.download-path }}\fleet-osquery.msi /quiet /passive /lv log.txt
- name: Wait enroll
shell: bash
run: |
while curl --fail ${{ needs.gen.outputs.address }};
do
echo "Retrying in 10s..."
sleep 10
done
- name: Run orbit shell
shell: cmd
run: |
"C:\Program Files\Orbit\bin\orbit\orbit.exe" shell -- --json "select * from osquery_info;" | jq -e "if (.[0]) then true else false end"
- name: Fleet Service Tests
shell: powershell
run: |
#Tests setup
$serviceName = "Fleet osquery"
$defaultWaitTime = 2
$orbitRequiredInitExtraTime = 20
#Test 1 - Check that the service starts without issues
Stop-Service -Name $serviceName
Start-Service -Name $serviceName
Get-Service -Name $serviceName | %{ if ($_.Status -ne "Running") { throw "Test #1 failed" } }
#Test 2 - Check that the service stops without issues
Stop-Service -Name $serviceName
Get-Service -Name $serviceName | %{ if ($_.Status -ne "Stopped") { throw "Test #2 failed" } }
#Test 3 - Check that no orbit.exe is running after service stop
Start-Service -Name $serviceName
Stop-Service -Name $serviceName
Start-Sleep -Seconds $defaultWaitTime # shutdown wait time
Get-Process | %{ if ($_.Name -eq "orbit") { throw "Test #3 failed" } }
#Test 4 - Check that service starts in less than 3 secs
Start-Job { Start-Service -Name $args[0] } -ArgumentList $serviceName | Out-Null #async operation
Start-Sleep -Seconds $defaultWaitTime
Get-Service -Name $serviceName | %{ if ($_.Status -ne "Running") { throw "Test #4 failed" } }
#Test 5 - Check that service stops in less than 3 secs
Start-Job { Stop-Service -Name $args[0] } -ArgumentList $serviceName | Out-Null #async operation
Start-Sleep -Seconds $defaultWaitTime
Get-Service -Name $serviceName | %{ if ($_.Status -ne "Stopped") { throw "Test #5 failed" } }
#Test 6 - Check that no osqueryd process is running once service stops
Start-Service -Name $serviceName
Start-Sleep -Seconds $orbitRequiredInitExtraTime # orbit takes some time to spawn osquery and desktop app due to update check
Stop-Service -Name $serviceName
Start-Sleep -Seconds $defaultWaitTime
Get-Process | %{ if ($_.Name -eq "osqueryd") { throw "Test #6 failed" } }
#Test 7 - Check that no fleet-desktop process is running once service stops
Start-Service -Name $serviceName
Start-Sleep -Seconds $orbitRequiredInitExtraTime # orbit takes some time to spawn osquery and desktop app due to update check
Stop-Service -Name $serviceName
Start-Sleep -Seconds $defaultWaitTime
Get-Process | %{ if ($_.Name -eq "fleet-desktop") { throw "Test #7 failed" } }
- name: Upload Orbit logs
if: always()
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v2
with:
name: orbit-logs-windows
path: C:\Windows\system32\config\systemprofile\AppData\Local\FleetDM\Orbit\Logs\orbit-osquery.log