You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[PPSC-563] feat(auth): remove auth-endpoint flag (#98)
* [PPSC-563] feat(auth): remove auth-endpoint flag and add region support
Simplify CLI authentication by removing the --auth-endpoint flag entirely.
Auth now routes through moose's proxy endpoint automatically, with the base
URL derived from the --dev flag or hardcoded production endpoint.
Changes:
- Replace AuthEndpoint config with BaseURL (derived from getAPIBaseURL)
- Update auth client endpoint from /api/v1/authenticate to /api/v1/auth/token
- Remove --auth-endpoint flag and ARMIS_AUTH_ENDPOINT environment variable
- Add region claim support to JWT parsing for deployment-aware routing
- Rename endpoint → baseURL in NewAuthClient for semantic clarity
- Update error messages to reflect base URL terminology
- Update all tests and documentation
This simplifies the auth flow by removing a user-configurable endpoint,
reducing attack surface and improving UX when configuring authentication.
* fix(auth): check os.Setenv/Unsetenv error returns in tests
* fix(docs): address PR review comments on auth documentation
- Update NewAuthProvider comment to say "base URL" instead of "endpoint"
- Document ARMIS_API_URL in FEATURES.md and CLAUDE.md env var sections
* feat(auth): add region caching with retry and shared cache utility
Add region caching to optimize JWT authentication by persisting the
discovered region to disk and reusing it on subsequent CLI invocations.
Key changes:
- Add --region flag for explicit region override (bypasses auto-discovery)
- Implement file-based region cache (~/.cache/armis-cli/region-cache.json)
- Add automatic retry without region hint when cached region auth fails
- Memoize cached region in AuthProvider to avoid repeated disk I/O
- Extract shared cache directory utility (util.GetCacheDir/GetCacheFilePath)
- Add comprehensive tests for region cache (client ID mismatch, corrupt
JSON, permissions, etc.)
Region selection priority:
1. --region flag - explicit override
2. Cached region - from previous successful auth
3. Auto-discovery - server tries regions until one succeeds
Addresses review findings:
- F1: No tests for region cache → 249 lines of tests added
- F2: No retry on stale cache → Retry logic with usingCachedHint flag
- F3: Redundant writes → Skip if region unchanged
- F4: Repeated disk I/O → Memoization via cachedRegion/regionLoaded
- F5: Duplicated cache constant → Extracted to util.CacheDirName
* fix(test): make cache tests Windows-compatible
- Skip file permissions test on Windows (Unix permissions not supported)
- Use filepath.Join for platform-agnostic path separators in test assertions
* fix(util): prevent path traversal in GetCacheFilePath (CWE-22)
Address PR review comments from Copilot:
- Reject absolute paths and path separators in cache filename parameter
to prevent filepath.Join from discarding the cache directory
- Add containment check to ensure result stays within cache directory
- Fix incorrect test assumptions about filepath.Join behavior
- Use temp directory in TestPackageLevelFunctions to avoid modifying
real user cache during tests
- Document ARMIS_REGION environment variable in FEATURES.md and CLAUDE.md
* fix(util): harden cache path validation and add region retry test
Address follow-up PR review comments:
- Reject empty, whitespace-only, ".", and ".." filenames in GetCacheFilePath
to prevent returning directory path instead of file path
- Replace strings.HasPrefix with filepath.Rel for robust path containment
check (handles case-insensitivity and path separator edge cases)
- Add TestAuthProvider_CachedRegionRetryOnFailure to cover region-caching
retry logic when auth fails with stale cached region
- Fix CLAUDE.md: ARMIS_REGION is for region-aware authentication,
not API URL selection
* fix(auth): add Bearer prefix to JWT Authorization header
The CLI was sending raw JWT tokens without the "Bearer" prefix,
but the backend middleware expects "Authorization: Bearer <token>"
per RFC 6750. This caused 401 errors when using JWT authentication.
Changes:
- auth.go: Return "Bearer " + token for JWT auth
- client.go: Update comments to match actual behavior
- auth_test.go: Update tests to expect Bearer prefix
* fix(auth): address PR review comments for region cache and retry logic
- Fix test containment assertion to use filepath.Rel instead of
strings.HasPrefix for robust path-boundary checking
- Bound RegionCache.Load file reads with 4KB size limit to prevent
memory exhaustion from corrupted cache files
- Add typed AuthError with HTTP status code to enable selective retry:
only retry on region-specific rejections (not 401/transport errors)
- Add deprecation warning when ARMIS_AUTH_ENDPOINT env var is set,
directing users to ARMIS_API_URL or --region
- Update CI docs to recommend JWT auth credentials
Copy file name to clipboardExpand all lines: CLAUDE.md
+3-2Lines changed: 3 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -43,7 +43,7 @@ go test -v ./internal/output/... -run TestHumanFormatter
43
43
44
44
### Core Packages
45
45
46
-
-`internal/auth/` - Authentication provider supporting two modes. JWT (priority): client credentials exchange at `/api/v1/authenticate`, auto-refresh 5min before expiry, tenant ID extracted from `customer_id` JWT claim. Basic (fallback): static token + explicit tenant ID. Implements `AuthHeaderProvider` interface used by the API client.
46
+
-`internal/auth/` - Authentication provider supporting two modes. JWT (priority): client credentials exchange at `/api/v1/auth/token`, auto-refresh 5min before expiry, tenant ID extracted from `customer_id` JWT claim. Basic (fallback): static token + explicit tenant ID. Implements `AuthHeaderProvider` interface used by the API client.
47
47
-`internal/api/` - API client for Armis Cloud. Two HTTP clients: one for general calls (60s timeout), one for uploads (streaming, no timeout, no retry). Functional options pattern (`WithHTTPClient()`, `WithUploadHTTPClient()`, `WithAllowLocalURLs()`). Upload uses `io.Pipe` streaming to avoid OOM on large files. Enforces HTTPS, validates presigned S3 URLs against SSRF.
48
48
-`internal/model/` - Data structures: `Finding` (23 fields), `ScanResult`, `Summary`, `Fix`, `FindingValidation` (with taint/reachability analysis), API response types (`NormalizedFinding`, pagination).
49
49
-`internal/output/` - Output formatters (human, json, sarif, junit) implementing the `Formatter` interface. `styles.go` defines ~50 lipgloss styles using Tailwind CSS color palette. `icons.go` defines Unicode constants (severity dots, box-drawing chars). `SyncColors()` switches between full-color and plain styles based on `cli.ColorsEnabled()`.
@@ -83,9 +83,10 @@ go test -v ./internal/output/... -run TestHumanFormatter
83
83
84
84
-`ARMIS_CLIENT_ID` - Client ID for JWT authentication (recommended)
85
85
-`ARMIS_CLIENT_SECRET` - Client secret for JWT authentication
86
-
-`ARMIS_AUTH_ENDPOINT` - JWT authentication service endpoint URL
87
86
-`ARMIS_API_TOKEN` - API token for Basic authentication (fallback)
88
87
-`ARMIS_TENANT_ID` - Tenant identifier (required only with Basic auth; JWT extracts it from token)
88
+
-`ARMIS_API_URL` - Override base URL for Armis API (advanced; defaults based on --dev flag)
89
+
-`ARMIS_REGION` - Override Armis cloud region (equivalent to `--region`; used for region-aware authentication)
0 commit comments