Only allow FLEET_DEV_* env vars when --dev is passed, allow overriding configs one at a time in dev (#38652)
Resolves #38484. This includes a CI job change to make sure we don't introduce any more env vars that don't get proxied (and thus turned off outside `--dev`). # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements) ## Testing - [x] Added/updated automated tests Manual QA touched hot paths, but did _not_ manually test every FLEET_DEV_* environment variable change. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Centralized dev-mode environment management for consistent FLEET_DEV_* handling and test-friendly overrides. * Dev-mode allows targeted overrides for certain dev-only configuration when running with --dev. * **Chores** * Migrated environment access to the centralized dev-mode helper across the codebase. * Added CI checks to enforce proper usage of FLEET_DEV_* variables. * **Documentation** * Added guidance on dev-mode environment variable rules and overrides. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Victor Lyuboslavsky <2685025+getvictor@users.noreply.github.com>
This commit is contained in:
co-authored by
Victor Lyuboslavsky
parent
89c35709ef
commit
2f25580c3a
@@ -78,6 +78,24 @@ jobs:
|
||||
run: |
|
||||
go run ./tools/cloner-check/main.go -check
|
||||
|
||||
- name: Ensure all FLEET_DEV_* env var accesses are proxied
|
||||
run: |
|
||||
if grep -R 'os.Getenv("FLEET_DEV' --include="*.go" .; then
|
||||
echo "Error: Found unproxied FLEET_DEV_* env var access. Please proxy via dev_mode.Env()." >&2
|
||||
exit 1
|
||||
else
|
||||
echo "OK: No unproxied FLEET_DEV_* env var accesses found."
|
||||
fi
|
||||
|
||||
- name: Restrict FLEET_DEV_* env var overrides to test code only
|
||||
run: |
|
||||
if grep -R 'SetOverride("FLEET_DEV' --include="*.go" --exclude="*_test.go" --exclude="testing_utils.go" --exclude-dir="mdmtest" .; then
|
||||
echo "Error: Found FLEET_DEV_* overrides in non-test code." >&2
|
||||
exit 1
|
||||
else
|
||||
echo "OK: No FLEET_DEV_* overrides in non-test code."
|
||||
fi
|
||||
|
||||
golangci-incremental:
|
||||
# Only run on pull requests (needs base branch for incremental comparison)
|
||||
if: github.event_name == 'pull_request'
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
* Disallowed use of FLEET_DEV_* environment variables unless `--dev` is passed when serving Fleet.
|
||||
* Allowed overriding individual configuration variables for MySQL and object storage when `--dev` is passed when serving Fleet.
|
||||
+2
-1
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/license"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/viewer"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/mysql"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/android"
|
||||
@@ -1452,7 +1453,7 @@ func newMDMAPNsPusher(
|
||||
const name = string(fleet.CronAppleMDMAPNsPusher)
|
||||
|
||||
interval := 1 * time.Minute
|
||||
if intervalEnv := os.Getenv("FLEET_DEV_CUSTOM_APNS_PUSHER_INTERVAL"); intervalEnv != "" {
|
||||
if intervalEnv := dev_mode.Env("FLEET_DEV_CUSTOM_APNS_PUSHER_INTERVAL"); intervalEnv != "" {
|
||||
var err error
|
||||
interval, err = time.ParseDuration(intervalEnv)
|
||||
if err != nil {
|
||||
|
||||
+28
-25
@@ -93,37 +93,40 @@ wish to override the default value.
|
||||
}
|
||||
|
||||
func applyDevFlags(cfg *config.FleetConfig) {
|
||||
cfg.Mysql.Username = "fleet"
|
||||
cfg.Mysql.Database = "fleet"
|
||||
cfg.Mysql.Password = "insecure"
|
||||
|
||||
if cfg.Prometheus.BasicAuth.Username == "" {
|
||||
cfg.Prometheus.BasicAuth.Username = "fleet"
|
||||
}
|
||||
if cfg.Prometheus.BasicAuth.Password == "" {
|
||||
cfg.Prometheus.BasicAuth.Password = "insecure"
|
||||
// set database and object storage configs to work with local docker-compose setup if a given value is missing
|
||||
setIfEmpty := func(target *string, value string) {
|
||||
if *target == "" {
|
||||
*target = value
|
||||
}
|
||||
}
|
||||
|
||||
// Allow the carves bucket to be overridden in dev mode
|
||||
if cfg.S3.CarvesBucket == "" {
|
||||
cfg.S3.CarvesBucket = "carves-dev"
|
||||
cfg.S3.CarvesRegion = "localhost"
|
||||
cfg.S3.CarvesPrefix = "dev-prefix"
|
||||
cfg.S3.CarvesEndpointURL = "http://localhost:9000"
|
||||
cfg.S3.CarvesAccessKeyID = "locals3"
|
||||
cfg.S3.CarvesSecretAccessKey = "locals3"
|
||||
setIfEmpty(&cfg.Mysql.Username, "fleet")
|
||||
setIfEmpty(&cfg.Mysql.Database, "fleet")
|
||||
setIfEmpty(&cfg.Mysql.Password, "insecure")
|
||||
|
||||
setIfEmpty(&cfg.Prometheus.BasicAuth.Username, "fleet")
|
||||
setIfEmpty(&cfg.Prometheus.BasicAuth.Password, "insecure")
|
||||
|
||||
setIfEmpty(&cfg.S3.CarvesBucket, "carves-dev")
|
||||
setIfEmpty(&cfg.S3.CarvesRegion, "localhost")
|
||||
setIfEmpty(&cfg.S3.CarvesPrefix, "dev-prefix")
|
||||
setIfEmpty(&cfg.S3.CarvesEndpointURL, "http://localhost:9000")
|
||||
setIfEmpty(&cfg.S3.CarvesAccessKeyID, "locals3")
|
||||
setIfEmpty(&cfg.S3.CarvesSecretAccessKey, "locals3")
|
||||
if cfg.S3.CarvesAccessKeyID == "locals3" && cfg.S3.CarvesSecretAccessKey == "locals3" {
|
||||
// can't rely on zero values
|
||||
cfg.S3.CarvesDisableSSL = true
|
||||
cfg.S3.CarvesForceS3PathStyle = true
|
||||
}
|
||||
|
||||
// Allow the software installers bucket to be overridden in dev mode
|
||||
if cfg.S3.SoftwareInstallersBucket == "" {
|
||||
cfg.S3.SoftwareInstallersBucket = "software-installers-dev"
|
||||
cfg.S3.SoftwareInstallersRegion = "localhost"
|
||||
cfg.S3.SoftwareInstallersPrefix = "dev-prefix"
|
||||
cfg.S3.SoftwareInstallersEndpointURL = "http://localhost:9000"
|
||||
cfg.S3.SoftwareInstallersAccessKeyID = "locals3"
|
||||
cfg.S3.SoftwareInstallersSecretAccessKey = "locals3"
|
||||
setIfEmpty(&cfg.S3.SoftwareInstallersBucket, "software-installers-dev")
|
||||
setIfEmpty(&cfg.S3.SoftwareInstallersRegion, "localhost")
|
||||
setIfEmpty(&cfg.S3.SoftwareInstallersPrefix, "dev-prefix")
|
||||
setIfEmpty(&cfg.S3.SoftwareInstallersEndpointURL, "http://localhost:9000")
|
||||
setIfEmpty(&cfg.S3.SoftwareInstallersAccessKeyID, "locals3")
|
||||
setIfEmpty(&cfg.S3.SoftwareInstallersSecretAccessKey, "locals3")
|
||||
if cfg.S3.SoftwareInstallersAccessKeyID == "locals3" && cfg.S3.SoftwareInstallersSecretAccessKey == "locals3" {
|
||||
// can't rely on zero values
|
||||
cfg.S3.SoftwareInstallersDisableSSL = true
|
||||
cfg.S3.SoftwareInstallersForceS3PathStyle = true
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/WatchBeam/clock"
|
||||
"github.com/fleetdm/fleet/v4/server/config"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/mysql"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -28,8 +29,6 @@ To setup Fleet infrastructure, use one of the available commands.
|
||||
}
|
||||
|
||||
noPrompt := false
|
||||
// Whether to enable developer options
|
||||
dev := false
|
||||
// Whether to show table stats before and after the migration
|
||||
showTableStats := false
|
||||
|
||||
@@ -40,7 +39,7 @@ To setup Fleet infrastructure, use one of the available commands.
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
config := configManager.LoadConfig()
|
||||
|
||||
if dev {
|
||||
if dev_mode.IsEnabled {
|
||||
applyDevFlags(&config)
|
||||
noPrompt = true
|
||||
}
|
||||
@@ -100,7 +99,7 @@ To setup Fleet infrastructure, use one of the available commands.
|
||||
printFleetv4732UnknownStateMessage(status.StatusCode)
|
||||
case fleet.UnknownMigrations:
|
||||
printUnknownMigrationsMessage(status.UnknownTable, status.UnknownData)
|
||||
if dev {
|
||||
if dev_mode.IsEnabled {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -118,7 +117,7 @@ To setup Fleet infrastructure, use one of the available commands.
|
||||
}
|
||||
|
||||
dbCmd.PersistentFlags().BoolVar(&noPrompt, "no-prompt", false, "disable prompting before migrations (for use in scripts)")
|
||||
dbCmd.PersistentFlags().BoolVar(&dev, "dev", false, "Enable developer options")
|
||||
dbCmd.PersistentFlags().BoolVar(&dev_mode.IsEnabled, "dev", false, "Enable developer options")
|
||||
dbCmd.PersistentFlags().BoolVar(&showTableStats, "with-table-stats", false, "Show approximate table row counts after migrations")
|
||||
|
||||
prepareCmd.AddCommand(dbCmd)
|
||||
|
||||
+7
-8
@@ -48,6 +48,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/mysqlredis"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/redis"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/s3"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/errorstore"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/health"
|
||||
@@ -119,8 +120,6 @@ type initializer interface {
|
||||
func createServeCmd(configManager configpkg.Manager) *cobra.Command {
|
||||
// Whether to enable the debug endpoints
|
||||
debug := false
|
||||
// Whether to enable developer options
|
||||
dev := false
|
||||
// Whether to enable development Fleet Premium license
|
||||
devLicense := false
|
||||
// Whether to enable development Fleet Premium license with an expired license
|
||||
@@ -140,7 +139,7 @@ the way that the Fleet server works.
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
config := configManager.LoadConfig()
|
||||
|
||||
if dev {
|
||||
if dev_mode.IsEnabled {
|
||||
applyDevFlags(&config)
|
||||
}
|
||||
|
||||
@@ -158,7 +157,7 @@ the way that the Fleet server works.
|
||||
|
||||
logger := initLogger(config)
|
||||
|
||||
if dev {
|
||||
if dev_mode.IsEnabled {
|
||||
createTestBuckets(&config, logger)
|
||||
}
|
||||
|
||||
@@ -276,7 +275,7 @@ the way that the Fleet server works.
|
||||
opts = append(opts, mysql.Replica(&config.MysqlReadReplica))
|
||||
}
|
||||
// NOTE this will disable OTEL/APM interceptor
|
||||
if dev && os.Getenv("FLEET_DEV_ENABLE_SQL_INTERCEPTOR") != "" {
|
||||
if dev_mode.Env("FLEET_DEV_ENABLE_SQL_INTERCEPTOR") != "" {
|
||||
opts = append(opts, mysql.WithInterceptor(&devSQLInterceptor{
|
||||
logger: kitlog.With(logger, "component", "sql-interceptor"),
|
||||
}))
|
||||
@@ -317,7 +316,7 @@ the way that the Fleet server works.
|
||||
// OK
|
||||
case fleet.UnknownMigrations:
|
||||
printUnknownMigrationsMessage(migrationStatus.UnknownTable, migrationStatus.UnknownData)
|
||||
if dev {
|
||||
if dev_mode.IsEnabled {
|
||||
os.Exit(1)
|
||||
}
|
||||
case fleet.NeedsFleetv4732Fix:
|
||||
@@ -563,7 +562,7 @@ the way that the Fleet server works.
|
||||
Certificates: []tls.Certificate{*cert},
|
||||
})), nil
|
||||
}))
|
||||
if os.Getenv("FLEET_DEV_MDM_APPLE_DISABLE_PUSH") == "1" {
|
||||
if dev_mode.Env("FLEET_DEV_MDM_APPLE_DISABLE_PUSH") == "1" {
|
||||
mdmPushService = nopPusher{}
|
||||
} else {
|
||||
mdmPushService = nanomdm_pushsvc.New(mdmStorage, mdmStorage, pushProviderFactory, nanoMDMLogger)
|
||||
@@ -1710,7 +1709,7 @@ the way that the Fleet server works.
|
||||
}
|
||||
|
||||
serveCmd.PersistentFlags().BoolVar(&debug, "debug", false, "Enable debug endpoints")
|
||||
serveCmd.PersistentFlags().BoolVar(&dev, "dev", false, "Enable developer options")
|
||||
serveCmd.PersistentFlags().BoolVar(&dev_mode.IsEnabled, "dev", false, "Enable developer options")
|
||||
serveCmd.PersistentFlags().BoolVar(&devLicense, "dev_license", false, "Enable development license")
|
||||
serveCmd.PersistentFlags().BoolVar(&devExpiredLicense, "dev_expired_license", false, "Enable expired development license")
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/license"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
|
||||
"github.com/WatchBeam/clock"
|
||||
"github.com/fleetdm/fleet/v4/server/config"
|
||||
@@ -19,7 +20,6 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
dev bool
|
||||
devLicense bool
|
||||
devExpiredLicense bool
|
||||
lockDuration time.Duration
|
||||
@@ -36,7 +36,7 @@ will disable it on the server allowing the user configure their own 'cron' mecha
|
||||
by an exit code of zero.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
cfg := configManager.LoadConfig()
|
||||
if dev {
|
||||
if dev_mode.IsEnabled {
|
||||
applyDevFlags(&cfg)
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ by an exit code of zero.`,
|
||||
return
|
||||
},
|
||||
}
|
||||
vulnProcessingCmd.PersistentFlags().BoolVar(&dev, "dev", false, "Enable developer options")
|
||||
vulnProcessingCmd.PersistentFlags().BoolVar(&dev_mode.IsEnabled, "dev", false, "Enable developer options")
|
||||
vulnProcessingCmd.PersistentFlags().BoolVar(&devLicense, "dev_license", false, "Enable development license")
|
||||
vulnProcessingCmd.PersistentFlags().BoolVar(&devExpiredLicense, "dev_expired_license", false, "Enable expired development license")
|
||||
vulnProcessingCmd.PersistentFlags().DurationVar(
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/pkg/optjson"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/ptr"
|
||||
"github.com/ghodss/yaml"
|
||||
@@ -785,8 +786,7 @@ func configureFMAManifestServer(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
t.Cleanup(manifestServer.Close)
|
||||
os.Setenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL", manifestServer.URL)
|
||||
t.Cleanup(func() { os.Unsetenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL") })
|
||||
dev_mode.SetOverride("FLEET_DEV_MAINTAINED_APPS_BASE_URL", manifestServer.URL, t)
|
||||
}
|
||||
|
||||
func TestGenerateGitops(t *testing.T) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/config"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/cached_mysql"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/mysql"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
apple_mdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/apple/vpp"
|
||||
@@ -643,7 +644,7 @@ func StartVPPApplyServer(t *testing.T, config *AppleVPPConfigSrvConf) {
|
||||
_, _ = w.Write(resp)
|
||||
}))
|
||||
|
||||
t.Setenv("FLEET_DEV_VPP_URL", srv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", srv.URL, t)
|
||||
t.Cleanup(srv.Close)
|
||||
}
|
||||
|
||||
@@ -748,8 +749,8 @@ func StartAndServeVPPServer(t *testing.T) {
|
||||
|
||||
t.Cleanup(vppProxySrv.Close)
|
||||
t.Cleanup(vppProxyAuthSrv.Close)
|
||||
t.Setenv("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL", vppProxySrv.URL)
|
||||
t.Setenv("FLEET_DEV_VPP_PROXY_AUTH_URL", vppProxyAuthSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL", vppProxySrv.URL, t)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_PROXY_AUTH_URL", vppProxyAuthSrv.URL, t)
|
||||
}
|
||||
|
||||
type MockPusher struct{}
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/filesystem"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/mysql"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/redis/redistest"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
appleMdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/nanodep/tokenpki"
|
||||
@@ -2495,8 +2496,7 @@ team_settings:
|
||||
}))
|
||||
|
||||
t.Cleanup(manifestServer.Close)
|
||||
os.Setenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL", manifestServer.URL)
|
||||
defer os.Unsetenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL")
|
||||
dev_mode.SetOverride("FLEET_DEV_MAINTAINED_APPS_BASE_URL", manifestServer.URL, t)
|
||||
|
||||
mysql.ExecAdhocSQL(t, s.DS, func(q sqlx.ExtContext) error {
|
||||
_, err := q.ExecContext(ctx, `INSERT INTO fleet_maintained_apps (name, slug, platform, unique_identifier)
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/crewjam/saml"
|
||||
"github.com/fleetdm/fleet/v4/server/config"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/service/middleware/log"
|
||||
"github.com/fleetdm/fleet/v4/server/service/middleware/otel"
|
||||
@@ -591,7 +592,7 @@ func (s *idpService) buildSSOServerURL(ctx context.Context) (string, error) {
|
||||
}
|
||||
|
||||
// Use the AppConfig method to build the SSO URL
|
||||
ssoURL, err := appConfig.ConditionalAccessIdPSSOURL(os.Getenv)
|
||||
ssoURL, err := appConfig.ConditionalAccessIdPSSOURL(dev_mode.Env)
|
||||
if err != nil {
|
||||
return "", ctxerr.Wrap(ctx, err, "build conditional access SSO URL")
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -21,6 +20,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/ee/server/service/hostidentity/types"
|
||||
"github.com/fleetdm/fleet/v4/server/config"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/assets"
|
||||
scepdepot "github.com/fleetdm/fleet/v4/server/mdm/scep/depot"
|
||||
@@ -54,7 +54,7 @@ func (e *RateLimitError) StatusCode() int { return http.StatusTooManyRequests }
|
||||
// It checks for FLEET_DEV_HOST_IDENTITY_CERT_VALIDITY_DAYS environment variable
|
||||
// and falls back to scepValidityDays if not set or invalid.
|
||||
func getCertValidityDays() int {
|
||||
if envValue := os.Getenv("FLEET_DEV_HOST_IDENTITY_CERT_VALIDITY_DAYS"); envValue != "" {
|
||||
if envValue := dev_mode.Env("FLEET_DEV_HOST_IDENTITY_CERT_VALIDITY_DAYS"); envValue != "" {
|
||||
if days, err := strconv.Atoi(envValue); err == nil && days > 0 {
|
||||
return days
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -14,6 +13,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/authz"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/viewer"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
maintained_apps "github.com/fleetdm/fleet/v4/server/mdm/maintainedapps"
|
||||
"github.com/go-kit/kit/log/level"
|
||||
@@ -71,7 +71,7 @@ func (svc *Service) AddFleetMaintainedApp(
|
||||
|
||||
// Download installer from the URL
|
||||
timeout := maintained_apps.InstallerTimeout
|
||||
if v := os.Getenv("FLEET_DEV_MAINTAINED_APPS_INSTALLER_TIMEOUT"); v != "" {
|
||||
if v := dev_mode.Env("FLEET_DEV_MAINTAINED_APPS_INSTALLER_TIMEOUT"); v != "" {
|
||||
timeout, _ = time.ParseDuration(v)
|
||||
}
|
||||
client := fleethttp.NewClient(fleethttp.WithTimeout(timeout))
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/authz"
|
||||
authz_ctx "github.com/fleetdm/fleet/v4/server/contexts/authz"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/viewer"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/mock"
|
||||
"github.com/fleetdm/fleet/v4/server/ptr"
|
||||
@@ -226,8 +227,7 @@ func TestGetMaintainedAppAuth(t *testing.T) {
|
||||
}
|
||||
|
||||
var forbiddenError *authz.Forbidden
|
||||
require.NoError(t, os.Setenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL", srv.URL))
|
||||
defer os.Unsetenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL")
|
||||
dev_mode.SetOverride("FLEET_DEV_MAINTAINED_APPS_BASE_URL", srv.URL, t)
|
||||
for _, tt := range testCases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx := viewer.NewContext(context.Background(), viewer.Viewer{User: tt.user})
|
||||
@@ -330,8 +330,7 @@ func TestAddFleetMaintainedApp(t *testing.T) {
|
||||
}))
|
||||
|
||||
t.Cleanup(manifestServer.Close)
|
||||
os.Setenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL", manifestServer.URL)
|
||||
defer os.Unsetenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL")
|
||||
dev_mode.SetOverride("FLEET_DEV_MAINTAINED_APPS_BASE_URL", manifestServer.URL, t)
|
||||
|
||||
svc := newTestService(t, ds)
|
||||
|
||||
@@ -411,8 +410,7 @@ func TestExtractMaintainedAppVersionWhenLatest(t *testing.T) {
|
||||
}))
|
||||
|
||||
t.Cleanup(manifestServer.Close)
|
||||
os.Setenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL", manifestServer.URL)
|
||||
defer os.Unsetenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL")
|
||||
dev_mode.SetOverride("FLEET_DEV_MAINTAINED_APPS_BASE_URL", manifestServer.URL, t)
|
||||
|
||||
svc := newTestService(t, ds)
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/config"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/viewer"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/s3"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/mdm"
|
||||
"github.com/fleetdm/fleet/v4/server/mock"
|
||||
@@ -247,7 +248,6 @@ func TestInstallSoftwareTitle(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSoftwareInstallerPayloadFromSlug(t *testing.T) {
|
||||
t.Parallel()
|
||||
ds := new(mock.Store)
|
||||
svc := newTestService(t, ds)
|
||||
|
||||
@@ -296,8 +296,7 @@ func TestSoftwareInstallerPayloadFromSlug(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
t.Cleanup(manifestServer.Close)
|
||||
os.Setenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL", manifestServer.URL)
|
||||
defer os.Unsetenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL")
|
||||
dev_mode.SetOverride("FLEET_DEV_MAINTAINED_APPS_BASE_URL", manifestServer.URL, t)
|
||||
|
||||
ds.GetMaintainedAppBySlugFunc = func(ctx context.Context, slug string, teamID *uint) (*fleet.MaintainedApp, error) {
|
||||
return &fleet.MaintainedApp{
|
||||
|
||||
@@ -6,7 +6,8 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
)
|
||||
|
||||
type Metadata struct {
|
||||
@@ -19,7 +20,7 @@ type Metadata struct {
|
||||
}
|
||||
|
||||
func getBaseURL() string {
|
||||
devURL := os.Getenv("FLEET_DEV_DOWNLOAD_FLEETDM_URL")
|
||||
devURL := dev_mode.Env("FLEET_DEV_DOWNLOAD_FLEETDM_URL")
|
||||
if devURL != "" {
|
||||
return devURL
|
||||
}
|
||||
|
||||
@@ -6,12 +6,13 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetBaseURL(t *testing.T) {
|
||||
t.Run("with env variable", func(t *testing.T) {
|
||||
t.Setenv("FLEET_DEV_DOWNLOAD_FLEETDM_URL", "https://download-testing.fleetdm.com")
|
||||
dev_mode.SetOverride("FLEET_DEV_DOWNLOAD_FLEETDM_URL", "https://download-testing.fleetdm.com", t)
|
||||
require.Equal(t, "https://download-testing.fleetdm.com", getBaseURL())
|
||||
})
|
||||
|
||||
@@ -37,7 +38,7 @@ func TestGetMetadata(t *testing.T) {
|
||||
require.NoError(t, json.NewEncoder(w).Encode(expectedMetadata))
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
t.Setenv("FLEET_DEV_DOWNLOAD_FLEETDM_URL", server.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_DOWNLOAD_FLEETDM_URL", server.URL, t)
|
||||
|
||||
meta, err := GetMetadata()
|
||||
require.NoError(t, err)
|
||||
@@ -46,7 +47,7 @@ func TestGetMetadata(t *testing.T) {
|
||||
|
||||
func TestGetMetadataErrorScenarios(t *testing.T) {
|
||||
t.Run("invalid URL", func(t *testing.T) {
|
||||
t.Setenv("FLEET_DEV_DOWNLOAD_FLEETDM_URL", "://invalid-url")
|
||||
dev_mode.SetOverride("FLEET_DEV_DOWNLOAD_FLEETDM_URL", "://invalid-url", t)
|
||||
_, err := GetMetadata()
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "invalid URL")
|
||||
@@ -57,7 +58,7 @@ func TestGetMetadataErrorScenarios(t *testing.T) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
t.Setenv("FLEET_DEV_DOWNLOAD_FLEETDM_URL", server.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_DOWNLOAD_FLEETDM_URL", server.URL, t)
|
||||
|
||||
_, err := GetMetadata()
|
||||
require.Error(t, err)
|
||||
@@ -72,7 +73,7 @@ func TestGetMetadataErrorScenarios(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
t.Setenv("FLEET_DEV_DOWNLOAD_FLEETDM_URL", server.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_DOWNLOAD_FLEETDM_URL", server.URL, t)
|
||||
|
||||
_, err := GetMetadata()
|
||||
require.Error(t, err)
|
||||
@@ -82,7 +83,7 @@ func TestGetMetadataErrorScenarios(t *testing.T) {
|
||||
|
||||
func TestGetPKGManifestURL(t *testing.T) {
|
||||
t.Run("with env variable", func(t *testing.T) {
|
||||
t.Setenv("FLEET_DEV_DOWNLOAD_FLEETDM_URL", "https://download-test.fleetdm.com")
|
||||
dev_mode.SetOverride("FLEET_DEV_DOWNLOAD_FLEETDM_URL", "https://download-test.fleetdm.com", t)
|
||||
require.Equal(t, "https://download-test.fleetdm.com/stable/fleetd-base-manifest.plist", GetPKGManifestURL())
|
||||
})
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
|
||||
shared_mdm "github.com/fleetdm/fleet/v4/pkg/mdm"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/mysql"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
apple_mdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/mdm"
|
||||
@@ -538,16 +539,17 @@ func (c *TestAppleMDMClient) fetchOTAProfile(url string) error {
|
||||
// believe this could be done with a little bit of reverse
|
||||
// engineering/cleverness but for now, we're signing the request with
|
||||
// our mock certs and setting this env var to skip the verification.
|
||||
os.Setenv("FLEET_DEV_MDM_APPLE_DISABLE_DEVICE_INFO_CERT_VERIFY", "1")
|
||||
|
||||
mockedCert, mockedKey, err := apple_mdm.NewSCEPCACertKey()
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating mock certificates: %w", err)
|
||||
}
|
||||
dev_mode.SetOverride("FLEET_DEV_MDM_APPLE_DISABLE_DEVICE_INFO_CERT_VERIFY", "1")
|
||||
body, err = do(mockedCert, mockedKey)
|
||||
dev_mode.ClearOverride("FLEET_DEV_MDM_APPLE_DISABLE_DEVICE_INFO_CERT_VERIFY")
|
||||
if err != nil {
|
||||
return fmt.Errorf("first OTA request: %w", err)
|
||||
}
|
||||
os.Unsetenv("FLEET_DEV_MDM_APPLE_DISABLE_DEVICE_INFO_CERT_VERIFY")
|
||||
|
||||
var scepInfo struct {
|
||||
PayloadContent []struct {
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package dev_mode
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var IsEnabled bool
|
||||
|
||||
var envOverrides = map[string]string{}
|
||||
|
||||
type GetEnv func(name string) string
|
||||
|
||||
func Env(name string) string {
|
||||
if !IsEnabled {
|
||||
return ""
|
||||
}
|
||||
if override, ok := envOverrides[name]; ok {
|
||||
return override
|
||||
}
|
||||
|
||||
return os.Getenv(name)
|
||||
}
|
||||
|
||||
func SetOverride(name string, value string, cleanup ...*testing.T) { // optional parameter to reset on test cleanup
|
||||
if len(cleanup) > 0 {
|
||||
cleanup[0].Setenv("FLEET_DEV_OVERRIDE_SET", "1") // triggers test deny-parallel check
|
||||
cleanup[0].Cleanup(func() {
|
||||
ClearOverride(name)
|
||||
})
|
||||
}
|
||||
|
||||
IsEnabled = true // if we're setting overrides, we're in a test environment so want to turn dev mode on
|
||||
envOverrides[name] = value
|
||||
}
|
||||
|
||||
func ClearOverride(name string) {
|
||||
delete(envOverrides, name)
|
||||
}
|
||||
|
||||
func ClearAllOverrides() {
|
||||
envOverrides = map[string]string{}
|
||||
}
|
||||
+2
-1
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/pkg/optjson"
|
||||
"github.com/fleetdm/fleet/v4/pkg/rawjson"
|
||||
"github.com/fleetdm/fleet/v4/server/config"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/ptr"
|
||||
)
|
||||
|
||||
@@ -288,7 +289,7 @@ func (c *AppConfig) MDMUrl() string {
|
||||
// - https://foo.example.com:8080 -> https://okta.foo.example.com:8080
|
||||
//
|
||||
// Returns an error if the server URL is not configured or cannot be parsed.
|
||||
func (c *AppConfig) ConditionalAccessIdPSSOURL(getenv func(string) string) (string, error) {
|
||||
func (c *AppConfig) ConditionalAccessIdPSSOURL(getenv dev_mode.GetEnv) (string, error) {
|
||||
// Check for dev override
|
||||
if devURL := getenv("FLEET_DEV_OKTA_SSO_SERVER_URL"); devURL != "" {
|
||||
return devURL, nil
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"cloud.google.com/go/pubsub"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/android"
|
||||
"github.com/go-json-experiment/json"
|
||||
@@ -35,7 +36,7 @@ type GoogleClient struct {
|
||||
// Compile-time check to ensure that ProxyClient implements Client.
|
||||
var _ Client = &GoogleClient{}
|
||||
|
||||
func NewGoogleClient(ctx context.Context, logger kitlog.Logger, getenv func(string) string) Client {
|
||||
func NewGoogleClient(ctx context.Context, logger kitlog.Logger, getenv dev_mode.GetEnv) Client {
|
||||
androidServiceCredentials := getenv("FLEET_DEV_ANDROID_GOOGLE_SERVICE_CREDENTIALS")
|
||||
if androidServiceCredentials == "" {
|
||||
return nil
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/android"
|
||||
"github.com/go-json-experiment/json"
|
||||
kitlog "github.com/go-kit/log"
|
||||
@@ -36,7 +37,7 @@ type ProxyClient struct {
|
||||
// Compile-time check to ensure that ProxyClient implements Client.
|
||||
var _ Client = &ProxyClient{}
|
||||
|
||||
func NewProxyClient(ctx context.Context, logger kitlog.Logger, licenseKey string, getenv func(string) string) Client {
|
||||
func NewProxyClient(ctx context.Context, logger kitlog.Logger, licenseKey string, getenv dev_mode.GetEnv) Client {
|
||||
proxyEndpoint := getenv("FLEET_DEV_ANDROID_PROXY_ENDPOINT")
|
||||
if proxyEndpoint == "" {
|
||||
proxyEndpoint = defaultProxyEndpoint
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -19,6 +18,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/config"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/viewer"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/android"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/android/service/androidmgmt"
|
||||
@@ -110,10 +110,11 @@ func NewServiceWithClient(
|
||||
|
||||
func newAMAPIClient(ctx context.Context, logger kitlog.Logger, licenseKey string) androidmgmt.Client {
|
||||
var client androidmgmt.Client
|
||||
if os.Getenv("FLEET_DEV_ANDROID_GOOGLE_CLIENT") == "1" || strings.ToUpper(os.Getenv("FLEET_DEV_ANDROID_GOOGLE_CLIENT")) == "ON" {
|
||||
client = androidmgmt.NewGoogleClient(ctx, logger, os.Getenv)
|
||||
getEnv := dev_mode.Env
|
||||
if getEnv("FLEET_DEV_ANDROID_GOOGLE_CLIENT") == "1" || strings.ToUpper(getEnv("FLEET_DEV_ANDROID_GOOGLE_CLIENT")) == "ON" {
|
||||
client = androidmgmt.NewGoogleClient(ctx, logger, getEnv)
|
||||
} else {
|
||||
client = androidmgmt.NewProxyClient(ctx, logger, licenseKey, os.Getenv)
|
||||
client = androidmgmt.NewProxyClient(ctx, logger, licenseKey, getEnv)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -16,6 +15,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
|
||||
"github.com/fleetdm/fleet/v4/pkg/retry"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
)
|
||||
|
||||
@@ -244,14 +244,14 @@ func ToVPPApps(app Metadata) map[fleet.InstallableDevicePlatform]fleet.VPPApp {
|
||||
|
||||
func getBaseURL() string {
|
||||
region := "us"
|
||||
if os.Getenv("FLEET_DEV_VPP_REGION") != "" {
|
||||
region = os.Getenv("FLEET_DEV_VPP_REGION")
|
||||
if dev_mode.Env("FLEET_DEV_VPP_REGION") != "" {
|
||||
region = dev_mode.Env("FLEET_DEV_VPP_REGION")
|
||||
}
|
||||
if os.Getenv("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL") == "apple" {
|
||||
if dev_mode.Env("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL") == "apple" {
|
||||
return fmt.Sprintf(appleHostAndScheme+"/v1/catalog/%s/stoken-authenticated-apps?platform=iphone&additionalPlatforms=ipad,mac&extend[apps]=latestVersionInfo", region)
|
||||
}
|
||||
if os.Getenv("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL") != "" {
|
||||
return os.Getenv("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL")
|
||||
if dev_mode.Env("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL") != "" {
|
||||
return dev_mode.Env("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL")
|
||||
}
|
||||
return fmt.Sprintf("https://fleetdm.com/api/vpp/v1/metadata/%s?platform=iphone&additionalPlatforms=ipad,mac&extend[apps]=latestVersionInfo", region)
|
||||
}
|
||||
@@ -266,7 +266,7 @@ type DataStore interface {
|
||||
}
|
||||
|
||||
func GetAuthenticator(ctx context.Context, ds DataStore, licenseKey string) Authenticator {
|
||||
token := os.Getenv("FLEET_DEV_VPP_METADATA_BEARER_TOKEN")
|
||||
token := dev_mode.Env("FLEET_DEV_VPP_METADATA_BEARER_TOKEN")
|
||||
if token != "" {
|
||||
return func(bool) (string, error) { return token, nil }
|
||||
}
|
||||
@@ -281,7 +281,7 @@ func GetAuthenticator(ctx context.Context, ds DataStore, licenseKey string) Auth
|
||||
}
|
||||
}
|
||||
|
||||
authUrl := os.Getenv("FLEET_DEV_VPP_PROXY_AUTH_URL")
|
||||
authUrl := dev_mode.Env("FLEET_DEV_VPP_PROXY_AUTH_URL")
|
||||
if authUrl == "" {
|
||||
authUrl = "https://fleetdm.com/api/vpp/v1/auth"
|
||||
}
|
||||
|
||||
@@ -6,18 +6,19 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetBaseURLAndBuildMetadataRequest(t *testing.T) {
|
||||
defer dev_mode.ClearAllOverrides()
|
||||
t.Run("Default URL", func(t *testing.T) {
|
||||
os.Setenv("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL", "")
|
||||
dev_mode.SetOverride("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL", "", t)
|
||||
require.Equal(t, "https://fleetdm.com/api/vpp/v1/metadata/us?platform=iphone&additionalPlatforms=ipad,mac&extend[apps]=latestVersionInfo", getBaseURL())
|
||||
|
||||
req, err := buildMetadataRequest([]string{"1"}, "this-is-a-token")
|
||||
@@ -28,7 +29,7 @@ func TestGetBaseURLAndBuildMetadataRequest(t *testing.T) {
|
||||
|
||||
t.Run("Custom URL", func(t *testing.T) {
|
||||
customURL := "http://localhost:8000"
|
||||
os.Setenv("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL", customURL)
|
||||
dev_mode.SetOverride("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL", customURL, t)
|
||||
require.Equal(t, customURL, getBaseURL())
|
||||
|
||||
req, err := buildMetadataRequest([]string{"1"}, "this-is-a-token")
|
||||
@@ -38,14 +39,14 @@ func TestGetBaseURLAndBuildMetadataRequest(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Custom Region", func(t *testing.T) {
|
||||
os.Setenv("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL", "")
|
||||
os.Setenv("FLEET_DEV_VPP_REGION", "fr")
|
||||
dev_mode.SetOverride("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL", "", t)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_REGION", "fr", t)
|
||||
require.Equal(t, "https://fleetdm.com/api/vpp/v1/metadata/fr?platform=iphone&additionalPlatforms=ipad,mac&extend[apps]=latestVersionInfo", getBaseURL())
|
||||
})
|
||||
|
||||
t.Run("Direct to Apple", func(t *testing.T) {
|
||||
os.Setenv("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL", "apple")
|
||||
os.Setenv("FLEET_DEV_VPP_REGION", "")
|
||||
dev_mode.SetOverride("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL", "apple", t)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_REGION", "", t)
|
||||
require.Equal(t, "https://api.ent.apple.com/v1/catalog/us/stoken-authenticated-apps?platform=iphone&additionalPlatforms=ipad,mac&extend[apps]=latestVersionInfo", getBaseURL())
|
||||
|
||||
req, err := buildMetadataRequest([]string{"1"}, "this-is-a-token")
|
||||
@@ -57,7 +58,7 @@ func TestGetBaseURLAndBuildMetadataRequest(t *testing.T) {
|
||||
|
||||
func setupFakeServer(t *testing.T, handler http.HandlerFunc) {
|
||||
server := httptest.NewServer(handler)
|
||||
os.Setenv("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL", server.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL", server.URL, t)
|
||||
t.Cleanup(server.Close)
|
||||
}
|
||||
|
||||
@@ -233,16 +234,8 @@ func (m *mockDataStore) GetAllCAConfigAssetsByType(ctx context.Context, assetTyp
|
||||
|
||||
func TestAuthentication(t *testing.T) {
|
||||
// Clear any dev env vars that might interfere
|
||||
originalDevToken := os.Getenv("FLEET_DEV_VPP_METADATA_BEARER_TOKEN")
|
||||
originalAuthURL := os.Getenv("FLEET_DEV_VPP_PROXY_AUTH_URL")
|
||||
t.Cleanup(func() {
|
||||
os.Setenv("FLEET_DEV_VPP_METADATA_BEARER_TOKEN", originalDevToken)
|
||||
os.Setenv("FLEET_DEV_VPP_PROXY_AUTH_URL", originalAuthURL)
|
||||
})
|
||||
|
||||
t.Run("uses bearer token env var when set", func(t *testing.T) {
|
||||
os.Setenv("FLEET_DEV_VPP_METADATA_BEARER_TOKEN", "dev-test-token")
|
||||
defer os.Setenv("FLEET_DEV_VPP_METADATA_BEARER_TOKEN", "")
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_METADATA_BEARER_TOKEN", "dev-test-token", t)
|
||||
|
||||
ds := &mockDataStore{}
|
||||
auth := GetAuthenticator(context.Background(), ds, "license-key")
|
||||
@@ -261,7 +254,7 @@ func TestAuthentication(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("returns cached token from database when not forced renewal", func(t *testing.T) {
|
||||
os.Setenv("FLEET_DEV_VPP_METADATA_BEARER_TOKEN", "")
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_METADATA_BEARER_TOKEN", "", t)
|
||||
|
||||
ds := &mockDataStore{
|
||||
assets: map[fleet.MDMAssetName]fleet.MDMConfigAsset{
|
||||
@@ -281,7 +274,7 @@ func TestAuthentication(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("requests new token when forced renewal even if cached exists", func(t *testing.T) {
|
||||
os.Setenv("FLEET_DEV_VPP_METADATA_BEARER_TOKEN", "")
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_METADATA_BEARER_TOKEN", "", t)
|
||||
|
||||
// Set up a mock auth server
|
||||
authServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -294,7 +287,7 @@ func TestAuthentication(t *testing.T) {
|
||||
_, _ = w.Write([]byte(`{"fleetServerSecret": "new-token-from-auth"}`))
|
||||
}))
|
||||
defer authServer.Close()
|
||||
os.Setenv("FLEET_DEV_VPP_PROXY_AUTH_URL", authServer.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_PROXY_AUTH_URL", authServer.URL, t)
|
||||
|
||||
ds := &mockDataStore{
|
||||
assets: map[fleet.MDMAssetName]fleet.MDMConfigAsset{
|
||||
@@ -326,7 +319,7 @@ func TestAuthentication(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("requests new token when nothing in database and no forced renewal", func(t *testing.T) {
|
||||
os.Setenv("FLEET_DEV_VPP_METADATA_BEARER_TOKEN", "")
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_METADATA_BEARER_TOKEN", "", t)
|
||||
|
||||
// Set up a mock auth server
|
||||
authServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -339,7 +332,7 @@ func TestAuthentication(t *testing.T) {
|
||||
_, _ = w.Write([]byte(`{"fleetServerSecret": "fresh-token"}`))
|
||||
}))
|
||||
defer authServer.Close()
|
||||
os.Setenv("FLEET_DEV_VPP_PROXY_AUTH_URL", authServer.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_PROXY_AUTH_URL", authServer.URL, t)
|
||||
|
||||
ds := &mockDataStore{
|
||||
assets: map[fleet.MDMAssetName]fleet.MDMConfigAsset{}, // Empty - no cached token
|
||||
@@ -363,7 +356,7 @@ func TestAuthentication(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("returns error when auth server fails", func(t *testing.T) {
|
||||
os.Setenv("FLEET_DEV_VPP_METADATA_BEARER_TOKEN", "")
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_METADATA_BEARER_TOKEN", "", t)
|
||||
|
||||
// Set up a mock auth server that fails
|
||||
authServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -371,7 +364,7 @@ func TestAuthentication(t *testing.T) {
|
||||
_, _ = w.Write([]byte(`{"error": "invalid license"}`))
|
||||
}))
|
||||
defer authServer.Close()
|
||||
os.Setenv("FLEET_DEV_VPP_PROXY_AUTH_URL", authServer.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_PROXY_AUTH_URL", authServer.URL, t)
|
||||
|
||||
ds := &mockDataStore{
|
||||
assets: map[fleet.MDMAssetName]fleet.MDMConfigAsset{}, // Empty
|
||||
@@ -389,7 +382,7 @@ func TestAuthentication(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("returns error when auth response has empty token", func(t *testing.T) {
|
||||
os.Setenv("FLEET_DEV_VPP_METADATA_BEARER_TOKEN", "")
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_METADATA_BEARER_TOKEN", "", t)
|
||||
|
||||
// Set up a mock auth server that returns empty token
|
||||
authServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -397,7 +390,7 @@ func TestAuthentication(t *testing.T) {
|
||||
_, _ = w.Write([]byte(`{"fleetServerSecret": ""}`))
|
||||
}))
|
||||
defer authServer.Close()
|
||||
os.Setenv("FLEET_DEV_VPP_PROXY_AUTH_URL", authServer.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_PROXY_AUTH_URL", authServer.URL, t)
|
||||
|
||||
ds := &mockDataStore{
|
||||
assets: map[fleet.MDMAssetName]fleet.MDMConfigAsset{},
|
||||
@@ -492,7 +485,7 @@ func TestDoRetries(t *testing.T) {
|
||||
})
|
||||
|
||||
start := time.Now()
|
||||
req, err := http.NewRequest(http.MethodGet, os.Getenv("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL"), nil)
|
||||
req, err := http.NewRequest(http.MethodGet, dev_mode.Env("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL"), nil)
|
||||
require.NoError(t, err)
|
||||
err = do(req, func(forceRenew bool) (string, error) {
|
||||
if forceRenew {
|
||||
|
||||
@@ -36,9 +36,9 @@ import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/apple/rootcert"
|
||||
"github.com/micromdm/plist"
|
||||
@@ -171,7 +171,7 @@ func ParseMachineInfoFromPKCS7(buf []byte, verify bool) (*fleet.MDMAppleMachineI
|
||||
//
|
||||
// NOTE: most of this code was taken from micromdm.
|
||||
func VerifyFromAppleIphoneDeviceCA(c *x509.Certificate) error {
|
||||
if os.Getenv("FLEET_DEV_MDM_APPLE_DISABLE_DEVICE_INFO_CERT_VERIFY") == "1" {
|
||||
if dev_mode.Env("FLEET_DEV_MDM_APPLE_DISABLE_DEVICE_INFO_CERT_VERIFY") == "1" {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff"
|
||||
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/apple/rootcert"
|
||||
)
|
||||
@@ -205,7 +205,7 @@ func doWithRetry(req *http.Request) (*http.Response, error) {
|
||||
}
|
||||
|
||||
func getBaseURL() string {
|
||||
devURL := os.Getenv("FLEET_DEV_GDMF_URL")
|
||||
devURL := dev_mode.Env("FLEET_DEV_GDMF_URL")
|
||||
if devURL != "" {
|
||||
return devURL
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -24,7 +25,7 @@ func TestGetLatest(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
defer srv.Close()
|
||||
t.Setenv("FLEET_DEV_GDMF_URL", srv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_GDMF_URL", srv.URL, t)
|
||||
|
||||
// test the function
|
||||
d := fleet.MDMAppleMachineInfo{
|
||||
@@ -224,10 +225,10 @@ func TestRetries(t *testing.T) {
|
||||
_, err := w.Write([]byte(`{"error": "bad request"}`))
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
os.Setenv("FLEET_DEV_GDMF_URL", srv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_GDMF_URL", srv.URL)
|
||||
t.Cleanup(func() {
|
||||
srv.Close()
|
||||
os.Unsetenv("FLEET_DEV_GDMF_URL")
|
||||
dev_mode.ClearOverride("FLEET_DEV_GDMF_URL")
|
||||
})
|
||||
|
||||
latest, err := GetLatestOSVersion(fleet.MDMAppleMachineInfo{
|
||||
|
||||
@@ -10,12 +10,12 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
|
||||
"github.com/fleetdm/fleet/v4/pkg/retry"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
)
|
||||
|
||||
// Asset is a product in the store.
|
||||
@@ -362,7 +362,7 @@ func do[T any](req *http.Request, token string, dest *T) error {
|
||||
}
|
||||
|
||||
func getBaseURL() string {
|
||||
devURL := os.Getenv("FLEET_DEV_VPP_URL")
|
||||
devURL := dev_mode.Env("FLEET_DEV_VPP_URL")
|
||||
if devURL != "" {
|
||||
return devURL
|
||||
}
|
||||
|
||||
@@ -6,18 +6,18 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func setupFakeServer(t *testing.T, handler http.HandlerFunc) {
|
||||
server := httptest.NewServer(handler)
|
||||
os.Setenv("FLEET_DEV_VPP_URL", server.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", server.URL, t)
|
||||
t.Cleanup(server.Close)
|
||||
}
|
||||
|
||||
@@ -356,7 +356,7 @@ func TestDoRetryAfter(t *testing.T) {
|
||||
})
|
||||
|
||||
start := time.Now()
|
||||
req, err := http.NewRequest(http.MethodGet, os.Getenv("FLEET_DEV_VPP_URL"), nil)
|
||||
req, err := http.NewRequest(http.MethodGet, dev_mode.Env("FLEET_DEV_VPP_URL"), nil)
|
||||
require.NoError(t, err)
|
||||
err = do[any](req, "test-token", nil)
|
||||
require.NoError(t, err)
|
||||
@@ -368,13 +368,12 @@ func TestDoRetryAfter(t *testing.T) {
|
||||
|
||||
func TestGetBaseURL(t *testing.T) {
|
||||
t.Run("Default URL", func(t *testing.T) {
|
||||
os.Setenv("FLEET_DEV_VPP_URL", "")
|
||||
require.Equal(t, "https://vpp.itunes.apple.com/mdm/v2", getBaseURL())
|
||||
})
|
||||
|
||||
t.Run("Custom URL", func(t *testing.T) {
|
||||
customURL := "http://localhost:8000"
|
||||
os.Setenv("FLEET_DEV_VPP_URL", customURL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", customURL, t)
|
||||
require.Equal(t, customURL, getBaseURL())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
ma "github.com/fleetdm/fleet/v4/ee/maintained-apps"
|
||||
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
kitlog "github.com/go-kit/log"
|
||||
)
|
||||
@@ -45,7 +45,7 @@ func Refresh(ctx context.Context, ds fleet.Datastore, logger kitlog.Logger) erro
|
||||
func FetchAppsList(ctx context.Context) (*AppsList, error) {
|
||||
httpClient := fleethttp.NewClient(fleethttp.WithTimeout(10 * time.Second))
|
||||
baseURL := fmaOutputsBase
|
||||
if baseFromEnvVar := os.Getenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL"); baseFromEnvVar != "" {
|
||||
if baseFromEnvVar := dev_mode.Env("FLEET_DEV_MAINTAINED_APPS_BASE_URL"); baseFromEnvVar != "" {
|
||||
baseURL = baseFromEnvVar
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ func upsertMaintainedApps(ctx context.Context, appsList *AppsList, ds fleet.Data
|
||||
func Hydrate(ctx context.Context, app *fleet.MaintainedApp) (*fleet.MaintainedApp, error) {
|
||||
httpClient := fleethttp.NewClient(fleethttp.WithTimeout(10 * time.Second))
|
||||
baseURL := fmaOutputsBase
|
||||
if baseFromEnvVar := os.Getenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL"); baseFromEnvVar != "" {
|
||||
if baseFromEnvVar := dev_mode.Env("FLEET_DEV_MAINTAINED_APPS_BASE_URL"); baseFromEnvVar != "" {
|
||||
baseURL = baseFromEnvVar
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -41,8 +42,8 @@ func SyncApps(t *testing.T, ds fleet.Datastore) []fleet.MaintainedApp {
|
||||
|
||||
// not using t.Setenv because we want the env var to be unset on return of
|
||||
// this call
|
||||
os.Setenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL", srv.URL)
|
||||
defer os.Unsetenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL")
|
||||
dev_mode.SetOverride("FLEET_DEV_MAINTAINED_APPS_BASE_URL", srv.URL)
|
||||
defer dev_mode.ClearOverride("FLEET_DEV_MAINTAINED_APPS_BASE_URL")
|
||||
|
||||
err := Refresh(context.Background(), ds, log.NewNopLogger())
|
||||
require.NoError(t, err)
|
||||
@@ -97,8 +98,8 @@ func SyncAndRemoveApps(t *testing.T, ds fleet.Datastore) {
|
||||
|
||||
// not using t.Setenv because we want the env var to be unset on return of
|
||||
// this call
|
||||
os.Setenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL", srv.URL)
|
||||
defer os.Unsetenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL")
|
||||
dev_mode.SetOverride("FLEET_DEV_MAINTAINED_APPS_BASE_URL", srv.URL)
|
||||
defer dev_mode.ClearOverride("FLEET_DEV_MAINTAINED_APPS_BASE_URL")
|
||||
|
||||
err = Refresh(context.Background(), ds, log.NewNopLogger())
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -21,6 +20,7 @@ import (
|
||||
"github.com/MicahParks/jwkset"
|
||||
"github.com/fleetdm/fleet/v4/server"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/microsoft/syncml"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/cryptoutil"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
@@ -258,7 +258,7 @@ func GetAzureAuthTokenClaims(ctx context.Context, tokenStr string) (AzureData, e
|
||||
// Parse JWT token
|
||||
jwksURI := "https://login.microsoftonline.com/common/discovery/v2.0/keys"
|
||||
var token *jwt.Token
|
||||
FLEET_DEV_AZURE_JWT_JWKS_URI := os.Getenv("FLEET_DEV_AZURE_JWT_JWKS_URI")
|
||||
FLEET_DEV_AZURE_JWT_JWKS_URI := dev_mode.Env("FLEET_DEV_AZURE_JWT_JWKS_URI")
|
||||
if FLEET_DEV_AZURE_JWT_JWKS_URI != "" {
|
||||
jwksURI = FLEET_DEV_AZURE_JWT_JWKS_URI
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/viewer"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/mysql"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/redis/redistest"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
fleetmdm "github.com/fleetdm/fleet/v4/server/mdm"
|
||||
apple_mdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
|
||||
@@ -5121,7 +5122,7 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
defer gdmf.Close()
|
||||
t.Setenv("FLEET_DEV_GDMF_URL", gdmf.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_GDMF_URL", gdmf.URL, t)
|
||||
|
||||
latestMacOSVersion := "14.6.1"
|
||||
latestMacOSBuild := "23G93"
|
||||
|
||||
@@ -9,13 +9,13 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/logging"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
@@ -367,7 +367,7 @@ func (svc *Service) ConditionalAccessGetIdPAppleProfile(ctx context.Context) (pr
|
||||
challenge := secrets[0].Secret
|
||||
|
||||
// Get mTLS URL using ConditionalAccessIdPSSOURL
|
||||
mtlsURL, err := appConfig.ConditionalAccessIdPSSOURL(os.Getenv)
|
||||
mtlsURL, err := appConfig.ConditionalAccessIdPSSOURL(dev_mode.Env)
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "failed to get mTLS URL")
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/filesystem"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/mysql"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/redis/redistest"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/live_query/live_query_mock"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm"
|
||||
@@ -18834,8 +18835,8 @@ func (s *integrationEnterpriseTestSuite) TestMaintainedApps() {
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
t.Cleanup(manifestServer.Close)
|
||||
os.Setenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL", manifestServer.URL)
|
||||
defer os.Unsetenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL")
|
||||
dev_mode.SetOverride("FLEET_DEV_MAINTAINED_APPS_BASE_URL", manifestServer.URL)
|
||||
defer dev_mode.ClearOverride("FLEET_DEV_MAINTAINED_APPS_BASE_URL")
|
||||
|
||||
// Create a team
|
||||
var newTeamResp teamResponse
|
||||
@@ -19028,9 +19029,9 @@ func (s *integrationEnterpriseTestSuite) TestMaintainedApps() {
|
||||
require.Contains(t, extractServerErrorText(r.Body), "mismatch in maintained app SHA256 hash")
|
||||
|
||||
// Should timeout
|
||||
os.Setenv("FLEET_DEV_MAINTAINED_APPS_INSTALLER_TIMEOUT", "1s")
|
||||
dev_mode.SetOverride("FLEET_DEV_MAINTAINED_APPS_INSTALLER_TIMEOUT", "1s")
|
||||
r = s.Do("POST", "/api/latest/fleet/software/fleet_maintained_apps", &addFleetMaintainedAppRequest{AppID: 3}, http.StatusGatewayTimeout)
|
||||
os.Unsetenv("FLEET_DEV_MAINTAINED_APPS_INSTALLER_TIMEOUT")
|
||||
dev_mode.ClearOverride("FLEET_DEV_MAINTAINED_APPS_INSTALLER_TIMEOUT")
|
||||
require.Contains(t, extractServerErrorText(r.Body), "Couldn't add. Request timeout. Please make sure your server and load balancer timeout is long enough.")
|
||||
|
||||
// Add a maintained app to no team
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/fleetdm/fleet/v4/pkg/mdm/mdmtest"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/mysql"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/android"
|
||||
android_service "github.com/fleetdm/fleet/v4/server/mdm/android/service"
|
||||
@@ -744,7 +745,7 @@ func (s *integrationMDMTestSuite) TestSetupExperienceVPPInstallError() {
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
@@ -1863,7 +1864,7 @@ func (s *integrationMDMTestSuite) TestSetupExperienceVPPCRUD() {
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
@@ -2090,7 +2091,7 @@ func (s *integrationMDMTestSuite) TestSetupExperienceIOSAndIPadOS() {
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
@@ -3009,7 +3010,7 @@ func (s *integrationMDMTestSuite) TestSetupExperienceFlowWithRequiredSoftwareVPP
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
|
||||
"github.com/MicahParks/jwkset"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/android"
|
||||
android_mock "github.com/fleetdm/fleet/v4/server/mdm/android/mock"
|
||||
android_service "github.com/fleetdm/fleet/v4/server/mdm/android/service"
|
||||
@@ -11722,7 +11723,7 @@ func (s *integrationMDMTestSuite) TestBatchAssociateAppStoreApps() {
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var vppRes uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &vppRes)
|
||||
|
||||
@@ -12578,13 +12579,13 @@ func (s *integrationMDMTestSuite) TestVPPApps() {
|
||||
s.setSkipWorkerJobs(t)
|
||||
|
||||
// Invalid token
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL+"?invalidToken")
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL+"?invalidToken", t)
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte("foobar"), http.StatusUnprocessableEntity, "Invalid token. Please provide a valid content token from Apple Business Manager.", nil)
|
||||
// Attempt to renew an invalid (nonexistent) token, should fail
|
||||
s.uploadDataViaFormWithVerb("/api/latest/fleet/vpp_tokens/999/renew", "PATCH", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte("foobar"))), http.StatusUnprocessableEntity, "Invalid token. Please provide a valid content token from Apple Business Manager.", nil)
|
||||
|
||||
// Simulate a server error from the Apple API
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL+"?serverError")
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL+"?serverError", t)
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte("foobar"), http.StatusInternalServerError, "Apple VPP endpoint returned error: Internal server error (error number: 9603)", nil)
|
||||
|
||||
// Valid token
|
||||
@@ -12594,7 +12595,7 @@ func (s *integrationMDMTestSuite) TestVPPApps() {
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
@@ -13852,7 +13853,7 @@ func (s *integrationMDMTestSuite) TestNoTeamVPPAppIcons() {
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
@@ -13945,7 +13946,7 @@ func (s *integrationMDMTestSuite) TestVPPAppPolicyAutomation() {
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
@@ -14828,7 +14829,7 @@ func (s *integrationMDMTestSuite) TestOTAEnrollment() {
|
||||
})
|
||||
|
||||
t.Run("if invalid device signature", func(t *testing.T) {
|
||||
t.Setenv("FLEET_DEV_MDM_APPLE_DISABLE_DEVICE_INFO_CERT_VERIFY", "1")
|
||||
dev_mode.SetOverride("FLEET_DEV_MDM_APPLE_DISABLE_DEVICE_INFO_CERT_VERIFY", "1", t)
|
||||
httpResp := s.DoRawNoAuth("POST", "/api/latest/fleet/ota_enrollment?enroll_secret=foo", signedReqBody, http.StatusForbidden)
|
||||
errMsg := extractServerErrorText(httpResp.Body)
|
||||
require.Contains(t, errMsg, "Couldn't install the profile. Invalid enroll secret. Please contact your IT admin.")
|
||||
@@ -17551,7 +17552,7 @@ func (s *integrationMDMTestSuite) TestVPPPolicyAutomationLabelScopingRetrigger()
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
@@ -17809,7 +17810,7 @@ func (s *integrationMDMTestSuite) TestRefreshVPPAppVersions() {
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
@@ -17927,7 +17928,7 @@ func (s *integrationMDMTestSuite) TestRefreshVPPAppVersionsForAllPlatforms() {
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
@@ -18075,7 +18076,7 @@ func (s *integrationMDMTestSuite) TestUpcomingActivitiesTurnMDMOff() {
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
@@ -18609,7 +18610,7 @@ func (s *integrationMDMTestSuite) TestCancelUpcomingActivity() {
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
@@ -19098,7 +19099,7 @@ func (s *integrationMDMTestSuite) TestSoftwareCategories() {
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
@@ -20240,7 +20241,7 @@ func (s *integrationMDMTestSuite) TestTeamLabelsAssociationsCheck() {
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/fleetdm/fleet/v4/pkg/mdm/mdmtest"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/mysql"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/apple/vpp"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/mdm"
|
||||
@@ -34,7 +35,7 @@ func (s *integrationMDMTestSuite) setVPPTokenForTeam(teamID uint) {
|
||||
expTime := time.Now().Add(200 * time.Hour).UTC().Round(time.Second)
|
||||
expDate := expTime.Format(fleet.VPPTimeFormat)
|
||||
tokenJSON := fmt.Sprintf(`{"expDate":"%s","token":"%s","orgName":"%s"}`, expDate, token, orgName)
|
||||
t.Setenv("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL)
|
||||
dev_mode.SetOverride("FLEET_DEV_VPP_URL", s.appleVPPConfigSrv.URL, t)
|
||||
var validToken uploadVPPTokenResponse
|
||||
s.uploadDataViaForm("/api/latest/fleet/vpp_tokens", "token", "token.vpptoken", []byte(base64.StdEncoding.EncodeToString([]byte(tokenJSON))), http.StatusAccepted, "", &validToken)
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/go-json-experiment/json"
|
||||
"github.com/go-json-experiment/json/jsontext"
|
||||
"google.golang.org/api/androidmanagement/v1"
|
||||
@@ -17,7 +18,7 @@ import (
|
||||
|
||||
// Required env vars:
|
||||
var (
|
||||
androidServiceCredentials = os.Getenv("FLEET_DEV_ANDROID_GOOGLE_SERVICE_CREDENTIALS")
|
||||
androidServiceCredentials string
|
||||
androidProjectID string
|
||||
)
|
||||
|
||||
@@ -46,6 +47,8 @@ var commands = []string{
|
||||
}
|
||||
|
||||
func main() {
|
||||
dev_mode.IsEnabled = true
|
||||
androidServiceCredentials = dev_mode.Env("FLEET_DEV_ANDROID_GOOGLE_SERVICE_CREDENTIALS")
|
||||
if androidServiceCredentials == "" {
|
||||
log.Fatal("FLEET_DEV_ANDROID_GOOGLE_SERVICE_CREDENTIALS must be set")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user