2021-04-12 13:32:25 +00:00
import "@testing-library/cypress/add-commands" ;
2021-06-15 17:14:57 +00:00
import "cypress-wait-until" ;
2022-05-18 17:03:00 +00:00
import CONSTANTS from "./constants" ;
const { GOOD_PASSWORD } = CONSTANTS ;
2021-03-30 19:56:20 +00:00
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
2021-10-12 21:33:56 +00:00
const SHELL = Cypress . platform === "win32" ? "cmd" : "bash" ;
2021-04-12 13:32:25 +00:00
Cypress . Commands . add ( "setup" , ( ) = > {
2021-10-12 21:33:56 +00:00
cy . exec ( "make e2e-reset-db e2e-setup" , {
timeout : 20000 ,
env : { SHELL } ,
} ) ;
2021-03-30 19:56:20 +00:00
} ) ;
2021-06-24 20:42:29 +00:00
Cypress . Commands . add ( "login" , ( email , password ) = > {
email || = "admin@example.com" ;
2022-05-18 17:03:00 +00:00
password || = GOOD_PASSWORD ;
2022-04-11 20:04:38 +00:00
cy . request ( "POST" , "/api/latest/fleet/login" , { email , password } ) . then (
2021-04-12 13:32:25 +00:00
( resp ) = > {
2021-06-07 01:28:37 +00:00
window . localStorage . setItem ( "FLEET::auth_token" , resp . body . token ) ;
2021-04-12 13:32:25 +00:00
}
) ;
2021-04-05 18:01:30 +00:00
} ) ;
2022-01-24 21:21:05 +00:00
Cypress . Commands . add ( "loginWithCySession" , ( email , password ) = > {
email || = "admin@example.com" ;
2022-05-18 17:03:00 +00:00
password || = GOOD_PASSWORD ;
2022-01-24 21:21:05 +00:00
cy . session ( [ email , password ] , ( ) = > {
2022-04-11 20:04:38 +00:00
cy . request ( "POST" , "/api/latest/fleet/login" , { email , password } ) . then (
2022-01-24 21:21:05 +00:00
( resp ) = > {
window . localStorage . setItem ( "FLEET::auth_token" , resp . body . token ) ;
}
) ;
} ) ;
} ) ;
2021-04-12 13:32:25 +00:00
Cypress . Commands . add ( "logout" , ( ) = > {
2021-04-05 18:01:30 +00:00
cy . request ( {
2022-04-11 20:04:38 +00:00
url : "/api/latest/fleet/logout" ,
2021-04-12 13:32:25 +00:00
method : "POST" ,
2021-04-05 18:01:30 +00:00
body : { } ,
auth : {
2021-06-07 01:28:37 +00:00
bearer : window.localStorage.getItem ( "FLEET::auth_token" ) ,
2021-04-05 18:01:30 +00:00
} ,
2021-04-30 15:47:33 +00:00
} ) . then ( ( ) = > {
2021-06-07 01:28:37 +00:00
window . localStorage . removeItem ( "FLEET::auth_token" ) ;
2021-04-30 15:47:33 +00:00
} ) ;
} ) ;
2021-06-11 21:27:19 +00:00
Cypress . Commands . add ( "seedQueries" , ( ) = > {
const queries = [
{
name : "Detect presence of authorized SSH keys" ,
query :
"SELECT username, authorized_keys. * FROM users CROSS JOIN authorized_keys USING (uid)" ,
description :
"Presence of authorized SSH keys may be unusual on laptops. Could be completely normal on servers, but may be worth auditing for unusual keys and/or changes." ,
observer_can_run : true ,
} ,
{
name : "Get authorized keys for Domain Joined Accounts" ,
query :
"SELECT * FROM users CROSS JOIN authorized_keys USING(uid) WHERE username IN (SELECT distinct(username) FROM last);" ,
description : "List authorized_keys for each user on the system." ,
observer_can_run : false ,
} ,
2021-08-30 23:02:53 +00:00
{
2022-04-20 18:12:53 +00:00
name : "Get local user accounts" ,
2021-08-30 23:02:53 +00:00
query :
2022-04-20 18:12:53 +00:00
"SELECT uid, gid, username, description,directory, shell FROM users;" ,
description :
"Local user accounts (including domain accounts that have logged on locally (Windows))." ,
2021-08-30 23:02:53 +00:00
observer_can_run : false ,
} ,
2021-06-11 21:27:19 +00:00
] ;
queries . forEach ( ( queryForm ) = > {
const { name , query , description , observer_can_run } = queryForm ;
cy . request ( {
2022-04-11 20:04:38 +00:00
url : "/api/latest/fleet/queries" ,
2021-06-11 21:27:19 +00:00
method : "POST" ,
body : { name , query , description , observer_can_run } ,
auth : {
bearer : window.localStorage.getItem ( "FLEET::auth_token" ) ,
} ,
} ) ;
} ) ;
} ) ;
2022-02-10 23:49:10 +00:00
Cypress . Commands . add ( "seedSchedule" , ( ) = > {
const scheduledQueries = [
{
interval : 86400 ,
platform : "" ,
query_id : 1 ,
removed : false ,
shard : null ,
snapshot : true ,
version : "" ,
} ,
{
interval : 604800 ,
platform : "linux" ,
query_id : 2 ,
removed : true ,
shard : 50 ,
snapshot : false ,
version : "4.6.0" ,
} ,
] ;
scheduledQueries . forEach ( ( scheduleForm ) = > {
const {
interval ,
platform ,
query_id ,
removed ,
shard ,
snapshot ,
version ,
} = scheduleForm ;
cy . request ( {
2022-04-11 20:04:38 +00:00
url : "/api/latest/fleet/schedule" ,
2022-02-10 23:49:10 +00:00
method : "POST" ,
body : { interval , platform , query_id , removed , shard , snapshot , version } ,
auth : {
bearer : window.localStorage.getItem ( "FLEET::auth_token" ) ,
} ,
} ) ;
} ) ;
} ) ;
2022-05-18 17:03:00 +00:00
// @ts-ignore
2022-01-28 16:48:51 +00:00
Cypress . Commands . add ( "seedPacks" , ( ) = > {
const packs = [
{
name : "Mac starter pack" ,
description : "Run all queries weekly on Mac hosts" ,
} ,
{
name : "Windows starter pack" ,
description : "Run all queries weekly on Windows hosts" ,
} ,
] ;
packs . forEach ( ( packForm ) = > {
const { name , description } = packForm ;
cy . request ( {
2022-04-11 20:04:38 +00:00
url : "/api/latest/fleet/packs" ,
2022-01-28 16:48:51 +00:00
method : "POST" ,
body : { name , description , host_ids : [ ] , label_ids : [ ] , team_ids : [ ] } ,
auth : {
bearer : window.localStorage.getItem ( "FLEET::auth_token" ) ,
} ,
} ) ;
} ) ;
} ) ;
2021-12-22 18:06:52 +00:00
Cypress . Commands . add ( "seedPolicies" , ( team = "" ) = > {
const policies = [
{
name : "Is Filevault enabled on macOS devices?" ,
query :
"SELECT 1 FROM disk_encryption WHERE user_uuid IS NOT '' AND filevault_status = 'on' LIMIT 1" ,
description :
"Checks to make sure that the Filevault feature is enabled on macOS devices." ,
resolution :
"Choose Apple menu > System Preferences, then click Security & Privacy. Click the FileVault tab. Click the Lock icon, then enter an administrator name and password. Click Turn On FileVault." ,
2022-03-21 16:51:00 +00:00
platform : "darwin,linux" ,
2021-12-22 18:06:52 +00:00
} ,
{
name : "Is Ubuntu, version 20.4.0 installed?" ,
query :
"SELECT 1 from os_version WHERE name = 'Ubuntu' AND major || '.' || minor || '.' || patch = '20.4.0';" ,
description :
"Returns yes or no for detecting operating system and version" ,
resolution : "Update OS if needed" ,
2022-03-21 16:51:00 +00:00
platform : "darwin,windows,linux" ,
2021-12-22 18:06:52 +00:00
} ,
2022-03-24 15:47:43 +00:00
{
name : "Is Ubuntu, version 16.4.0 or later, installed?" ,
query :
"SELECT 1 from os_version WHERE name = 'Ubuntu' AND major || '.' || minor || '.' || patch >= '16.4.0';" ,
description :
"Returns yes or no for detecting operating system and version" ,
resolution : "Update OS if needed" ,
platform : "" ,
} ,
2021-12-22 18:06:52 +00:00
] ;
if ( team === "apples" ) {
policies . forEach ( ( policyForm ) = > {
cy . request ( {
2022-04-11 20:04:38 +00:00
url : "/api/latest/fleet/teams/1/policies" ,
2021-12-22 18:06:52 +00:00
method : "POST" ,
2022-03-21 16:51:00 +00:00
body : { . . . policyForm } ,
2021-12-22 18:06:52 +00:00
auth : {
bearer : window.localStorage.getItem ( "FLEET::auth_token" ) ,
} ,
} ) ;
} ) ;
} else {
policies . forEach ( ( policyForm ) = > {
cy . request ( {
2022-04-11 20:04:38 +00:00
url : "/api/latest/fleet/policies" ,
2021-12-22 18:06:52 +00:00
method : "POST" ,
2022-03-21 16:51:00 +00:00
body : { . . . policyForm } ,
2021-12-22 18:06:52 +00:00
auth : {
bearer : window.localStorage.getItem ( "FLEET::auth_token" ) ,
} ,
} ) ;
} ) ;
}
} ) ;
2021-04-30 15:47:33 +00:00
Cypress . Commands . add ( "setupSMTP" , ( ) = > {
const body = {
smtp_settings : {
authentication_type : "authtype_none" ,
enable_smtp : true ,
port : 1025 ,
2021-05-31 17:56:50 +00:00
sender_address : "fleet@example.com" ,
2021-04-14 16:52:15 +00:00
server : "localhost" ,
2021-03-30 19:56:20 +00:00
} ,
} ;
cy . request ( {
2022-04-11 20:04:38 +00:00
url : "/api/latest/fleet/config" ,
2021-04-14 16:52:15 +00:00
method : "PATCH" ,
2021-03-30 19:56:20 +00:00
body ,
auth : {
2021-06-07 01:28:37 +00:00
bearer : window.localStorage.getItem ( "FLEET::auth_token" ) ,
2021-03-30 19:56:20 +00:00
} ,
} ) ;
} ) ;
2021-04-12 13:32:25 +00:00
Cypress . Commands . add ( "setupSSO" , ( enable_idp_login = false ) = > {
2021-04-05 18:01:30 +00:00
const body = {
sso_settings : {
enable_sso : true ,
enable_sso_idp_login : enable_idp_login ,
2021-04-12 13:32:25 +00:00
entity_id : "https://localhost:8080" ,
idp_name : "SimpleSAML" ,
issuer_uri : "http://localhost:8080/simplesaml/saml2/idp/SSOService.php" ,
metadata_url : "http://localhost:9080/simplesaml/saml2/idp/metadata.php" ,
2021-04-05 18:01:30 +00:00
} ,
} ;
cy . request ( {
2022-04-11 20:04:38 +00:00
url : "/api/latest/fleet/config" ,
2021-04-12 13:32:25 +00:00
method : "PATCH" ,
2021-04-05 18:01:30 +00:00
body ,
auth : {
2021-06-07 01:28:37 +00:00
bearer : window.localStorage.getItem ( "FLEET::auth_token" ) ,
2021-04-05 18:01:30 +00:00
} ,
} ) ;
} ) ;
2021-04-12 13:32:25 +00:00
Cypress . Commands . add ( "loginSSO" , ( ) = > {
2021-04-05 18:01:30 +00:00
// Note these requests set cookies that are required for the SSO flow to
// work properly. This is handled automatically by the browser.
cy . request ( {
2021-04-12 13:32:25 +00:00
method : "GET" ,
url :
"http://localhost:9080/simplesaml/saml2/idp/SSOService.php?spentityid=https://localhost:8080" ,
2021-04-05 18:01:30 +00:00
followRedirect : false ,
} ) . then ( ( firstResponse ) = > {
2021-10-12 21:33:56 +00:00
const redirect = firstResponse . headers . location as string ;
2021-04-05 18:01:30 +00:00
cy . request ( {
2021-04-12 13:32:25 +00:00
method : "GET" ,
2021-04-05 18:01:30 +00:00
url : redirect ,
followRedirect : false ,
} ) . then ( ( secondResponse ) = > {
2021-04-12 13:32:25 +00:00
const el = document . createElement ( "html" ) ;
2021-04-05 18:01:30 +00:00
el . innerHTML = secondResponse . body ;
2021-04-12 13:32:25 +00:00
const authState = el . getElementsByTagName ( "input" ) . namedItem ( "AuthState" )
. defaultValue ;
2021-04-05 18:01:30 +00:00
cy . request ( {
2021-04-12 13:32:25 +00:00
method : "POST" ,
2021-04-05 18:01:30 +00:00
url : redirect ,
2021-06-09 18:56:59 +00:00
body : ` username=sso_user&password=user123#&AuthState= ${ authState } ` ,
2021-04-05 18:01:30 +00:00
form : true ,
followRedirect : false ,
} ) . then ( ( finalResponse ) = > {
el . innerHTML = finalResponse . body ;
2021-04-12 13:32:25 +00:00
const saml = el . getElementsByTagName ( "input" ) . namedItem ( "SAMLResponse" )
. defaultValue ;
2021-04-05 18:01:30 +00:00
// Load the callback URL with the response from the IdP
cy . visit ( {
2022-04-20 16:46:45 +00:00
url : "/api/v1/fleet/sso/callback" ,
2021-04-12 13:32:25 +00:00
method : "POST" ,
2021-04-05 18:01:30 +00:00
body : {
SAMLResponse : saml ,
} ,
} ) ;
} ) ;
2021-03-30 19:56:20 +00:00
} ) ;
2021-04-05 18:01:30 +00:00
} ) ;
2021-03-30 19:56:20 +00:00
} ) ;
2021-04-29 17:10:25 +00:00
Cypress . Commands . add ( "getEmails" , ( ) = > {
return cy
. request ( "http://localhost:8025/api/v2/messages" )
. then ( ( response ) = > {
expect ( response . status ) . to . eq ( 200 ) ;
return response ;
} ) ;
} ) ;
2021-06-09 18:56:59 +00:00
2021-09-03 16:05:23 +00:00
Cypress . Commands . add ( "seedFree" , ( ) = > {
2021-06-09 18:56:59 +00:00
const authToken = window . localStorage . getItem ( "FLEET::auth_token" ) ;
2021-09-03 16:05:23 +00:00
cy . exec ( "bash ./tools/api/fleet/teams/create_free" , {
2021-06-09 18:56:59 +00:00
env : {
TOKEN : authToken ,
CURL_FLAGS : "-k" ,
SERVER_URL : Cypress.config ( ) . baseUrl ,
// clear any value for FLEET_ENV_PATH since we set the environment explicitly just above
FLEET_ENV_PATH : "" ,
2021-10-12 21:33:56 +00:00
SHELL ,
2021-06-09 18:56:59 +00:00
} ,
} ) ;
} ) ;
2021-09-03 16:05:23 +00:00
Cypress . Commands . add ( "seedPremium" , ( ) = > {
2021-06-09 18:56:59 +00:00
const authToken = window . localStorage . getItem ( "FLEET::auth_token" ) ;
2021-09-03 16:05:23 +00:00
cy . exec ( "bash ./tools/api/fleet/teams/create_premium" , {
2021-06-09 18:56:59 +00:00
env : {
TOKEN : authToken ,
CURL_FLAGS : "-k" ,
SERVER_URL : Cypress.config ( ) . baseUrl ,
// clear any value for FLEET_ENV_PATH since we set the environment explicitly just above
FLEET_ENV_PATH : "" ,
2021-10-12 21:33:56 +00:00
SHELL ,
2021-06-09 18:56:59 +00:00
} ,
} ) ;
} ) ;
Cypress . Commands . add ( "seedFigma" , ( ) = > {
const authToken = window . localStorage . getItem ( "FLEET::auth_token" ) ;
cy . exec ( "bash ./tools/api/fleet/teams/create_figma" , {
env : {
TOKEN : authToken ,
CURL_FLAGS : "-k" ,
SERVER_URL : Cypress.config ( ) . baseUrl ,
// clear any value for FLEET_ENV_PATH since we set the environment explicitly just above
FLEET_ENV_PATH : "" ,
2021-10-12 21:33:56 +00:00
SHELL ,
2021-06-09 18:56:59 +00:00
} ,
} ) ;
} ) ;
2021-06-24 20:42:29 +00:00
Cypress . Commands . add ( "addUser" , ( options = { } ) = > {
2021-06-09 18:56:59 +00:00
let { password , email , globalRole } = options ;
2022-05-18 17:03:00 +00:00
password || = GOOD_PASSWORD ;
2021-06-24 20:42:29 +00:00
email || = ` admin@example.com ` ;
2021-06-09 18:56:59 +00:00
globalRole || = "admin" ;
cy . exec (
2021-06-24 20:42:29 +00:00
` ./build/fleetctl user create --context e2e --password " ${ password } " --email " ${ email } " --global-role " ${ globalRole } " ` ,
2021-10-12 21:33:56 +00:00
{
timeout : 5000 ,
env : { SHELL } ,
}
2021-06-09 18:56:59 +00:00
) ;
} ) ;
2021-06-15 17:14:57 +00:00
2021-09-03 16:05:23 +00:00
// Ability to add a docker host to a team using args if ran after seedPremium()
2021-06-17 14:09:12 +00:00
Cypress . Commands . add ( "addDockerHost" , ( team = "" ) = > {
2021-06-15 17:14:57 +00:00
const serverPort = new URL ( Cypress . config ( ) . baseUrl ) . port ;
// Get enroll secret
2022-04-11 20:04:38 +00:00
let enrollSecretURL = "/api/latest/fleet/spec/enroll_secret" ;
2021-06-17 14:09:12 +00:00
if ( team === "apples" ) {
2022-04-11 20:04:38 +00:00
enrollSecretURL = "/api/latest/fleet/teams/1/secrets" ;
2021-06-17 14:09:12 +00:00
} else if ( team === "oranges" ) {
2022-04-11 20:04:38 +00:00
enrollSecretURL = "/api/latest/fleet/teams/2/secrets" ;
2021-06-17 14:09:12 +00:00
}
2021-06-15 17:14:57 +00:00
cy . request ( {
2021-06-17 14:09:12 +00:00
url : enrollSecretURL ,
2021-06-15 17:14:57 +00:00
auth : {
bearer : window.localStorage.getItem ( "FLEET::auth_token" ) ,
} ,
} ) . then ( ( { body } ) = > {
2021-06-17 14:09:12 +00:00
const enrollSecret =
2021-06-29 17:58:15 +00:00
team === "" ? body . spec . secrets [ 0 ] . secret : body.secrets [ 0 ] . secret ;
2021-06-15 17:14:57 +00:00
// Start up docker-compose with enroll secret
cy . exec (
"docker-compose -f tools/osquery/docker-compose.yml up -d ubuntu20-osquery" ,
{
env : {
ENROLL_SECRET : enrollSecret ,
FLEET_SERVER : ` host.docker.internal: ${ serverPort } ` ,
2021-10-12 21:33:56 +00:00
SHELL ,
2021-06-15 17:14:57 +00:00
} ,
}
) ;
} ) ;
} ) ;
Cypress . Commands . add ( "stopDockerHost" , ( ) = > {
// Start up docker-compose with enroll secret
cy . exec ( "docker-compose -f tools/osquery/docker-compose.yml stop" , {
env : {
// Not that ENROLL_SECRET must be specified or docker-compose errors,
// even when just trying to shut down the hosts.
ENROLL_SECRET : "invalid" ,
2021-10-12 21:33:56 +00:00
SHELL ,
2021-06-15 17:14:57 +00:00
} ,
} ) ;
} ) ;
2021-09-17 17:04:51 +00:00
Cypress . Commands . add ( "clearDownloads" , ( ) = > {
2021-10-12 21:33:56 +00:00
// windows has issue with downloads location
if ( Cypress . platform !== "win32" ) {
cy . exec ( ` rm -rf ${ Cypress . config ( "downloadsFolder" ) } ` , { env : { SHELL } } ) ;
}
2021-09-17 17:04:51 +00:00
} ) ;
2021-12-20 17:36:17 +00:00
Cypress . Commands . add ( "getAttached" , ( selector ) = > {
const uniqueAlias = ` element_ ${ selector } ` ;
return cy
. waitUntil (
( ) = >
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy
. get ( selector )
. as ( uniqueAlias )
. wait ( 1 )
. then ( ( $el ) = > Cypress . dom . isAttached ( $el ) ) ,
{ timeout : 1000 , interval : 10 }
)
. get ( ` @ ${ uniqueAlias } ` ) ;
} ) ;