acmephp / symfony-bundle

dev-master / 1.0.x-dev 2016-03-24 08:35 UTC

This package is auto-updated.

Last update: 2024-09-22 21:54:09 UTC


README

注意:此插件处于**积极开发中(目前尚未准备好**)。

ACME 协议是由 Let's Encrypt 证书颁发机构定义的协议。您可以在https://letsencrypt.github.io/acme-spec/上查看完整规范。

ACME PHP 项目旨在在 PHP 中实现 ACME 协议,以便在各个项目中轻松使用。

此仓库是基于PHP 库的 Symfony 插件。

安装

步骤 1:使用 composer 下载 AcmePhpBundle

使用 composer Composer 需要 acmephp/symfony-bundle

$ composer require acmephp/symfony-bundle

步骤 2:启用插件

在内核中启用插件

<?php

// app/AppKernel.php
public function registerBundles()
{
    $bundles = array(
        // ...
        new AcmePhp\Bundle\AcmePhpBundle(),
        // ...
    );
}

步骤 3:配置 AcmePhpBundle

以下是一个使用 AcmePhpBundle 的配置示例,适用于您的应用程序

# app/config/config.yml

acme_php:
    contact_email: contact@mycompany.com
    default_distinguished_name:
        country: FR
        state: France
        locality: Paris
        organization_name: MyCompany
        organization_unit_name: IT
    domains:
        myapp.com: ~

步骤 4:导入 AcmePhpBundle 路由文件

激活并配置插件后,接下来要做的就是导入 AcmePhpBundle 路由文件。

# app/config/routing.yml

acme_php:
    resource: "@AcmePhpBundle/Resources/config/routing.xml"

使用方法

安装并配置插件后,您可以通过运行命令 acmephp:generate 请求证书

$ ./bin/console acmephp:generate

