Skip to content
This repository has been archived by the owner on Feb 13, 2020. It is now read-only.
/ yalec Public archive

Yalec - Yet anther lets encrypt client

License

Notifications You must be signed in to change notification settings

afosto/yalec

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This package is abandoned. Look at yaac

Yalec - Yet another Lets Encrypt client

Written in PHP, this client aims to be a decoupled LetsEncrypt client, based on ACME V2.

Decoupled from a filesystem or webserver

In stead of, for example writing the certificate to the disk under an nginx configuration, this client just returns the data (the certificate and private key).

Why

Why whould I need this package? At Afosto we run our software in a multi tenant setup, as any other SaaS would do, and therefore we cannot make use of the many clients that are already out there.

Almost all clients are coupled to a type of webserver or a fixed (set of) domain(s). This package can be extremely useful in case you need to dynamically fetch and install certificates.

Requirements

  • PHP7+
  • openssl
  • Flysystem (any adapter would do) - to store the Lets Encrypt account information

Getting started

Getting started is easy. First install the client, then you need to construct a flysystem filesystem, instantiate the client and you can start requesting certificates.

Installation

Installing this package is done easily with composer.

composer require afosto/yalec

Instantiate the client

To start the client you need 3 things; a username for your LetsEncrypt account, a bootstrapped Flysystem and you need to decide whether you want to issue Fake LE Intermediate X1 (staging: MODE_STAGING) or Let's Encrypt Authority X3 (live: MODE_LIVE, use for production) certificates.

use League\Flysystem\Filesystem;
use League\Flysystem\Adapter\Local;
use Afosto\LetsEncrypt\Client;
 
//Prepare flysystem
$adapter = new Local('data');
$filesystem = new Filesystem($adapter);
 
//Construct the client
$client = new Client([
    'username' => '[email protected]',
    'fs'       => $filesystem,
    'mode'     => Client::MODE_STAGING,
]);

While you instantiate the client, when needed a new LetsEcrypt account is created and then agrees to the TOS.

Create an order

To start retrieving certificates, we need to create an order first. This is done as follows:

$order = $client->createOrder(['example.org', 'www.example.org']);

In the example above the primary domain is followed by a secondary domain(s). Make sure that for each domain you are able to prove ownership. As a result the certificate will be valid for all provided domains.

Prove ownership

Before you can obtain a certificate for a given domain you need to prove that you own the given domain(s). In this example we will show you how to do this for http-01 validation (where serve specific content at a specific url on the domain, like: example.org/.well-known/acme-challenge/*).

Obtain the authorizations for order. For each domain supplied in the create order request an authorization is returned.

$authorizations = $client->authorize($order);

You now have an array of Authorization objects. These have the challenges you can use (both DNS and HTTP) to provide proof of ownership.

Use the following example to get the HTTP validation going. First obtain the challenges, the next step is to make the challenges accessible from

foreach ($authorizations as $authorization) {
    $challenge = $authorization->getHttpChallenge();

    $file = $authorization->getFile($challenge);
    file_put_contents($file->getFilename(), $file->getContents());   
}

Now that the challenges are in place and accessible through example.org/.well-known/acme-challenge/* we can request validation.

Request validation

Next step is to request validation of ownership. For each authorization (domain) we ask LetsEncrypt to verify the challenge.

foreach ($authorizations as $authorization) {
    $ok = $client->validate($authorization->getHttpChallenge(), 15);
}

The method above will perform 15 attempts to ask LetsEncrypt to validate the challenge (with 1 second intervals) and retrieve an updated status (it might take Lets Encrypt a few seconds to validate the challenge).

Get the certificate

Now to know if validation was successful, test if the order is ready as follows:

if ($client->isReady($order)) {
    //The validation was successful.
}

We now know validation was completed and can obtain the certificate. This is done as follows:

$certificate = $client->getCertificate($order);

We now have the certificate, to store it on the filesystem:

//Store the certificate and private key where you need it
file_put_contents('certificate.cert', $certificate->getCertificate());
file_put_contents('private.key', $certificate->getPrivateKey());