2022-07-18 16:44:30 +00:00
|
|
|
package service
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
2022-07-27 19:47:39 +00:00
|
|
|
"net/url"
|
2024-03-13 14:27:29 +00:00
|
|
|
"os"
|
2022-07-18 16:44:30 +00:00
|
|
|
"testing"
|
|
|
|
|
2022-07-27 19:47:39 +00:00
|
|
|
"github.com/fleetdm/fleet/v4/server/config"
|
2022-07-18 16:44:30 +00:00
|
|
|
"github.com/fleetdm/fleet/v4/server/datastore/s3"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/fleet"
|
2024-03-13 14:27:29 +00:00
|
|
|
kitlog "github.com/go-kit/kit/log"
|
2022-07-18 16:44:30 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
)
|
|
|
|
|
2022-08-04 21:39:38 +00:00
|
|
|
const enrollSecret = "xyz/abc$@"
|
2022-07-18 16:44:30 +00:00
|
|
|
|
2022-07-27 19:47:39 +00:00
|
|
|
type integrationSandboxTestSuite struct {
|
2022-07-18 16:44:30 +00:00
|
|
|
suite.Suite
|
|
|
|
withServer
|
|
|
|
installers []fleet.Installer
|
|
|
|
}
|
|
|
|
|
2022-07-27 19:47:39 +00:00
|
|
|
func (s *integrationSandboxTestSuite) SetupSuite() {
|
|
|
|
s.withDS.SetupSuite("integrationSandboxTestSuite")
|
2022-07-18 16:44:30 +00:00
|
|
|
t := s.T()
|
|
|
|
|
2022-07-27 19:47:39 +00:00
|
|
|
// make sure sandbox is enabled
|
|
|
|
cfg := config.TestConfig()
|
|
|
|
cfg.Server.SandboxEnabled = true
|
|
|
|
|
2022-07-18 16:44:30 +00:00
|
|
|
is := s3.SetupTestInstallerStore(t, "integration-tests", "")
|
2024-03-13 14:27:29 +00:00
|
|
|
opts := &TestServerOpts{FleetConfig: &cfg, Is: is}
|
|
|
|
if os.Getenv("FLEET_INTEGRATION_TESTS_DISABLE_LOG") != "" {
|
|
|
|
opts.Logger = kitlog.NewNopLogger()
|
|
|
|
}
|
|
|
|
users, server := RunServerForTestsWithDS(t, s.ds, opts)
|
2022-07-18 16:44:30 +00:00
|
|
|
s.server = server
|
|
|
|
s.users = users
|
|
|
|
s.token = s.getTestAdminToken()
|
|
|
|
s.installers = s3.SeedTestInstallerStore(t, is, enrollSecret)
|
|
|
|
|
|
|
|
err := s.ds.ApplyEnrollSecrets(context.TODO(), nil, []*fleet.EnrollSecret{{Secret: enrollSecret}})
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2022-07-27 19:47:39 +00:00
|
|
|
func TestIntegrationsSandbox(t *testing.T) {
|
|
|
|
testingSuite := new(integrationSandboxTestSuite)
|
2022-07-18 16:44:30 +00:00
|
|
|
testingSuite.s = &testingSuite.Suite
|
|
|
|
suite.Run(t, testingSuite)
|
|
|
|
}
|
|
|
|
|
2022-07-27 19:47:39 +00:00
|
|
|
func (s *integrationSandboxTestSuite) TestDemoLogin() {
|
2022-07-18 16:44:30 +00:00
|
|
|
t := s.T()
|
|
|
|
|
2022-07-27 19:47:39 +00:00
|
|
|
validEmail := testUsers["user1"].Email
|
|
|
|
validPwd := testUsers["user1"].PlaintextPassword
|
|
|
|
wrongPwd := "nope"
|
|
|
|
hdrs := map[string]string{"Content-Type": "application/x-www-form-urlencoded"}
|
|
|
|
|
|
|
|
formBody := make(url.Values)
|
|
|
|
formBody.Set("email", validEmail)
|
|
|
|
formBody.Set("password", wrongPwd)
|
|
|
|
res := s.DoRawWithHeaders("POST", "/api/v1/fleet/demologin", []byte(formBody.Encode()), http.StatusUnauthorized, hdrs)
|
|
|
|
require.Equal(t, http.StatusUnauthorized, res.StatusCode)
|
|
|
|
|
|
|
|
formBody.Set("email", validEmail)
|
|
|
|
formBody.Set("password", validPwd)
|
|
|
|
res = s.DoRawWithHeaders("POST", "/api/v1/fleet/demologin", []byte(formBody.Encode()), http.StatusOK, hdrs)
|
|
|
|
resBody, err := io.ReadAll(res.Body)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, http.StatusOK, res.StatusCode)
|
|
|
|
require.Contains(t, string(resBody), `window.location = "/"`)
|
|
|
|
require.Regexp(t, `window.localStorage.setItem\('FLEET::auth_token', '[^']+'\)`, string(resBody))
|
|
|
|
}
|
2022-07-18 16:44:30 +00:00
|
|
|
|
2022-07-27 19:47:39 +00:00
|
|
|
func (s *integrationSandboxTestSuite) TestInstallerGet() {
|
|
|
|
t := s.T()
|
|
|
|
|
2022-08-16 15:54:41 +00:00
|
|
|
validURL, formBody := installerPOSTReq(enrollSecret, "pkg", s.token, false)
|
2022-07-18 16:44:30 +00:00
|
|
|
|
2022-08-16 15:54:41 +00:00
|
|
|
r := s.DoRaw("POST", validURL, formBody, http.StatusOK)
|
2022-07-18 16:44:30 +00:00
|
|
|
body, err := io.ReadAll(r.Body)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, "mock", string(body))
|
|
|
|
require.Equal(t, "application/octet-stream", r.Header.Get("Content-Type"))
|
|
|
|
require.Equal(t, "4", r.Header.Get("Content-Length"))
|
2022-08-16 15:54:41 +00:00
|
|
|
require.Equal(t, `attachment;filename="fleet-osquery.pkg"`, r.Header.Get("Content-Disposition"))
|
2022-10-12 13:19:21 +00:00
|
|
|
require.Equal(t, `nosniff`, r.Header.Get("X-Content-Type-Options"))
|
2022-07-18 16:44:30 +00:00
|
|
|
|
|
|
|
// unauthorized requests
|
2022-08-16 15:54:41 +00:00
|
|
|
s.DoRawNoAuth("POST", validURL, nil, http.StatusUnauthorized)
|
2022-07-18 16:44:30 +00:00
|
|
|
s.token = "invalid"
|
2022-08-16 15:54:41 +00:00
|
|
|
s.Do("POST", validURL, nil, http.StatusUnauthorized)
|
2022-07-18 16:44:30 +00:00
|
|
|
s.token = s.cachedAdminToken
|
|
|
|
|
|
|
|
// wrong enroll secret
|
2022-08-16 15:54:41 +00:00
|
|
|
wrongURL, wrongFormBody := installerPOSTReq("wrong-enroll", "pkg", s.token, false)
|
2023-04-13 20:16:40 +00:00
|
|
|
s.Do("POST", wrongURL, wrongFormBody, http.StatusNotFound)
|
2022-07-18 16:44:30 +00:00
|
|
|
|
|
|
|
// non-existent package
|
2022-08-16 15:54:41 +00:00
|
|
|
wrongURL, wrongFormBody = installerPOSTReq(enrollSecret, "exe", s.token, false)
|
|
|
|
s.Do("POST", wrongURL, wrongFormBody, http.StatusNotFound)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *integrationSandboxTestSuite) TestInstallerHeadCheck() {
|
|
|
|
validURL := installerURL(enrollSecret, "pkg", false)
|
2022-08-23 12:58:10 +00:00
|
|
|
s.DoRaw("HEAD", validURL, nil, http.StatusOK)
|
2022-08-16 15:54:41 +00:00
|
|
|
|
|
|
|
// unauthorized requests
|
|
|
|
s.DoRawNoAuth("HEAD", validURL, nil, http.StatusUnauthorized)
|
|
|
|
s.token = "invalid"
|
2022-08-23 12:58:10 +00:00
|
|
|
s.DoRaw("HEAD", validURL, nil, http.StatusUnauthorized)
|
2022-08-16 15:54:41 +00:00
|
|
|
s.token = s.cachedAdminToken
|
|
|
|
|
|
|
|
// wrong enroll secret
|
|
|
|
invalidURL := installerURL("wrong-enroll", "pkg", false)
|
2023-04-13 20:16:40 +00:00
|
|
|
s.DoRaw("HEAD", invalidURL, nil, http.StatusNotFound)
|
2022-08-16 15:54:41 +00:00
|
|
|
|
|
|
|
// non-existent package
|
|
|
|
invalidURL = installerURL(enrollSecret, "exe", false)
|
2022-08-23 12:58:10 +00:00
|
|
|
s.DoRaw("HEAD", invalidURL, nil, http.StatusNotFound)
|
2022-07-18 16:44:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func installerURL(secret, kind string, desktop bool) string {
|
2022-08-16 15:54:41 +00:00
|
|
|
path := fmt.Sprintf("/api/latest/fleet/download_installer/%s?enroll_secret=%s", kind, secret)
|
|
|
|
if desktop {
|
|
|
|
path += "&desktop=1"
|
|
|
|
}
|
|
|
|
return path
|
|
|
|
}
|
|
|
|
|
|
|
|
func installerPOSTReq(secret, kind, token string, desktop bool) (string, []byte) {
|
|
|
|
path := installerURL(secret, kind, desktop)
|
|
|
|
d := "0"
|
2022-07-18 16:44:30 +00:00
|
|
|
if desktop {
|
2022-08-16 15:54:41 +00:00
|
|
|
d = "1"
|
2022-07-18 16:44:30 +00:00
|
|
|
}
|
2022-08-16 15:54:41 +00:00
|
|
|
formBody := make(url.Values)
|
|
|
|
formBody.Set("token", token)
|
|
|
|
formBody.Set("enroll_secret", secret)
|
|
|
|
formBody.Set("desktop", d)
|
|
|
|
return path, []byte(formBody.Encode())
|
2022-07-18 16:44:30 +00:00
|
|
|
}
|