首次运行此命令时,AmePhpBundle 将向配置的证书颁发机构(默认为 Let's Encrypt)请求新的证书,并将生成的证书存储在配置的文件夹中(默认为 ~/.acmephp)。

自动续期

每次运行 acmephp:generate 命令时,证书将使用 90 天的有效期(由证书颁发机构定义)进行续期。您可以添加 crontab 来执行此任务。

$ crontab -e

0 0     1 * *     /var/www/my_app/bin/console acmephp:generate

在重新生成证书后,您需要重新加载 Web 服务器以考虑更改。

如果您在 /etc/cron.d/ 中使用专用 crontab 文件,请注意证书存储位置(默认在 $HOME 目录中配置),这与运行命令的用户相关。

配置参考

# app/config/config.yml

acme_php:
    # Certificates locations. Default: `~/.acmephp`
    # Beware to use a directory readable by the web server
    # It should be writable too, to store certificates, keys and challenges.
    certificate_dir: ~/.acmephp
    
    # Certificate Authority used to deliver certificates. Default: `letsencrypt`. Available values : `letsencrypt`
    # You can use your own Certificate Authority by :
    #  - implementing the CertificateAuthorityConfigurationInterface interface
    #  - registering the service with the tag "acme_php.certificate_authority" and with an alias to use here
    certificate_authority: letsencrypt

    # Email addresse associated to the account used to generate certificate
    contact_email: contact@mycompany.com
    
    # Default Distinguished Name (or a DN) informations used to request certificates.
    default_distinguished_name: # https://scotthelme.co.uk/setting-up-le/
        # Country Name (2 letter code)
        country: FR
        
        # State or Province Name (full name)
        state: France
        
        # Locality Name (eg, city)
        locality: Paris
        
        # Organization Name (eg, company)
        organization_name: MyCompany
        
        # Organizational Unit Name (eg, section)
        organization_unit_name: IT
        
        # Email Address. When missing, the adresse defined in the parameter contact_email will be used
        email_address: john.doe@mycompany.com
    
    # List of domains to request
    domains:
    
        myapp.com: ~

        www.myapp.com: ~

        invoice.myapp.com:
            # You can override default distinguished name define above for each domain
            organization_unit_name: sales

使用方法

您可以使用单个命令请求和续期证书

$ bin/console acmephp:generate

证书将存储在参数 certificate_dir 定义的文件夹中。

$ tree ~/.acmephp
├── account                   # Your account's keys
│   ├── private.pem
│   └── public.pem
├── challenges                # Pending challenges
├── domains                   # Contains all domain's certificate (1 sub directory per domain)
│   ├── company.com           # Contains the certificates for domain `company.com`
│   │   ├── cert.pem          # Server certificate only
│   │   ├── chain.pem         # All certificates that need to be served by the browser **excluding** server certificate
│   │   ├── combined.pem      # All certificates plus private key
│   │   ├── fullchain.pem     # All certificates, **including** server certificate
│   │   ├── private.pem       # Private key for the certificate
│   │   └── public.pem        # Public key for the certificate
│   └── www.company.com
│       └── ...
└── domains-backup            # Previous versions of the certificates
    ├── company.com           # domains as subdirectory
    │   └── 20160314-144416   # each subdirectory is a backup
    │       └── ...
    └── www.company.com
        └── ...

监控

如果您的应用程序使用 monolog(默认应该如此),Acme PHP Symfony Bundle 将在 acme_php 通道中记录。这样,您就可以处理日志并在续期失败时收到通知。

以下是一个配置示例

# app/config/config.yml

monolog:
    handlers:
        certificate_slack:
            type: slack
            token: # Your slack's token : https://api.slack.com/web
            channel: "#production" # name of the slack's channel
            bot_name: CertificatesBot
            icon_emoji: lock_with_ink_pen
            level: NOTICE
            channels: [acme_php]

扩展

证书颁发机构:您可以通过实现接口 AcmePhp\Bundle\Acme\CertificateAuthority\Configuration\CertificateAuthorityConfigurationInterface 并添加带有标签 acme_php.certificate_authority 的服务来添加自己的证书颁发机构,如下所示

# app/config/services.yml

services:
    app.custom_certificate_authority:
        class: AppBundle\Acme\CustomConfiguration
        public: false
        tags:
            - name: acme_php.certificate_authority
              alias: custom

您只需在配置中引用它即可

# app/config/config.yml

acme_php:
    certificate_authority: custom

域名加载器:默认情况下,插件通过配置文件加载域名配置。但是,您可以通过实现接口 AcmePhp\Bundle\Acme\Domain\Loader\LoaderInterface 并添加带有标签 acme_php.domains_configurations_loader 的服务来添加自己的加载器,如下所示

# app/config/services.yml

services:
    app.custom_certificate_authority:
        class: AppBundle\Acme\CustomLoader
        public: false
        tags:
            - name: acme_php.domains_configurations_loader

证书格式化器:当请求新的证书时,它将以多种格式(cert.pem、chain.pem、combined.pem 等)导出。您可以通过实现接口 AcmePhp\Bundle\Acme\Certificate\Formatter\FormatterInterface 并添加带有标签 acme_php.certificate_formatter 的服务来添加自己的格式化器,如下所示

# app/config/services.yml

services:
    app.custom_certificate_authority:
        class: AppBundle\Acme\CustomFormatter
        public: false
        tags:
            - name: acme_php.certificate_formatter

事件:AcmePhpBundle 触发了许多事件

  • CERTIFICATE_REQUESTED:当请求续订证书时
  • CHALLENGE_REQUESTED:当请求新的挑战时
  • CHALLENGE_CHECKED:当检查挑战时(无论是否已接受)
  • CHALLENGE_ACCEPTED:当挑战被接受时
  • CHALLENGE_REJECTED:当挑战被拒绝时

WebServer 配置示例

以下是常见 Web 服务器的一些基本配置。

Mozilla 提供了一个工具来生成更高级的配置:[https://mozilla.github.io/server-side-tls/ssl-config-generator/](https://mozilla.github.io/server-side-tls/ssl-config-generator/)

您还可以使用此工具检查您的在线证书:[https://www.ssllabs.com/ssltest/](https://www.ssllabs.com/ssltest/)

### Apache 2.2

# /etc/apache2/sites-available/<domain>.

<VirtualHost *:443>
    SSLEngine on
    SSLCertificateFile      /var/www/.acmephp/domains/<domain>/cert.pem
    SSLCertificateKeyFile   /var/www/.acmephp/domains/<domain>/private.pem
    SSLCACertificateFile    /var/www/.acmephp/domains/<domain>/chain.pem

    ...
</VirtualHost>
$ sudo service apache2 reload

### Apache 2.4

# /etc/apache2/sites-available/<domain>.

<VirtualHost *:443>
    SSLEngine on
    SSLCertificateFile      /var/www/.acmephp/domains/<domain>/fullchain.pem
    SSLCertificateKeyFile   /var/www/.acmephp/domains/<domain>/private.pem

    ...
</VirtualHost>
$ sudo service apache2 reload

### Nginx

# /etc/nginx/sites-available/<domain>.

server {
    listen 443 ssl default_server;
    server_name my-domain;

    ssl_certificate       /var/www/.acmephp/domains/<domain>/fullchain.pem
    ssl_certificate_key   /var/www/.acmephp/domains/<domain>/private.pem

    ...
}
$ sudo service nginx reload

haproxy

# /etc/haproxy/haproxy.cfg

frontend www
    bind :80
    bind :443 ssl crt /var/www/.acmephp/domains/<domain>/combined.pem

    ...
$ sudo service haproxy reload

贡献

单元测试

composer install

./bin/phpunit

功能性测试

composer install

docker run -d --net host acmephp/testing-ca
docker run --rm --net host martin/wait -c localhost:4000 -t 120
features/fixtures/TestApp/console acmephp:server:start

./bin/behat

features/fixtures/TestApp/console acmephp:server:stop

手动测试

由于 Let's Encrypt 有速率限制,我们建议使用 Boulder 作为证书颁发机构。它包含并完全打包在 docker 图像 acmephp/testing-ca 中。

您将在文件夹 features/fixtures/TestApp 中找到一个微型的 symfony 应用程序。

它允许您轻松测试应用程序。您只需编辑 features/fixtures/TestApp/config/config.yml 中的配置文件。然后启动 Boulder 和 symfony 服务器(处理挑战请求)。

composer install

# Launch boulder
docker run -d --net host acmephp/testing-ca
docker run --rm --net host martin/wait -c localhost:4000 -t 120

# Launche the application to listen to challenge checks
features/fixtures/TestApp/console acmephp:server:start

# Generate the certificate
features/fixtures/TestApp/console acmephp:generate

ls -al features/fixtures/TestApp/certs/domains/*/