Check CAA record before issuing certificate#10258
Conversation
📝 WalkthroughWalkthroughThis change introduces support for DNS CAA record validation in the application. Two new environment variables, Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. 📜 Recent review detailsConfiguration used: .coderabbit.yaml 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
Security Scan Results for PRDocker Image Scan Results
Source Code Scan Results🎉 No vulnerabilities found! |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (5)
.env (2)
125-125: Consider DNS server choice for different environments.Google's public DNS (8.8.8.8) is appropriate for development, but production deployments might benefit from:
- Using system default DNS resolvers
- Configuring environment-specific DNS servers
- Consider privacy implications of using external DNS services
124-126: Address static analysis style issues.The dotenv-linter has identified several style issues that should be addressed for consistency:
Apply this diff to fix the ordering and formatting issues:
# Move the variables to maintain alphabetical order -_APP_STATS_USAGE_DUAL_WRITING_DBS=database_db_main -_APP_DOMAINS_DNS=8.8.8.8 -_APP_DOMAIN_TARGET_CAA='0 issue "digicert.com"' +_APP_DOMAIN_TARGET_CAA='0 issue "digicert.com"' +_APP_DOMAINS_DNS=8.8.8.8 +_APP_STATS_USAGE_DUAL_WRITING_DBS=database_db_main +Note: Reorder these variables to maintain alphabetical sorting and add a blank line at the end of the file.
src/Appwrite/Utopia/Response/Model/ConsoleVariables.php (1)
31-42: LGTM! Consider adding format validation for CAA records.The additions are well-structured and consistent with existing patterns. The default DNS server (8.8.8.8) is a good choice. However, since CAA records have a specific format (e.g., "0 issue "domain.com""), consider adding validation or documentation about the expected format to prevent configuration errors.
app/config/variables.php (1)
154-171: Improve environment variable descriptions for better clarity.The additions are correctly placed and structured. However, the descriptions could be enhanced:
- For
_APP_DOMAIN_TARGET_CAA: The format example is helpful, but consider explaining what CAA records do (authorize certificate issuers).- For
_APP_DOMAINS_DNS: Consider mentioning that an empty value will use the system's default DNS resolver.Apply this diff to improve the descriptions:
- 'description' => 'A CAA record value that can be used to validate custom domains. Format: "0 issue \"certainly.com\""', + 'description' => 'A CAA (Certification Authority Authorization) record value that specifies which certificate authorities are allowed to issue certificates for custom domains. Format: "0 issue \"certainly.com\""',- 'description' => 'DNS server to use for domain validation. Default: 8.8.8.8', + 'description' => 'DNS server to use for domain validation. Default: 8.8.8.8 (Google Public DNS). Leave empty to use system default DNS resolver.',tests/unit/Network/Validators/DNSTest.php (1)
51-72: Well-structured CAA validation tests with good error handling.The test implementation is solid with appropriate error handling for DNS resolution failures. Good coverage of positive and negative test cases.
Consider adding tests for:
- Different CAA record formats (e.g., "0 iodef", "0 issuewild")
- Invalid CAA record formats to ensure proper validation
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
composer.lockis excluded by!**/*.lock
📒 Files selected for processing (10)
.env(1 hunks)app/config/variables.php(1 hunks)app/controllers/api/console.php(1 hunks)app/controllers/api/proxy.php(1 hunks)composer.json(1 hunks)docker-compose.yml(4 hunks)src/Appwrite/Network/Validator/DNS.php(2 hunks)src/Appwrite/Platform/Workers/Certificates.php(1 hunks)src/Appwrite/Utopia/Response/Model/ConsoleVariables.php(1 hunks)tests/unit/Network/Validators/DNSTest.php(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: stnguyen90
PR: appwrite/appwrite#10119
File: app/controllers/api/account.php:1226-1232
Timestamp: 2025-07-08T01:20:14.364Z
Learning: In Appwrite, `_APP_DOMAIN` is a required environment variable that must always be set for the system to function properly.
📚 Learning: in appwrite, `_app_domain` is a required environment variable that must always be set for the system...
Learnt from: stnguyen90
PR: appwrite/appwrite#10119
File: app/controllers/api/account.php:1226-1232
Timestamp: 2025-07-08T01:20:14.364Z
Learning: In Appwrite, `_APP_DOMAIN` is a required environment variable that must always be set for the system to function properly.
Applied to files:
app/controllers/api/console.phpdocker-compose.yml.envapp/config/variables.php
🧬 Code Graph Analysis (3)
tests/unit/Network/Validators/DNSTest.php (1)
src/Appwrite/Network/Validator/DNS.php (3)
DNS(9-103)isValid(50-78)getLogs(39-42)
app/controllers/api/proxy.php (1)
src/Appwrite/Network/Validator/DNS.php (1)
DNS(9-103)
src/Appwrite/Platform/Workers/Certificates.php (1)
src/Appwrite/Network/Validator/DNS.php (1)
DNS(9-103)
🪛 dotenv-linter (3.3.0)
.env
[warning] 124-124: [UnorderedKey] The _APP_STATS_USAGE_DUAL_WRITING_DBS key should go before the _APP_STORAGE_ANTIVIRUS key
[warning] 125-125: [UnorderedKey] The _APP_DOMAINS_DNS key should go before the _APP_DOMAIN_FUNCTIONS key
[warning] 126-126: [EndingBlankLine] No blank line at the end of the file
[warning] 126-126: [UnorderedKey] The _APP_DOMAIN_TARGET_CAA key should go before the _APP_DOMAIN_TARGET_CNAME key
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Setup & Build Appwrite Image
- GitHub Check: Setup & Build Appwrite Image
- GitHub Check: scan
🔇 Additional comments (6)
app/controllers/api/console.php (1)
74-75: LGTM! Environment variables properly exposed.The new DNS-related environment variables are correctly retrieved and included in the console variables response, maintaining consistency with the existing pattern.
app/controllers/api/proxy.php (1)
260-264: LGTM! CAA validation properly integrated.The CAA record validation follows the established pattern used for A and AAAA records. The conditional check ensures the validator is only added when the environment variable is configured.
src/Appwrite/Platform/Workers/Certificates.php (1)
317-321: LGTM! CAA validation consistently implemented.The CAA record validation is properly integrated into the domain validation logic, following the same pattern used for other DNS record types. The conditional check and placement within the non-main domain validation block is appropriate.
docker-compose.yml (1)
123-124: Environment variables correctly propagated to relevant services.The new DNS-related environment variables are appropriately added to services that handle domain validation and certificate management. The placement is consistent with existing domain configuration variables.
Also applies to: 540-541, 711-712, 747-748
src/Appwrite/Network/Validator/DNS.php (2)
60-65: Good error handling implementation.The try-catch block properly handles DNS query failures and stores error details in logs for debugging. This is especially important for DNS operations which can fail due to network issues.
71-75: Clean implementation of DNS record validation.The iteration through records and comparison using
getRdata()is well-structured. The method properly handles the object-oriented response from the DNS client.
✨ Benchmark results
⚡ Benchmark Comparison
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
.env (1)
24-32: Keys inserted out of alphabetical order – failsdotenv-linter& hurts merge-diff clarity
dotenv-linteralready flags the new_APP_DNSand_APP_DOMAIN_TARGET_*keys. Re-ordering keeps the file deterministic and avoids future churn in unrelated PRs.Diff to relocate the new keys near the other
_APP_DOMAIN_*entries:-_APP_DNS=8.8.8.8 -_APP_DOMAIN_TARGET_CNAME=test.localhost -_APP_DOMAIN_TARGET_A=127.0.0.1 -_APP_DOMAIN_TARGET_AAAA=::1 -_APP_DOMAIN_TARGET_CAA=digicert.com +_APP_DNS=8.8.8.8 + +_APP_DOMAIN_TARGET_A=127.0.0.1 +_APP_DOMAIN_TARGET_AAAA=::1 +_APP_DOMAIN_TARGET_CAA=digicert.com +_APP_DOMAIN_TARGET_CNAME=test.localhost(Adapt positions to match the project’s exact ordering rules.)
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
composer.lockis excluded by!**/*.lock
📒 Files selected for processing (12)
.env(1 hunks)app/config/variables.php(1 hunks)app/controllers/api/console.php(1 hunks)app/controllers/api/proxy.php(1 hunks)app/views/install/compose.phtml(4 hunks)composer.json(1 hunks)docker-compose.yml(4 hunks)src/Appwrite/Network/Validator/DNS.php(2 hunks)src/Appwrite/Platform/Workers/Certificates.php(1 hunks)src/Appwrite/Utopia/Response/Model/ConsoleVariables.php(1 hunks)tests/e2e/Services/Console/ConsoleConsoleClientTest.php(1 hunks)tests/unit/Network/Validators/DNSTest.php(1 hunks)
✅ Files skipped from review due to trivial changes (4)
- app/controllers/api/proxy.php
- app/views/install/compose.phtml
- composer.json
- docker-compose.yml
🚧 Files skipped from review as they are similar to previous changes (7)
- src/Appwrite/Network/Validator/DNS.php
- app/config/variables.php
- app/controllers/api/console.php
- src/Appwrite/Platform/Workers/Certificates.php
- tests/unit/Network/Validators/DNSTest.php
- tests/e2e/Services/Console/ConsoleConsoleClientTest.php
- src/Appwrite/Utopia/Response/Model/ConsoleVariables.php
🧰 Additional context used
🪛 dotenv-linter (3.3.0)
.env
[warning] 24-24: [UnorderedKey] The _APP_DNS key should go before the _APP_EDITION key
[warning] 25-25: [UnorderedKey] The _APP_DOMAIN key should go before the _APP_EDITION key
[warning] 26-26: [UnorderedKey] The _APP_CONSOLE_DOMAIN key should go before the _APP_CONSOLE_HOSTNAMES key
[warning] 27-27: [UnorderedKey] The _APP_DOMAIN_FUNCTIONS key should go before the _APP_EDITION key
[warning] 28-28: [UnorderedKey] The _APP_DOMAIN_SITES key should go before the _APP_EDITION key
[warning] 29-29: [UnorderedKey] The _APP_DOMAIN_TARGET_CNAME key should go before the _APP_EDITION key
[warning] 30-30: [UnorderedKey] The _APP_DOMAIN_TARGET_A key should go before the _APP_DOMAIN_TARGET_CNAME key
[warning] 31-31: [UnorderedKey] The _APP_DOMAIN_TARGET_AAAA key should go before the _APP_DOMAIN_TARGET_CNAME key
[warning] 32-32: [UnorderedKey] The _APP_DOMAIN_TARGET_CAA key should go before the _APP_DOMAIN_TARGET_CNAME key
🔇 Additional comments (2)
.env (2)
24-24: Hard-coding Google’s 8.8.8.8 as default DNS may break installs in private networksGoogle’s public resolver is often blocked or unreachable inside corporate / air-gapped environments. Shipping it as the baked-in default means first-time deploys can silently fail at the new CAA check, even though the user’s local resolver would have worked. Consider:
- Leaving
_APP_DNSempty to fall back to the OS resolver, or- Documenting that the value must be overridden for production, or
- Using a safer placeholder like
resolver.example.com.Please verify downstream code paths don’t assume the variable is always present/non-empty.
32-32: Default CAA value “digicert.com” may not match your public CA policyIf Appwrite primarily issues certificates via Let’s Encrypt or other ACME CAs, having
digicert.comas the baked-in default could cause false negatives in CAA validation. A blank default (forcing ops to declare an explicit value) or a more neutral example such asletsencrypt.orgwould reduce surprises.Confirm that
digicert.comis indeed the intended CA across all deployment variants.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/Appwrite/Network/Validator/DNS.php (1)
56-57: Address the DNS server validation issue from previous review.This is the same issue flagged in the previous review. The DNS server configuration should be validated before passing to the Client constructor to prevent runtime errors.
The previous review comment is still valid. Please implement the suggested validation:
- $dnsServer = System::getEnv('_APP_DNS', '8.8.8.8'); - $dns = new Client($dnsServer); + $dnsServer = System::getEnv('_APP_DNS', '8.8.8.8'); + // Validate DNS server IP address + if (!filter_var($dnsServer, FILTER_VALIDATE_IP)) { + $dnsServer = '8.8.8.8'; // Fallback to Google DNS + } + $dns = new Client($dnsServer);
🧹 Nitpick comments (5)
tests/unit/Network/Validators/DNSTest.php (3)
69-69: Fix typo in comment.There's a typo in the comment: "becasue" should be "because".
- // Valid becasue no CAA record configured + // Valid because no CAA record configured
73-73: Fix typo in comment.Same typo here: "becasue" should be "because".
- // Valid becasue no CAA record configured + // Valid because no CAA record configured
51-76: Consider test stability with real domains.The test uses real external domains (github.com, test1.appwrite.org) which could make tests flaky if their DNS records change. Consider using mock DNS responses or dedicated test domains that you control.
For more stable tests, consider mocking the DNS client or using controlled test domains:
// Example with mocking approach $mockDns = $this->createMock(Client::class); $mockDns->method('query') ->willReturn([/* predictable test data */]);src/Appwrite/Network/Validator/DNS.php (2)
76-82: Simplify CAA record counting logic.The CAA record counting is unnecessary since you're already iterating through records. The count is only used once at line 101, which could be simplified.
Consider removing the counter and using a flag instead:
- $caaCount = 0; + $foundCaaRecords = false; - foreach ($query as $record) { - if ($record->getTypeName() === self::RECORD_CAA) { - $caaCount++; - } + foreach ($query as $record) { + if ($record->getTypeName() === self::RECORD_CAA) { + $foundCaaRecords = true; + } - if ($this->type === self::RECORD_CAA && $caaCount === 0) { + if ($this->type === self::RECORD_CAA && !$foundCaaRecords) {
101-104: Redundant CAA validation logic.This check for CAA records with count === 0 is redundant because it's already handled at lines 67-74 when the query is empty.
The empty query check at lines 67-74 already handles the case where no CAA records exist. This additional check is unnecessary and can be removed:
- if ($this->type === self::RECORD_CAA && $caaCount === 0) { - // No CAA records, means anyone can issue certificate - return true; - }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/Appwrite/Network/Validator/DNS.php(2 hunks)tests/unit/Network/Validators/DNSTest.php(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: stnguyen90
PR: appwrite/appwrite#10119
File: app/controllers/api/account.php:1226-1232
Timestamp: 2025-07-08T01:20:14.364Z
Learning: In Appwrite, `_APP_DOMAIN` is a required environment variable that must always be set for the system to function properly.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
- GitHub Check: Benchmark
- GitHub Check: E2E Service Test (VCS)
- GitHub Check: E2E Service Test (Storage)
- GitHub Check: E2E Service Test (Users)
- GitHub Check: E2E Service Test (Messaging)
- GitHub Check: E2E Service Test (Functions)
- GitHub Check: E2E Service Test (GraphQL)
- GitHub Check: E2E Service Test (Avatars)
- GitHub Check: E2E Service Test (FunctionsSchedule)
- GitHub Check: E2E Service Test (Databases)
- GitHub Check: E2E Service Test (Account)
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: E2E General Test
🔇 Additional comments (3)
src/Appwrite/Network/Validator/DNS.php (3)
5-6: LGTM! Proper imports added.The addition of Utopia\DNS\Client and Utopia\System\System imports is appropriate for the new DNS client functionality.
11-14: LGTM! Constants standardized and CAA support added.The DNS record constants are now properly uppercase and the new RECORD_CAA constant is added with helpful documentation.
62-65: LGTM! Proper error handling added.The exception handling properly captures DNS query errors and logs them for debugging while returning false for validation failure.
What does this PR do?
Verify domain has expected CAA record before issuing certificate
Test Plan
(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Screenshots may also be helpful.)
Related PRs and Issues
Checklist