Commit graph

24 commits

Author SHA1 Message Date
Andras Bacsai
5b9146d8df Fix: Preserve clean docker_compose_raw without Coolify additions
The previous fix (a956e11b3) incorrectly set docker_compose_raw to the
fully processed compose file, which included all Coolify additions like
labels, environment variables, networks, and modified container names.

This broke the separation between user input (docker_compose_raw) and
Coolify's processed output (docker_compose).

Changes:
- Store original compose at parser start before any processing
- Only remove content/isDirectory fields from original compose
- Save clean version to docker_compose_raw
- Save fully processed version to docker_compose

Now docker_compose_raw contains:
✓ Original user input with only content fields removed
✓ User's template variables ($SERVICE_FQDN_*, $SERVICE_URL_*)
✓ User's original labels and environment variables

And docker_compose contains:
✓ All Coolify additions (labels, networks, COOLIFY_* env vars)
✓ Modified container names with UUIDs
✓ Resolved template variables

Added comprehensive unit tests to verify the fix.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 19:07:12 +02:00
Andras Bacsai
a956e11b3e Fix: Remove content from docker_compose_raw to prevent file overwrites
When users define volumes with content: in compose files, the content
was being removed from docker_compose but not docker_compose_raw.
This caused files to be overwritten on every deployment/save when
users edited the compose file.

Now both docker_compose and docker_compose_raw are updated with the
cleaned version (without content:), allowing users to freely edit
files in the persistent storage view without them being overwritten.

The content: field now acts as an initial value only - it creates
the file on first deployment, then is removed so users have full
control over file contents.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 17:09:36 +02:00
Andras Bacsai
97868c3264 feat: allow safe environment variable defaults in array-format volumes
Changes:
- Extended validateDockerComposeForInjection to recognize env vars with defaults
- Added pattern check for ${VAR:-default} format alongside simple ${VAR} check
- Maintains consistency with parseDockerVolumeString behavior for string format

Test coverage:
- Added test for safe environment variable defaults in array format
- Verifies ${DATA_PATH:-./data} is allowed in array-format volumes
- All 79 security tests pass (215 assertions)

This allows users to specify environment variables with safe default values
in array-format Docker Compose volumes, matching the behavior already
supported in string-format volumes.
2025-10-16 09:51:37 +02:00
Andras Bacsai
a219f2e80e fix: use canonical parser for Windows path validation
Problem:
- validateVolumeStringForInjection used explode(':') to parse volume strings
- This incorrectly splits Windows paths like "C:\host\path:/container" at the drive letter colon
- Could lead to false positives/negatives in injection detection

Solution:
- Replace custom parsing in validateVolumeStringForInjection with call to parseDockerVolumeString
- parseDockerVolumeString already handles Windows paths, environment variables, and performs validation
- Eliminates code duplication and uses single source of truth for volume string parsing

Tests:
- All 77 existing security tests pass (211 assertions)
- Added 6 new Windows path tests (8 assertions)
- Fixed pre-existing test bug: preg_match returns int 1, not boolean true

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 09:51:37 +02:00
Andras Bacsai
3700f78355 refactor: preserve exception chain in validation error handling
When catching and re-throwing exceptions, preserve the original exception
chain by passing the caught exception as the third parameter to new Exception.
This retains the full stack trace for debugging while keeping descriptive
error messages.

Changes:
- validateDockerComposeForInjection(): 4 locations fixed
- validateVolumeStringForInjection(): 3 locations fixed

Before:
  throw new \Exception('Invalid Docker volume definition: '.$e->getMessage());

After:
  throw new \Exception('Invalid Docker volume definition: '.$e->getMessage(), 0, $e);

Benefits:
- Full stack trace preserved for debugging
- Original exception context retained
- Better error diagnostics in production logs

All 60 security tests pass (176 assertions).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 09:51:37 +02:00
Andras Bacsai
334559bb0b Update bootstrap/helpers/parsers.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-10-16 09:51:37 +02:00
Andras Bacsai
cb1f571eb4 fix: prevent command injection in Docker Compose parsing - add pre-save validation
This commit addresses a critical security issue where malicious Docker Compose
data was being saved to the database before validation occurred.

Problem:
- Service models were saved to database first
- Validation ran afterwards during parse()
- Malicious data persisted even when validation failed
- User saw error but damage was already done

Solution:
1. Created validateDockerComposeForInjection() to validate YAML before save
2. Added pre-save validation to all Service creation/update points:
   - Livewire: DockerCompose.php, StackForm.php
   - API: ServicesController.php (create, update, one-click)
3. Validates service names and volume paths (string + array formats)
4. Blocks shell metacharacters: backticks, $(), |, ;, &, >, <, newlines

Security fixes:
- Volume source paths (string format) - validated before save
- Volume source paths (array format) - validated before save
- Service names - validated before save
- Environment variable patterns - safe ${VAR} allowed, ${VAR:-$(cmd)} blocked

Testing:
- 60 security tests pass (176 assertions)
- PreSaveValidationTest.php: 15 tests for pre-save validation
- ValidateShellSafePathTest.php: 15 tests for core validation
- VolumeSecurityTest.php: 15 tests for volume parsing
- ServiceNameSecurityTest.php: 15 tests for service names

Related commits:
- Previous: Added validation during parse() phase
- This commit: Moves validation before database save

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 09:51:37 +02:00
Andras Bacsai
ce12c94709 fix: prevent duplicate services on image change and enable real-time UI refresh
This commit addresses two critical issues with Docker Compose service management:

