mirror of
https://github.com/fleetdm/fleet
synced 2026-05-20 07:29:08 +00:00
#13643 New integration test for `fleetctl gitops` which loads the configs from https://github.com/fleetdm/fleet-gitops
245 lines
7.3 KiB
Go
245 lines
7.3 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"github.com/fleetdm/fleet/v4/server/config"
|
|
"github.com/fleetdm/fleet/v4/server/datastore/mysql"
|
|
"github.com/fleetdm/fleet/v4/server/datastore/redis/redistest"
|
|
"github.com/fleetdm/fleet/v4/server/fleet"
|
|
appleMdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
|
|
"github.com/fleetdm/fleet/v4/server/ptr"
|
|
"github.com/fleetdm/fleet/v4/server/service"
|
|
"github.com/fleetdm/fleet/v4/server/test"
|
|
"github.com/go-git/go-git/v5"
|
|
|
|
nanodepClient "github.com/micromdm/nanodep/client"
|
|
"github.com/micromdm/nanodep/tokenpki"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/stretchr/testify/suite"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestIntegrationsGitops(t *testing.T) {
|
|
testingSuite := new(integrationGitopsTestSuite)
|
|
testingSuite.suite = &testingSuite.Suite
|
|
suite.Run(t, testingSuite)
|
|
}
|
|
|
|
type integrationGitopsTestSuite struct {
|
|
suite.Suite
|
|
withServer
|
|
fleetCfg config.FleetConfig
|
|
}
|
|
|
|
func (s *integrationGitopsTestSuite) SetupSuite() {
|
|
s.withDS.SetupSuite("integrationGitopsTestSuite")
|
|
|
|
appConf, err := s.ds.AppConfig(context.Background())
|
|
require.NoError(s.T(), err)
|
|
appConf.MDM.EnabledAndConfigured = true
|
|
appConf.MDM.WindowsEnabledAndConfigured = true
|
|
appConf.MDM.AppleBMEnabledAndConfigured = true
|
|
err = s.ds.SaveAppConfig(context.Background(), appConf)
|
|
require.NoError(s.T(), err)
|
|
|
|
testCert, testKey, err := appleMdm.NewSCEPCACertKey()
|
|
require.NoError(s.T(), err)
|
|
testCertPEM := tokenpki.PEMCertificate(testCert.Raw)
|
|
testKeyPEM := tokenpki.PEMRSAPrivateKey(testKey)
|
|
|
|
fleetCfg := config.TestConfig()
|
|
config.SetTestMDMConfig(s.T(), &fleetCfg, testCertPEM, testKeyPEM, testBMToken, "../../server/service/testdata")
|
|
fleetCfg.Osquery.EnrollCooldown = 0
|
|
|
|
mdmStorage, err := s.ds.NewMDMAppleMDMStorage(testCertPEM, testKeyPEM)
|
|
require.NoError(s.T(), err)
|
|
depStorage, err := s.ds.NewMDMAppleDEPStorage(*testBMToken)
|
|
require.NoError(s.T(), err)
|
|
scepStorage, err := s.ds.NewSCEPDepot(testCertPEM, testKeyPEM)
|
|
require.NoError(s.T(), err)
|
|
redisPool := redistest.SetupRedis(s.T(), "zz", false, false, false)
|
|
|
|
serverConfig := service.TestServerOpts{
|
|
License: &fleet.LicenseInfo{
|
|
Tier: fleet.TierPremium,
|
|
},
|
|
FleetConfig: &fleetCfg,
|
|
MDMStorage: mdmStorage,
|
|
DEPStorage: depStorage,
|
|
SCEPStorage: scepStorage,
|
|
Pool: redisPool,
|
|
APNSTopic: "com.apple.mgmt.External.10ac3ce5-4668-4e58-b69a-b2b5ce667589",
|
|
}
|
|
users, server := service.RunServerForTestsWithDS(s.T(), s.ds, &serverConfig)
|
|
s.T().Setenv("FLEET_SERVER_ADDRESS", server.URL) // fleetctl always uses this env var in tests
|
|
s.server = server
|
|
s.users = users
|
|
s.fleetCfg = fleetCfg
|
|
|
|
appConf, err = s.ds.AppConfig(context.Background())
|
|
require.NoError(s.T(), err)
|
|
appConf.ServerSettings.ServerURL = server.URL
|
|
err = s.ds.SaveAppConfig(context.Background(), appConf)
|
|
require.NoError(s.T(), err)
|
|
}
|
|
|
|
func (s *integrationGitopsTestSuite) TearDownSuite() {
|
|
appConf, err := s.ds.AppConfig(context.Background())
|
|
require.NoError(s.T(), err)
|
|
appConf.MDM.EnabledAndConfigured = false
|
|
err = s.ds.SaveAppConfig(context.Background(), appConf)
|
|
require.NoError(s.T(), err)
|
|
}
|
|
|
|
// TestFleetGitops runs `fleetctl gitops` command on configs in https://github.com/fleetdm/fleet-gitops repo.
|
|
// Changes to that repo may cause this test to fail.
|
|
func (s *integrationGitopsTestSuite) TestFleetGitops() {
|
|
t := s.T()
|
|
const fleetGitopsRepo = "https://github.com/fleetdm/fleet-gitops"
|
|
|
|
// Create GitOps user
|
|
user := fleet.User{
|
|
Name: "GitOps User",
|
|
Email: "fleetctl-gitops@example.com",
|
|
GlobalRole: ptr.String(fleet.RoleGitOps),
|
|
}
|
|
require.NoError(t, user.SetPassword(test.GoodPassword, 10, 10))
|
|
_, err := s.ds.NewUser(context.Background(), &user)
|
|
require.NoError(t, err)
|
|
|
|
// Create a temporary fleetctl config file
|
|
fleetctlConfig, err := os.CreateTemp(t.TempDir(), "*.yml")
|
|
require.NoError(t, err)
|
|
token := s.getTestToken(user.Email, test.GoodPassword)
|
|
configStr := fmt.Sprintf(
|
|
`
|
|
contexts:
|
|
default:
|
|
address: %s
|
|
tls-skip-verify: true
|
|
token: %s
|
|
`, s.server.URL, token,
|
|
)
|
|
_, err = fleetctlConfig.WriteString(configStr)
|
|
require.NoError(t, err)
|
|
|
|
// Clone git repo
|
|
repoDir := t.TempDir()
|
|
_, err = git.PlainClone(
|
|
repoDir, false, &git.CloneOptions{
|
|
ReferenceName: "main",
|
|
SingleBranch: true,
|
|
Depth: 1,
|
|
URL: fleetGitopsRepo,
|
|
Progress: os.Stdout,
|
|
},
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
// Set the required environment variables
|
|
t.Setenv("FLEET_SSO_METADATA", "sso_metadata")
|
|
t.Setenv("FLEET_GLOBAL_ENROLL_SECRET", "global_enroll_secret")
|
|
t.Setenv("FLEET_WORKSTATIONS_ENROLL_SECRET", "workstations_enroll_secret")
|
|
t.Setenv("FLEET_WORKSTATIONS_CANARY_ENROLL_SECRET", "workstations_canary_enroll_secret")
|
|
globalFile := path.Join(repoDir, "default.yml")
|
|
teamsDir := path.Join(repoDir, "teams")
|
|
teamFiles, err := os.ReadDir(teamsDir)
|
|
require.NoError(t, err)
|
|
|
|
// Dry run
|
|
_ = runAppForTest(t, []string{"gitops", "--config", fleetctlConfig.Name(), "-f", globalFile, "--dry-run"})
|
|
for _, file := range teamFiles {
|
|
if filepath.Ext(file.Name()) == ".yml" {
|
|
_ = runAppForTest(t, []string{"gitops", "--config", fleetctlConfig.Name(), "-f", path.Join(teamsDir, file.Name()), "--dry-run"})
|
|
}
|
|
}
|
|
|
|
// Real run
|
|
_ = runAppForTest(t, []string{"gitops", "--config", fleetctlConfig.Name(), "-f", globalFile})
|
|
for _, file := range teamFiles {
|
|
if filepath.Ext(file.Name()) == ".yml" {
|
|
_ = runAppForTest(t, []string{"gitops", "--config", fleetctlConfig.Name(), "-f", path.Join(teamsDir, file.Name())})
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
type withDS struct {
|
|
suite *suite.Suite
|
|
ds *mysql.Datastore
|
|
}
|
|
|
|
func (ts *withDS) SetupSuite(dbName string) {
|
|
t := ts.suite.T()
|
|
ts.ds = mysql.CreateNamedMySQLDS(t, dbName)
|
|
test.AddAllHostsLabel(t, ts.ds)
|
|
|
|
// Set up the required fields on AppConfig
|
|
appConf, err := ts.ds.AppConfig(context.Background())
|
|
require.NoError(t, err)
|
|
appConf.OrgInfo.OrgName = "FleetTest"
|
|
appConf.ServerSettings.ServerURL = "https://example.org"
|
|
err = ts.ds.SaveAppConfig(context.Background(), appConf)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func (ts *withDS) TearDownSuite() {
|
|
_ = ts.ds.Close()
|
|
}
|
|
|
|
type withServer struct {
|
|
withDS
|
|
|
|
server *httptest.Server
|
|
users map[string]fleet.User
|
|
}
|
|
|
|
type loginRequest struct {
|
|
Email string `json:"email"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
func (ts *withServer) getTestToken(email string, password string) string {
|
|
params := loginRequest{
|
|
Email: email,
|
|
Password: password,
|
|
}
|
|
j, err := json.Marshal(¶ms)
|
|
require.NoError(ts.suite.T(), err)
|
|
|
|
requestBody := io.NopCloser(bytes.NewBuffer(j))
|
|
resp, err := http.Post(ts.server.URL+"/api/latest/fleet/login", "application/json", requestBody)
|
|
require.NoError(ts.suite.T(), err)
|
|
defer func() { _ = resp.Body.Close() }()
|
|
assert.Equal(ts.suite.T(), http.StatusOK, resp.StatusCode)
|
|
|
|
jsn := struct {
|
|
User *fleet.User `json:"user"`
|
|
Token string `json:"token"`
|
|
Err []map[string]string `json:"errors,omitempty"`
|
|
}{}
|
|
err = json.NewDecoder(resp.Body).Decode(&jsn)
|
|
require.NoError(ts.suite.T(), err)
|
|
require.Len(ts.suite.T(), jsn.Err, 0)
|
|
|
|
return jsn.Token
|
|
}
|
|
|
|
var testBMToken = &nanodepClient.OAuth1Tokens{
|
|
ConsumerKey: "test_consumer",
|
|
ConsumerSecret: "test_secret",
|
|
AccessToken: "test_access_token",
|
|
AccessSecret: "test_access_secret",
|
|
AccessTokenExpiry: time.Date(2999, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
}
|