stonemax / acme2 Goto Github PK
View Code? Open in Web Editor NEWAnother PHP client for acme protocal (version 2) implementation, used for generating letsencrypt's free ssl certificates.
License: MIT License
Another PHP client for acme protocal (version 2) implementation, used for generating letsencrypt's free ssl certificates.
License: MIT License
We did a manual renewal after the auto update apparently wiped our RSA key and ORDER data. But when we did so we got
forge@app-w-1:~/domain.com/current$ php artisan ssl-controller:update-certificate domain.com
+ Starting ...
In OrderService.php line 281:
Get order info failed, the local order info file doesn't exist, the order info file path is: /home/forge/domain.com/shared/storage/tls/le-storage/xxxxxxx/rsa/ORDER
which refers to
acme2/src/services/OrderService.php
Line 293 in 5b368e6
Any ideas why the RSA cert and everything got wiped post
stonemax\acme2\exceptions\RequestException ·\SslManager\Jobs\UpdateCertificate
Request to https://acme-v02.api.letsencrypt.org/acme/authz-v3/xxxxxx(GET) failed, the error number is: 35
and or later on this morning
stonemax\acme2\exceptions\RequestException · Request to https://acme-v02.api.letsencrypt.org/acme/new-order(POST) failed, the error number is: 28, the error message is: Operation timed out after 5000 milliseconds with 0 out of 0 bytes received
? Cause for certificates to be wiped out something odd must happen now?
I've been using this package for a project at work, and I've noticed a number of issues:
When local verification works, but Lets Encrypt's fails (this happened with me due to firewall allowing my connection, but blocked LE's), the order and the challenge objects gets stuck in an "invalid" status.
Any subsequent calls to getOrder() without clearing the order cache (specifying renewal = true may also fix it), will return the same order with the "invalid" status, and getPendingChallenges() will not return the invalid challenges either. This means you are practically unable to ever complete the order.
I fixed this in my forked copy by adding a new method: OrderService::clearCachedOrderInfo(), which I call if($order->status === 'invalid'). Though this can probably be done another way by making the getPendingChallenges() also return 'invalid' status challenges so they can be re-attempted (if they can; untested).
The infinite loops were also a problem for me. I am writing a program that needs to provision and periodically renew TLS certs for 2,500+ websites, having it hang because of a single validation failure is unacceptable, I'd rather it throw an exception so that I can manually intervene.
I fixed this by adding a AuthorizationService::$timeout property, set to a default of 10 seconds. All while() loops will throw an exception after that timeout.
Let's Encrypt has a "Failed Validation limit of 5 failures per account, per hostname, per hour.", so I added a new LocalVerificationFailedException, I can now determine the difference between local verification (which doesn't count towards this limit), and remote verification failures. My program needs to determine the difference between the two so it can keep a note of when it's near the limit.
I haven't put up a PR yet as I'm still working with the package, and will likely make further modifications. However, if there hasn't been any fixes by the time I'm done, I will submit one for each issue.
Please Act order by new order ready status - pull request https://github.com/stonemax/acme2/pull/28/files
In some cases, HTTP responses from Let's Encrypt have returned a 50x during Let's Encrypt downtime, or a rate limit was hit. This client should probably handle these gracefully. I would also suggest using Guzzle instead of curl, which allows greater flexibility in handling HTTP requests from PHP, such as adding a retry middleware.
From the Let's Encrypt docs here: https://letsencrypt.org/docs/integration-guide/
Renewal failure should not be treated as a fatal error. You should implement graceful retry logic in your issuing services using an exponential backoff pattern, maxing out at once per day per certificate. For instance, a reasonable backoff schedule would be: 1st retry after one minute, 2nd retry after ten minutes, third retry after 100 minutes, 4th and subsequent retries after one day. You should of course have a way for administrators to request early retries on a per-domain or global basis.
Backoffs on retry means that your issuance software should keep track of failures as well as successes, and check if there was a recent failure before attempting a fresh issuance. There’s no point in attempting issuance hundreds of times per hour, since repeated failures are likely to be persistent.
When something is wrong it will never stop until PHP timeout, and no error messages will be shown.
Getting error No order for ID 174665053107
on certificate renewal:
[2023-04-14 05:22:02] production.ERROR: Get order info failed, the order url is: https://acme-v02.api.letsencrypt.org/acme/order/1048670227/174665053107, the code is: 404, the header is: HTTP/2 404
server: nginx
date: Fri, 14 Apr 2023 03:22:02 GMT
content-type: application/problem+json
content-length: 113
cache-control: public, max-age=0, no-cache
link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index", the body is: Array
(
[type] => urn:ietf:params:acme:error:malformed
[detail] => No order for ID 174665053107
[status] => 404
)
{"exception":"[object] (stonemax\\acme2\\exceptions\\OrderException(code: 0): Get order info failed, the order url is: https://acme-v02.api.letsencrypt.org/acme/order/1048670227/174665053107, the code is: 404, the header is: HTTP/2 404
What is the recommended way to solve this?
Is it correct that Stonemax/ACME2 sets up one account for the generation of certificates of domains? Or does it create on on every certificate request?
FYI LE Doc on Accounts
_In ACME, it’s possible to create one account and use it for all authorizations and issuances, or create one account per customer. This flexibility may be valuable. For instance, some hosting providers may want to use one account per customer, and store the account keys in different contexts, so that an account key compromise doesn’t allow issuance for all of their customers.
However, for most larger hosting providers we recommend using a single account and guarding the corresponding account key well. This makes it easier to identify certificates belonging to the same entity, easier to keep contact information up-to-date, and easier to provide rate limits adjustments if needed. We will be unable to effectively adjust rate limits if many different accounts are used._
Any chance you would like to publish this to Packagist as a composer package?
Hi,
Ive noticed the code is throwing an exception while the order is in processing state. Please, have a look below:
[php7:error] [pid 26473] [client 10.101.10.3:60616] PHP Fatal error: Uncaught afagund\dcert\vendor\stonemax\exceptions\OrderException: Finalize order failed, the url is: https://acme-v02.api.letsencrypt.org/acme/finalize/31918417/1239798, the domain list is: www.andrefagundes.com, the code is: 400, the header is: HTTP/1.1 100 Continue\r\nExpires: Mon, 26 Mar 2018 22:55:52 GMT\r\nCache-Control: max-age=0, no-cache, no-store\r\nPragma: no-cache\r\n\r\nHTTP/1.1 400 Bad Request\r\nServer: nginx\r\nContent-Type: application/problem+json\r\nContent-Length: 132\r\nBoulder-Requester: 31918417\r\nReplay-Nonce: 1HWxYKLrp6_fGLu_mctqOPJQCa6jL5x40LFD-WHum3k\r\nExpires: Mon, 26 Mar 2018 22:55:52 GMT\r\nCache-Control: max-age=0, no-cache, no-store\r\nPragma: no-cache\r\nDate: Mon, 26 Mar 2018 22:55:52 GMT\r\nConnection: close, the body is: Array\n(\n [type] => urn:ietf:params:acme:error:malformed\n [detail] => Order's status ("processing") was not pending\n [status] => 400\n)\n in /var/www/html/app/vendor/stonemax/OrderService.php:514\nStack trace:\n#0 /var/www/html/app/vendor/stonemax/OrderService.php(384): afagund\dce in /var/www/html/app/vendor/stonemax/OrderService.php on line 514
Even though, the order is being finalized. I was not able to understand this piece of code. How is the order being finalized if it is throwing an exception while trying to finalize?
Thanks,
Andre
Where are failures to issue certificates normally logged to in the system?
Hi
Is it possible to add Authorization deactivation feature?
https://community.letsencrypt.org/t/authorization-deactivation/19860
` /**
* Get authorization info
* @return array
* @throws AuthorizationException
* @throws \stonemax\acme2\exceptions\RequestException
*/
public function getAuthorization()
{
list($code, $header , $body) = RequestHelper::get($this->authorizationUrl);
if ($code != 200)
{
throw new AuthorizationException("Get authorization info failed, the authorization url is: {$this->authorizationUrl}, the code is: {$code}, the header is: {$header}, the body is: ".print_r($body, TRUE));
}
$this->populate($body);
return array_merge($body, ['authorizationUrl' => $this->authorizationUrl]);
}`
this function will Throw A Problem
[0] AuthorizationException in AuthorizationService.php line 95 Get authorization info failed, the authorization url is: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/107542734, the code is: 405, the header is: HTTP/1.1 405 Method Not Allowed Server: nginx Date: Tue, 08 Sep 2020 01:36:57 GMT Content-Type: application/problem+json Content-Length: 103 Connection: keep-alive Cache-Control: public, max-age=0, no-cache Link: <https://acme-staging-v02.api.letsencrypt.org/directory>;rel="index", the body is: Array ( [type] => urn:ietf:params:acme:error:malformed [detail] => Method not allowed [status] => 405 )
SO,I need solve this Exception immediately。can you help me,thinks。
And,I notice You are chinese,May I add your contact information like qq or wechat?
Anytime I try to auth my domain with an alt name such as the base domain itself it causes the script to fail. I took the example and piped it into my DNS API. Am I missing something?
['*.example.com', 'example.com']
> wutno@box:~/Programs/CFLetsAutomate# php test.php
> Created _acme-challenge.example.com : 000000-liVj3YRs-EtEfzA-YXNz3YGnmP3pon-00000
> PHP Fatal error: Uncaught stonemax\acme2\exceptions\AuthorizationException: Verify example.com failed, the authorization status becomes invalid. in /home/wutno/Programs/CFLetsAutomate/vendor/stonemax/acme2/src/services/AuthorizationService.php:166
> Stack trace:
> #0 /home/wutno/Programs/CFLetsAutomate/vendor/stonemax/acme2/src/services/ChallengeService.php(94): stonemax\acme2\services\AuthorizationService->verify('dns-01')
> #1 /home/wutno/Programs/CFLetsAutomate/test.php(57): stonemax\acme2\services\ChallengeService->verify()
> #2 {main}
> thrown in /home/wutno/Programs/CFLetsAutomate/vendor/stonemax/acme2/src/services/AuthorizationService.php on line 166
>
maybe just a documentation issue, but how do I get a certificate with SAN? (eg one certificate for both example.com and www.example.com; or both example.com and *.example.com)
thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.