Затворена бета на Let's Encrypt
Вчера от Let’s Encrypt ми изпратиха E-Mail, че домейните, за които съм поискал да бъдат подписани сертификати, са одобрени.
Let’s Encrypt
Let’s Encrypt е автоматизиран, отворен доставчик на (безплатни) удостоверителни услуги (на английски – Certificate Authority).
За повече информация, препоръчвам следните лекции:
- Let’s Encrypt - A Free Robotic Certificate Authority
- Let’s Encrypt - A Certificate Authority To Encrypt the Entire Web
Записване за бета програмата
Преди повече от месец, в Twitter акаунта на Let’s Encrypt беше обявено записване за бета програма, което ставаше, посредством попълване на Google формуляр. Въпреки че намерих за ироничен факта, че разчитат на Google, реших да изпратя заявка.
Формулярът беше изключително прост – поле, в което да изредиш за кои домейни искаш сертификати и поле за E-Mail адрес.
Начало на бета програмата
На 19-и октомври от Let’s Encrypt обявиха, че са получили cross-signatures за двата си intermediate сертификата, което означава, че подписаните от тях сертификати вече са доверени в браузърите.
Малко повече от седмица след това получих E-Mail, че домейните, за които съм поискал да бъдат подписани сертификати, са одобрени. Ето съдържанието на E-Mail-а:
From: Let’s Encrypt Beta <betaprogram@letsencrypt.org>
Date: Tue, Oct 27, 2015 at 5:14 PM
Subject: Let’s Encrypt Closed Beta Invite
To: [email here]
Greetings from Let’s Encrypt, [email here].
Thank you for your interest in our beta program! We’re excited to let you know that your domains (below) have been whitelisted, and you can now utilize an ACME client to obtain a certificate for them.
Quick Start
To use Let’s Encrypt’s official client to obtain your real certificates, you will need to provide the production API URL on the command line:
When running the Python client (installation directions [1]), be sure to specify the --server
argument with the production URL:
git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
./letsencrypt-auto --agree-dev-preview --server \
https://acme-v01.api.letsencrypt.org/directory auth
If you are using a different ACME client, be sure to configure it to use the production URL in order to get valid certificates. Many clients will default to the staging URL.
Known Issues
There are some known issues with the official Python client posted here: https://github.com/letsencrypt/letsencrypt/wiki/Known-issues
Renewals and Lifetimes
Certificates from Let’s Encrypt are valid for 90 days. We recommend renewing them every 60 days to provide a nice margin of error. As a beta participant, you should be prepared to manually renew your certificates at that time. As we get closer to General Availability, we hope to have automatic renewal tested and working on more platforms, but for now, please play it safe and keep track.
Rate Limiting
During this beta test we have very tight rate-limiting in place. We plan to loosen these limits as the beta proceeds.
There are two rate limits in play: Registrations/IP address
, and Certificates/Domain
.
Registrations/IP address
limits the number of registrations you can make in a given day; currently 10. This means you should avoid deleting the /etc/letsencrypt/accounts
folder, or you may not be able to re-register.
Certificates/Domain
you could run into through repeated re-issuance. This limit measures certificates issued for a given combination of Top Level Domain + Domain
. This means if you issue certificates for the following domains, at the end you would have what we consider 4 certificates for the domain example.com.
www.example.com
example.com www.example.com
webmail.example.com ldap.example.com
example.com www.example.com
The limit on Certificates/Domain
has a window of 60 days, to give 30 days for renewals. We know it’s restrictive at present; thank you for your patience in helping us ensure Let’s Encrypt is ready for the whole world.
Certificate Transparency
Part of our transparency mission includes publicly disclosing the certificates we issue via Certificate Transparency. Your email address is not publicly disclosed.
Helpful Information
Let’s Encrypt maintainence events are posted on https://letsencrypt.status.io/ and Twitter (@letsencrypt_ops). If you need help, both the Let’s Encrypt community at https://community.letsencrypt.org/ and #letsencrypt on irc.freenode.org are excellent sources of assistance.
If there are updates for Beta program participants, they will be posted at the community site at https://community.letsencrypt.org/t/beta-program-announcements/1631.
Your whitelisted domains are: …
След като набързо хвърлих едно око на изходния код на https://github.com/letsencrypt/letsencrypt, го клонирах на FreeBSD машината си и го изпробвах. Не ми допада, че letsencrypt-auto
трябва да се изпълни с root
привилегии, но изглежда работи доста чисто. Промените върху файловата система, които забелязах, са създаване на директории /etc/letsencrypt
, в която се помещават ключовете и сертификатите и ~/.local/share/letsencrypt
, в която е „виртуалната python среда“ на инструмента.
По подразбиране letsencrypt-auto
прави няколко неща:
- Създава средата, в която да се изпълни да се изпълни
letsencrypt
клиентът - Генерира чифт потребителски ключове, с които да се достъпва системата на Let’s Encrypt
- Пита за кои домейни искаш сертификат (с curses-базиран UI)
- Генерира 2048-битов ключ и CSR
- Валидира домейните
- Изпраща CSR-а за подпис
- Записва получения сертификат в
/etc/letsencrypt
, заедно с пълната му верига сертификати
Както споменах, не ми хареса нуждата да изпълня скрипта с административни права. Освен това, не ми хареса от колко неща зависи под FreeBSD:
bootstrap/freebsd.sh:
#!/bin/sh -xe
pkg install -Ay \
git \
python \
py27-virtualenv \
augeas \
libffi \
Изпълнението на този скрипт ми инсталира perl-5.20
и ми преинсталира(!) perl-5.18
, без очевидна нужда за това.
Валидацията на домейните ми също беше доста неприятна – като начало, скриптовете не откриват наличието на nginx и те изправят пред избор (в грозно форматиран текст, който прилича на stack trace на python) – да създадеш файл в /.well-known/
на уеб сървъра, който отговаря за дадения домейн, или да спреш уеб сървъра и да изпълниш Bash-python black voodoo magic заклинание, което пуска уеб сървър, който сервира нужните данни. Ето как изглежда съобщението, което се показва след приятния curses-базиран диалог за избор на домейни:
Bash-Python Black Voodoo Magic:
Make sure your web server displays the following content at
http://petko.me/.well-known/acme-challenge/al8Z37ePxkms5jo0WtqguLq2aT7sQEd_S1IubcFzpwU before continuing:
{"header": {"alg": "RS256", "jwk": {"e": "AQAB", "kty": "RSA", "n": "vhDQ-ssP5mgMd27zpovkmSD7oV3sjhTKdO2AU5N9GMkUMNsQ612dIa1sxXGErrW9WGlOa8EkPeK2T4JA5IBUNnuxJBJfT-EmT3suH2uW8klbFlJqHDIAHbnVZjVcrqKFS4Iuub5oaG0wPT4hPe4IKR3vob7DL7Yv0sgHwFFD0N8VWDCb6kG5HUqyvvMr6x0sPOyPQEzzJO-YWUwZM-FQ-sXLfxkBsI9hz9EqfaxvGV3wUVY_OOKMbKcyCM0e_sa7Vrd0jg_FEgHLW2dFVe1wdLLW4YEiimNHwINVloZxQ4QrSAaGI-aXJx1FojPGpkLwviSTmMGGC2MD7BSVqIzjiQ"}}, "payload": "eyJ0bHMiOiBmYWxzZSwgInRva2VuIjogImFsOFozN2VQeGttczVqbzBXdHFndUxxMmFUN3NRRWRfUzFJdWJjRnpwd1UiLCAidHlwZSI6ICJzaW1wbGVIdHRwIn0", "signature": "LCNiHNdZheeLCEcNG3JStH6J3pTZHqWL3Zne5AkzuFJ5NM8UQrhpAE-ie8E5VeXEGvXZFlJOpKU72rDmlaBQIyrWF1NLHh1A9vbTdPf_xa1lwVvASAFnvgcUU0c7o--5BegP4GEeWHkeOpqi5s45f-ktNUxtPuY9KrK_ByEQdcwfTcaUGwgOy86Oy-zVfyU45K6e-7fGahXLmrmcG9ADf4EQFVAx6Kax42kTkGl9oS-IiitQcCkc7pZA8nDWG_D6f5u01bBvBOn4PewBauajBr5fOX1StIi4ealnDKq0mcY4JlD8Efp6wAopqQAIoecHxCbiRUWULBevvW6wCzpUKA"}
Content-Type header MUST be set to application/jose+json.
If you don't have HTTP server configured, you can run the following
command on the target server (as root):
mkdir -p /tmp/letsencrypt/public_html/.well-known/acme-challenge
cd /tmp/letsencrypt/public_html
echo -n '{"header": {"alg": "RS256", "jwk": {"e": "AQAB", "kty": "RSA", "n": "vhDQ-ssP5mgMd27zpovkmSD7oV3sjhTKdO2AU5N9GMkUMNsQ612dIa1sxXGErrW9WGlOa8EkPeK2T4JA5IBUNnuxJBJfT-EmT3suH2uW8klbFlJqHDIAHbnVZjVcrqKFS4Iuub5oaG0wPT4hPe4IKR3vob7DL7Yv0sgHwFFD0N8VWDCb6kG5HUqyvvMr6x0sPOyPQEzzJO-YWUwZM-FQ-sXLfxkBsI9hz9EqfaxvGV3wUVY_OOKMbKcyCM0e_sa7Vrd0jg_FEgHLW2dFVe1wdLLW4YEiimNHwINVloZxQ4QrSAaGI-aXJx1FojPGpkLwviSTmMGGC2MD7BSVqIzjiQ"}}, "payload": "eyJ0bHMiOiBmYWxzZSwgInRva2VuIjogImFsOFozN2VQeGttczVqbzBXdHFndUxxMmFUN3NRRWRfUzFJdWJjRnpwd1UiLCAidHlwZSI6ICJzaW1wbGVIdHRwIn0", "signature": "LCNiHNdZheeLCEcNG3JStH6J3pTZHqWL3Zne5AkzuFJ5NM8UQrhpAE-ie8E5VeXEGvXZFlJOpKU72rDmlaBQIyrWF1NLHh1A9vbTdPf_xa1lwVvASAFnvgcUU0c7o--5BegP4GEeWHkeOpqi5s45f-ktNUxtPuY9KrK_ByEQdcwfTcaUGwgOy86Oy-zVfyU45K6e-7fGahXLmrmcG9ADf4EQFVAx6Kax42kTkGl9oS-IiitQcCkc7pZA8nDWG_D6f5u01bBvBOn4PewBauajBr5fOX1StIi4ealnDKq0mcY4JlD8Efp6wAopqQAIoecHxCbiRUWULBevvW6wCzpUKA"}' > .well-known/acme-challenge/al8Z37ePxkms5jo0WtqguLq2aT7sQEd_S1IubcFzpwU
# run only once per server:
$(command -v python2 || command -v python2.7 || command -v python2.6) -c \
"import BaseHTTPServer, SimpleHTTPServer; \
SimpleHTTPServer.SimpleHTTPRequestHandler.extensions_map = {'': 'application/jose+json'}; \
s = BaseHTTPServer.HTTPServer(('', 80), SimpleHTTPServer.SimpleHTTPRequestHandler); \
s.serve_forever()"
Press ENTER to continue
Първият вариант ми се стори по-приятен, въпреки великата глупост, че трябва на ръка да се зададе в конфигурацията на web сървъра какъв content type трябва да има дадения файл. За нещастие, по някаква причина не сработи при мен и се наложи да прибягна до втория вариант.
Втория вариант проработи за един домейн, но не и ако бях задал два – petko.me www.petko.me
.
За всяко ново изпълнение на letsencrypt-auto
се генерира нов (2048-битов!) частен ключ. Няма очевиден начин за увеличаване на големината на ключа или да указване на вече съществуващ такъв. След ровене открих, че има --csr
параметър, който обаче при мен не проработи.
В крайна сметка според мен letsencrypt-auto
не трябва да бъде използван.
Алтернативен инструмент
В крайна сметка изискванията ми са следните:
- Искам сертификат, подписан от Let’s Encrypt
- Искам да преизползвам частния ключ на сегашния си сертификат, за да не отрежа достъпа на клиентите (имам конфигуриран HPKP)
- Искам да ми бъде върнат подписания сертификат като текст, с който да работя, както сметна за добре
- Не искам да изпълнявам каквото и да е като
root
- Не искам да инсталирам излишни пакети
Предосатвеният от Let’s Encrypt инструмент не успя да отговори на изискванията ми. За щастие попаднах на https://github.com/diafygi/letsencrypt-nosudo. Със скрипта от това репо и с долния модифициран шелскрипт (разчита key.pem и openssl.cnf да са в работната директория), успях да се сдобия с подписан сертификат за petko.me
и www.petko.me
.
letsencrypt/examples/generate-csr-existing-key.sh:
#!/bin/sh
# This script generates a simple SAN CSR to be used with Let's Encrypt
# CA. Mostly intended for "auth --csr" testing, but, since it's easily
# auditable, feel free to adjust it and use it on your production web
# server.
if [ "$#" -lt 1 ]
then
echo "Usage: $0 domain [domain...]" >&2
exit 1
fi
domains="DNS:$1"
shift
for x in "$@"
do
domains="$domains,DNS:$x"
done
SAN="$domains" openssl req -config "${OPENSSL_CNF:-openssl.cnf}" \
-new -nodes -subj '/' -reqexts san \
-key key.pem \
-out "${CSR_PATH:-csr.der}" \
-outform DER
echo "You can now run: letsencrypt auth --csr ${CSR_PATH:-csr.der}"
Заключение
Мъка. Но има светлина в тунела.