## Issue 1: Duplicate Services Created on Image Change
When changing the image in a docker-compose file, the parser was creating new
ServiceApplication/ServiceDatabase records instead of updating existing ones.

**Root Cause**: The parsers used `firstOrCreate()` with `['name', 'image', 'service_id']`,
meaning any image change would create a new record.

**Fix**: Remove `image` from `firstOrCreate()` queries and update it separately after
finding or creating the service record.

**Changes**:
- `bootstrap/helpers/parsers.php` (serviceParser v3): Fixed in presave loop (lines 1188-1203)
  and main parsing loop (lines 1519-1539)
- `bootstrap/helpers/shared.php` (parseDockerComposeFile v2): Fixed null check logic
  (lines 1308-1348)

## Issue 2: UI Not Refreshing After Changes
When compose file or domain was modified, the Configuration component wasn't receiving
events to refresh its data, requiring manual page refresh to see updates.

**Root Cause**: The Configuration component wasn't listening for refresh events dispatched
by child components (StackForm, EditDomain).

**Fix**: Add event listeners and dispatchers to enable real-time UI updates.

**Changes**:
- `app/Livewire/Project/Service/Configuration.php`: Added listeners for `refreshServices`
  and `refresh` events (lines 36-37)
- `app/Livewire/Project/Service/EditDomain.php`: Added `refreshServices` dispatch (line 76)
- Note: `app/Livewire/Project/Service/StackForm.php` already had the dispatch

## Tests Added
- `tests/Unit/ServiceParserImageUpdateTest.php`: 4 tests verifying no duplicates created
- `tests/Unit/ServiceConfigurationRefreshTest.php`: 4 tests verifying event dispatching

All 8 new tests pass, and all existing unit tests continue to pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 10:12:36 +02:00
Andras Bacsai
f8e97501ce feat(deployments): generate SERVICE_NAME environment variables from Docker Compose services
- Added functionality to generate environment variables for each service defined in the Docker Compose file, transforming service names into uppercase and replacing special characters.
- Updated the service parser to merge these generated variables with existing environment variables, enhancing deployment configuration.
2025-10-03 09:41:59 +02:00
Andras Bacsai
708a08fdd6 fix(application): enhance domain handling by replacing both dots and dashes with underscores for HTML form binding 2025-09-25 13:19:12 +02:00
Andras Bacsai
5b3b4bbc43 refactor(environment): remove 'is_build_time' attribute from environment variable handling across the application to simplify configuration 2025-09-11 16:51:56 +02:00
Andras Bacsai
501e6a2650 refactor(environment): standardize service name formatting by replacing '-' and '.' with '_' in environment variable keys 2025-09-11 13:59:02 +02:00
Arnaud B
e23ab1e621
feat(deployment): add SERVICE_NAME variables for service discovery
This change introduces automatically generated `SERVICE_NAME_<SERVICE>`
environment variables for each service within a Docker Compose deployment.
This allows services to reliably reference each other by name, which is particularly
useful in pull request environments where container names are dynamically suffixed.

- The application parser now generates and injects these `SERVICE_NAME` variables
   into the environment of all services in the compose file.
- `ApplicationDeploymentJob` is updated to correctly handle and filter these
  new variables during deployment.
- UI components and the `EnvironmentVariableProtection` trait have been updated
to make these generated variables read-only, preventing accidental modification.

This commit introduces two new helper functions to standardize resource naming
for pull request deployments:

-  `addPreviewDeploymentSuffix()`: Generates a consistent suffix format (-pr-{id})
   for resource names in preview deployments
-  `generateDockerComposeServiceName()`: Creates SERVICE_NAME environment variables
   for Docker Compose services
2025-09-08 15:22:44 +02:00
Andras Bacsai
efc1264810 fix(parsers): do not modify service names, only for getting fqdns and related envs 2025-08-27 21:22:04 +02:00
Andras Bacsai
3e816c8281 refactor(parsers): remove unnecessary hyphen-to-underscore replacement for service names in serviceParser function 2025-08-27 18:36:58 +02:00
Andras Bacsai
cde528bf5e fix(parsers): enhance volume string handling by preserving mode in application and service parsers. Update related unit tests for validation. 2025-08-27 16:54:49 +02:00
Andras Bacsai
5fbad08e45 fix(parsers): implement parseDockerVolumeString function to handle various Docker volume formats and modes, including environment variables and Windows paths. Add unit tests for comprehensive coverage. 2025-08-27 16:39:38 +02:00
Andras Bacsai
4a1eb064a4 fix(parsers): replace hyphens with underscores in service names for consistency. this allows to properly parse custom domains in docker compose based applications 2025-08-27 16:22:37 +02:00
Andras Bacsai
460198bb05 fix(application): clear Docker Compose specific data when switching away from dockercompose 2025-08-18 11:31:14 +02:00
Andras Bacsai
be34c0c2b4 refactor(parsers): update volume parsing logic to use beforeLast and afterLast for improved accuracy 2025-08-17 18:36:28 +02:00
Andras Bacsai
970fd3d9e6 refactor(parsers): streamline domain handling in applicationParser and improve DNS validation logic 2025-08-12 10:07:11 +02:00
Andras Bacsai
936a192236 fix(parsers): clarify comments and update variable checks for FQDN and URL handling 2025-08-12 10:06:19 +02:00
Andras Bacsai
e8892b3d29 feat(core): finally fqdn is fqdn and url is url. haha 2025-08-12 10:06:19 +02:00
Andras Bacsai
a0bc4dac55 fix(application): streamline environment variable updates for Docker Compose services and enhance FQDN generation logic 2025-08-12 10:06:19 +02:00