• Время чтения ~11 мин
  • 25.04.2023

Защита вашего приложения Laravel с помощью SSL-сертификата имеет решающее значение для обеспечения того, чтобы трафик от и к вашему приложению всегда был зашифрован. Некоторые SSL-сертификаты бесплатны, в то время как другие должны быть приобретены и предоставляются центрами сертификации, такими как letsencrypt и Cloudflare.

Создание этих сертификатов вручную может стать утомительной задачей, особенно если вы не знаете, с чего начать.

Certbot приходит на помощь, предоставляя бесплатный и автоматизированный способ создания и обновления этих сертификатов.

Для этого требуется ручное создание сертификатов через Certbot. Вы можете узнать больше о том, как добавить SSL-сертификаты после развертывания приложения в рабочей среде.

Иногда нам может потребоваться создать эти сертификаты в большом масштабе, особенно в многопользовательском приложении. Хорошим примером является Slack. Slack предоставляет каждой команде уникальный поддомен, например team.slack.com.

Используя ту же аналогию, мы также можем предоставить пользователям бесплатные поддомены, как только они будут подключены к нашему многопользовательскому приложению или как только они предоставят свои собственные домены. Нам также нужно будет сгенерировать SSL-сертификаты для этих доменных имен.

Нам нужно найти способ генерировать SSL-сертификаты в большом масштабе. Существует несколько способов решения этой проблемы, например, использование сервера Caddy. Сервер Caddy предоставляет бесплатные SSL-сертификаты для каждого хоста, что упрощает добавление технологии в наш стек.

Другой вариант — использовать Certbot и генерировать эти сертификаты, если мы используем Apache или Nginx. В этом уроке я продемонстрирую, как автоматизировать эту задачу для подхода на основе Nginx.

Это продолжение этой статьи, в которой мы создали простую службу сокращения URL-адресов и добавили функцию, позволяющую пользователям добавлять свои личные домены.

Мы сгенерируем SSL-сертификаты, как только пользователи добавят свои собственные доменные имена в систему и обновят свои записи DNS, чтобы они указывали на наш сокращатель URL-адресов.

Рефакторинг кода

В предыдущей части этой серии мы хранили доменные имена в таблице пользователя. Хотя это хорошо для простого сокращения URL-адресов, в большинстве случаев у клиента может быть несколько доменных имен. Поэтому нам понадобится способ обработки нескольких доменов для одного и того же пользователя.

Мы создадим новый файл миграции, который удалит столбец домена из таблицы users

php artisan make:migration drop_domain_column_from_users_table --table=users
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('domain');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('domain')->nullable()->after('email');
        });
    }
};

Затем мы создадим новую модель домена, которая будет содержать все доменные имена.

php artisan make:model Domains -m
<?php

namespace App\Models;

use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class Domains extends Model
{
    use HasFactory;

    protected $guarded= [];

    public function user()
    {
        return $this->belongsTo(User::class, 'user_id');
    }
}

Модель доменов

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('domains', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
            $table->string('domain');
            $table->boolean('status')->default(0);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('domains');
    }
};

Файл

миграции доменов Теперь пользователь сможет добавлять в систему несколько доменов.

Давайте теперь разберемся с DNS-стороной вещей.

Работа с DNS

Система доменных имен — это служба, которая помогает преобразовать удобочитаемые доменные имена, такие как iankumu.com, в IP-адреса

. Для нашего сокращателя URL-адресов мы позволяли пользователям добавлять свои собственные домены. Это означает, что нам нужно предоставить им некоторые записи DNS, которые они добавят своим поставщикам DNS, чтобы завершить сопоставление с нашим приложением

сокращения. Есть две записи, которые мы можем использовать: записи A или записи Cname. Запись сопоставляет доменное имя с IP-адресом, а запись Cname сопоставляет одно доменное имя с другим.

Вы можете прочитать это руководство, чтобы понять их различия и какой из них выбрать. В зависимости от ваших потребностей вы можете выбрать один или другой.

Для моего случая я выберу записи Cname. Я попрошу пользователей добавить запись Cname, указывающую на short.app.com

Поэтому в своих DNS-записях на Namecheap я добавлю эту запись в личный домен, который я хочу использовать в сокращателе URL-адресов.

Type Host Value TTL
CNAME Record go short.app.com Automatic
Namecheap DNS Records

Это сопоставит go.example.com домена с short.app.com.

После этого мой личный домен готов к использованию.

Установка certbot

В предыдущей части этого урока мы установили Nginx на наш сервер. Теперь мы хотим установить Certbot.

Мы можем следовать этому руководству, чтобы установить Certbot на Nginx.

Генерация SSL-сертификатов с помощью laravel и certbot.

Теперь, когда уровень DNS установлен и Certbot установлен, мы можем генерировать SSL-сертификаты для пользователей.

Прежде чем создавать какие-либо SSL-сертификаты, нам сначала нужно убедиться, что записи DNS распространяются правильно. Мы будем использовать вспомогательную функцию dns_get_record для получения DNS-записей доменного имени.

//App/Utils/DomainHelper.php

<?php

namespace App\Utils;

class DomainHelper
{
    public $isfound = false;

    public function verifycname($domain)
    {
        $domain = parse_url($domain);

        $host = array_key_exists('host', $domain) ? $domain['host'] : $domain['path'];

        $records = dns_get_record($host, DNS_CNAME);

        if (!empty($records)) {
            foreach ($records as $record) {
                if ($record['target'] == "short.app.com") {
                    $this->isfound = true;
                    break;
                } else {
                    $this->isfound = false;
                }
            }
        } else {
            $this->isfound = false;
        }

        return $this->isfound;
    }
}

Распространение записей DNS может занять до 48 часов, поэтому нам нужно иметь способ проверить, распространились ли записи DNS.

Вы можете запланировать задание для выполнения этих проверок. В моем случае я просто пропущу эту часть. Как только записи распространятся, мы добавим домен в очередь на генерацию SSL.

Создание SSL-сертификатов Следующим шагом является создание SSL-сертификатов

. Мы будем использовать новый фасад Process для работы с Certbot. Это позволит нам запускать внешние процессы из нашего приложения Laravel.

Мы создадим новую конфигурацию в файле config/services.php , которая позволит нам изменить среду Certbot в зависимости от наших потребностей.

//config/services.php
<?php

...

'certbot' => [
        'test' => env('CERTBOT_TEST', true)
    ]

...

Эта конфигурация поможет нам определить, какую команду Certbot запустить.

//App/Utils/SSLManager.php
<?php

namespace App\Utils;

use App\Models\User;
use App\Models\Domains;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Process;

class SSLManager
{
    public function generateSSL($domain, $email = null)
    {
        $command = $this->certbot_command($domain, $email);

        $certbot = Process::path(base_path())->start($command);

        $process = $certbot->wait();

        if ($process->successful()) {
            return $process->output();
        }


    }

    public function certbot_command($domain, $email): string
    {

        if (config('services.certbot.test') == true) {
            $command = "sudo certbot certonly --nginx --agree-tos --no-eff-email -d $domain --email $email --test-cert";
        } else {
            $command = "sudo certbot certonly --nginx --agree-tos --no-eff-email -d $domain --email $email";
        }

        return $command;
    }

Мы используем флаг certonly, чтобы указать certbot только генерировать SSL-сертификат, но не обновлять файл конфигурации Nginx. Это связано с тем, что мы хотим подготовить пользовательский файл конфигурации Nginx для всех доменов в нашей системе.

Мы также используем флаг –test-cert для использования промежуточной среды , предоставляемой Let's encrypt. Это поможет увеличить лимит сертификатов на домен до 30 000 в неделю и предоставит нам тестовые SSL-сертификаты, которые мы можем использовать для проверки нашей логики.

В производственной среде один домен может запрашивать только 5 сертификатов в неделю.

Давайте теперь подготовим простой конфигурационный файл, который будет проксировать запросы к нашему сокращателю URL-адресов.

//App/Utils/SSLManager.php
<?php

...

public function nginx_config($domain): string
    {
        $host = "short.app.com";

        $content = "
        server {
            if (\$host = $domain) {
               return 301 https://\$host\$request_uri;
            }
            listen 80;
            listen [::]:80;
            server_name $domain;
        }
        server {
            listen 443 ssl http2;
            listen [::]:443 ssl http2;
            server_name $domain;
            return 301 https://$host\$request_uri;
            resolver 8.8.8.8;
            location / {
                include proxy_params;
                proxy_pass https://$host\$request_uri;
                proxy_set_header Host $domain;
                proxy_set_header X-Forwarded-Host \$http_host;
                proxy_set_header X-Real-IP \$remote_addr;
                proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto \$scheme;
                proxy_redirect off;
                proxy_http_version 1.1;
                proxy_set_header Upgrade \$http_upgrade;
            }
            ssl_certificate /etc/letsencrypt/live/$domain/fullchain.pem;
            ssl_certificate_key /etc/letsencrypt/live/$domain/privkey.pem;
            ssl_trusted_certificate /etc/letsencrypt/live/$domain/chain.pem;
            include /etc/letsencrypt/options-ssl-nginx.conf;
            ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
        }";

        return $content;
    }

...

Наше приложение предварительно заполнит переменные $host и $domain корректными параметрами для каждого доменного имени

Мы создадим эти конфигурационные файлы в папке sites-available для Nginx.

Конфигурации будут создаваться динамически с помощью нашего приложения.

//App/Utils/SSLManager
<?php

namespace App\Utils;

use App\Models\User;
use App\Models\Domains;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Process;

class SSLManager
{
    public function generateSSL($domain, $email = null): bool
    {
        $command = $this->certbot_command($domain, $email);

        $certbot = Process::path(base_path())->start($command);

        $process = $certbot->wait();


        if ($process->successful()) {
            $file_path = "/etc/nginx/sites-available/$domain";

            if (File::exists($file_path)) {
                $nginx = File::put($file_path, $this->nginx_config($domain));
            } else {
                touch($file_path);
                $nginx = File::put($file_path, $this->nginx_config($domain));
            }

            if ($nginx) {
                $symlink = $this->execute($this->symlink($domain));
                if ($symlink->successful()) {
                    $finally = $this->execute('sudo nginx -t && sudo systemctl reload nginx');
                    if ($finally->successful()) {
                        return true;
                    } else {
                        return false;
                    }
                }
            }
        } else {
            return false;
        }
    }

    public function certbot_command($domain, $email): string
    {

        if (config('services.certbot.test') == true) {
            $command = "sudo certbot certonly --nginx --agree-tos --no-eff-email -d $domain --email $email --test-cert";
        } else {
            $command = "sudo certbot certonly --nginx --agree-tos --no-eff-email -d $domain --email $email";
        }

        return $command;
    }

    public function nginx_config($domain): string
    {
        $host = "short.app.com";

        $content = "
        server {
            if (\$host = $domain) {
               return 301 https://\$host\$request_uri;
            }
            listen 80;
            listen [::]:80;
            server_name $domain;
        }
        server {
            listen 443 ssl http2;
            listen [::]:443 ssl http2;
            server_name $domain;
            return 301 https://$host\$request_uri;
            resolver 8.8.8.8;
            location / {
                include proxy_params;
                proxy_pass https://$host\$request_uri;
                proxy_set_header Host $domain;
                proxy_set_header X-Forwarded-Host \$http_host;
                proxy_set_header X-Real-IP \$remote_addr;
                proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto \$scheme;
                proxy_redirect off;
                proxy_http_version 1.1;
                proxy_set_header Upgrade \$http_upgrade;
            }
            ssl_certificate /etc/letsencrypt/live/$domain/fullchain.pem;
            ssl_certificate_key /etc/letsencrypt/live/$domain/privkey.pem;
            ssl_trusted_certificate /etc/letsencrypt/live/$domain/chain.pem;
            include /etc/letsencrypt/options-ssl-nginx.conf;
            ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
        }";

        return $content;
    }

    private function symlink($domain): string
    {
        return "sudo ln -s /etc/nginx/sites-available/$domain /etc/nginx/sites-enabled/";
    }

    private function execute($command)
    {
        return Process::path(base_path())->run($command);
    }

Теперь мы создадим задание, которое будет обрабатывать генерацию SSL-сертификатов.

php artisan make:job GenerateSSLJob
//App/Jobs/GenerateSSLJob
<?php

namespace App\Jobs;

use App\Utils\SSLManager;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Throwable;

class GenerateSSLJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $domain;

    public $email;

    public function __construct($domain, $email = null)
    {
        $this->domain = $domain;
        $this->email = $email;
    }

    /**
     * Execute the job.
     */
    public function handle(): void
    {
        (new SSLManager())->generateSSL($this->domain, $this->email);
    }
}

На этом наш генератор SSL-сертификатов готов.

Теперь мы можем использовать пользовательский домен в нашем сокращателе URL-адресов.

Удаление SSL-сертификатов

Поскольку мы создаем SSL-сертификаты в большом масштабе, нам нужен способ их удаления, как только пользователь покинет нашу платформу.

Мы можем создать другой метод, который справится с этой задачей за нас.

//App/Utils/SSLManager.php
<?php


...
  public function deleteSSL(User $user)
    {
        $domains = $this->getUserDomains($user);

        if (!empty($domains)) {
            foreach ($domains as $domain) {
                $nginx_path = "/etc/nginx/sites-available/$domain";
                $this->deleteConfig($nginx_path);
                $this->execute("sudo rm -rf /etc/nginx/sites-enabled/$domain");
                $this->execute("sudo certbot delete --cert-name $domain --non-interactive");
            }

            $finally = $this->execute('sudo nginx -t && sudo systemctl reload nginx');
            if ($finally->successful()) {

                return true;
            } else {
                return false;
            }
        }
    }

    public function getUserDomains(User $user)
    {
        return Domains::where('user_id', $user->id)->pluck('domain')->toArray();
    }

    public function deleteConfig($file_path)
    {
        if (File::exists($file_path)) {
            return File::delete($file_path);
        } else {
            return false;
        }
    }

...

Вы также можете отозвать сертификаты на этом шаге, чтобы вы также могли добавить сюда логику.

Доработка нашего кода

Мы можем добавить некоторые вспомогательные функции, которые помогут сделать наше приложение еще лучше.

Проверка доменных имен

Поскольку мы разрешаем пользователям добавлять пользовательские домены, у нас могут быть случаи, когда пользователи «случайно» добавляют недействительные доменные имена. Поэтому нам нужен способ гарантировать, что только действительные доменные имена будут иметь право на генерацию SSL.

Давайте добавим еще один метод, который будет проверять доменное имя

//App/Utils/DomainHelper.php
<?php

...

public function is_valid_domain_name($domain_name)
    {
        return preg_match("/^(?:[-A-Za-z0-9]+\.)+[A-Za-z]{2,6}$/", $domain_name);
    }
...

Мы используем простое регулярное выражение, которое я «позаимствовал» из чата gpt🙂, чтобы проверить домен и вернуть, действителен он или нет.

Автоматизируйте продление SSL Срок действия SSL-сертификатов

Letsencrypt истекает через 90 дней. К счастью, Certbort может продлить SSL-сертификаты для нас.

Давайте добавим метод, который будет продлевать доменные имена для нас

//App/Utils/SSLManager.php
<?php

...

 public function renewSSL($domain)
    {
        $command = "sudo certbot certonly --force-renew -d $domain";
        return $this->execute($command);
    }

...

Нам понадобится способ узнать, когда обновлять эти SSL-сертификаты. Давайте добавим новый столбец в таблицу доменов, который будет содержать дату продления.

php artisan make:migration add_renewal_column_to_domains_table --table=domains
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::table('domains', function (Blueprint $table) {
            $table->dateTime('renewal_date')->nullable()->after('status');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::table('domains', function (Blueprint $table) {
            $table->dropColumn('renewal_date');
        });
    }
};

Затем мы подготовим нашу работу по продлению этих доменов

php artisan make:job RenewSSLJob
<?php

namespace App\Jobs;

use App\Utils\SSLManager;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class RenewSSLJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * Create a new job instance.
     */
    public $domains;
    public function __construct(array $domains)
    {
        $this->domains = $domains;
    }

    /**
     * Execute the job.
     */
    public function handle(): void
    {
        foreach ($this->domains as $domain) {
            (new SSLManager())->renewSSL($domain);
        }
    }
}

Наконец, мы запланируем ежедневный запуск команды. Мы получим все домены, срок действия которых истекает через месяц, и продлим их.

Мы хотим продлить их за 30 дней до истечения срока их действия, чтобы предотвратить просрочку действия SSL-сертификатов на нашем сервере.

//App/Console/Kernel.php

<?php

namespace App\Console;

use App\Jobs\RenewSSLJob;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;

class Kernel extends ConsoleKernel
{
    /**
     * Define the application's command schedule.
     */
    protected function schedule(Schedule $schedule): void
    {
        // $schedule->command('inspire')->hourly();

        $renewalDate = Carbon::now()->addDays(30)->toDateTimeString();

        $domains = DB::table('domains')
            ->where('renewal_date', '<=', $renewalDate)
            ->pluck('domain')
            ->toArray();

        if (!empty($domains)) {
             $schedule->job(new RenewSSLJob($domains))->daily();
        }
    }

    /**
     * Register the commands for the application.
     */
    protected function commands(): void
    {
        $this->load(__DIR__ . '/Commands');

        require base_path('routes/console.php');
    }
}

Последний вспомогательный класс должен быть похож на приведенный ниже

//App/Utils/SSLManager.php
<?php

namespace App\Utils;

use App\Models\User;
use App\Models\Domains;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Process;

class SSLManager
{
    public function generateSSL($domain, $email = null): bool
    {
        $command = $this->certbot_command($domain, $email);

        $certbot = Process::path(base_path())->start($command);

        $process = $certbot->wait();


        if ($process->successful()) {
            $file_path = "/etc/nginx/sites-available/$domain";

            if (File::exists($file_path)) {
                $nginx = File::put($file_path, $this->nginx_config($domain));
            } else {
                touch($file_path);
                $nginx = File::put($file_path, $this->nginx_config($domain));
            }

            if ($nginx) {
                $symlink = $this->execute($this->symlink($domain));
                if ($symlink->successful()) {
                    $finally = $this->execute('sudo nginx -t && sudo systemctl reload nginx');
                    if ($finally->successful()) {
                        DB::table('domains')->where('domain', '=', $domain)->update([
                            'status' => 1,
                            'renewal_date' => now()->toDateTimeString()
                        ]);

                        return true;
                    } else {
                        return false;
                    }
                }
            }
        } else {
            return false;
        }
    }

    public function certbot_command($domain, $email): string
    {

        if (config('services.certbot.test') == true) {
            $command = "sudo certbot certonly --nginx --agree-tos --no-eff-email -d $domain --email $email --test-cert";
        } else {
            $command = "sudo certbot certonly --nginx --agree-tos --no-eff-email -d $domain --email $email";
        }

        return $command;
    }

    public function nginx_config($domain): string
    {
        $host = "short.app.com";

        $content = "
        server {
            if (\$host = $domain) {
               return 301 https://\$host\$request_uri;
            }
            listen 80;
            listen [::]:80;
            server_name $domain;
        }
        server {
            listen 443 ssl http2;
            listen [::]:443 ssl http2;
            server_name $domain;
            return 301 https://$host\$request_uri;
            resolver 8.8.8.8;
            location / {
                include proxy_params;
                proxy_pass https://$host\$request_uri;
                proxy_set_header Host $domain;
                proxy_set_header X-Forwarded-Host \$http_host;
                proxy_set_header X-Real-IP \$remote_addr;
                proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto \$scheme;
                proxy_redirect off;
                proxy_http_version 1.1;
                proxy_set_header Upgrade \$http_upgrade;
            }
            ssl_certificate /etc/letsencrypt/live/$domain/fullchain.pem;
            ssl_certificate_key /etc/letsencrypt/live/$domain/privkey.pem;
            ssl_trusted_certificate /etc/letsencrypt/live/$domain/chain.pem;
            include /etc/letsencrypt/options-ssl-nginx.conf;
            ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
        }";

        return $content;
    }

    private function symlink($domain): string
    {
        return "sudo ln -s /etc/nginx/sites-available/$domain /etc/nginx/sites-enabled/";
    }

    private function execute($command)
    {
        return Process::path(base_path())->run($command);
    }

    public function renewSSL($domain)
    {
        $command = "sudo certbot certonly --force-renew -d $domain";
        return $this->execute($command);
    }

    public function deleteSSL(User $user)
    {
        $domains = $this->getUserDomains($user);

        if (!empty($domains)) {
            foreach ($domains as $domain) {
                $nginx_path = "/etc/nginx/sites-available/$domain";
                $this->deleteConfig($nginx_path);
                $this->execute("sudo rm -rf /etc/nginx/sites-enabled/$domain");
                $this->execute("sudo certbot delete --cert-name $domain --non-interactive");
            }

            $finally = $this->execute('sudo nginx -t && sudo systemctl reload nginx');
            if ($finally->successful()) {
                return true;
            } else {
                return false;
            }
        }
    }

    public function getUserDomains(User $user)
    {
        return Domains::where('user_id', $user->id)->pluck('domain')->toArray();
    }

    public function deleteConfig($file_path)
    {
        if (File::exists($file_path)) {
            return File::delete($file_path);
        } else {
            return false;
        }
    }
}

Заключительный класс

SSLManager Связываем все это Давайте

соберем все воедино с помощью контроллера

php artisan make:controller DomainController
<?php

namespace App\Http\Controllers;

use App\Jobs\GenerateSSLJob;
use App\Models\Domains;
use App\Utils\DomainHelper;
use Illuminate\Http\Request;

class DomainController extends Controller
{

    public function store(Request $request)
    {
        $domain_name = $request->input('domain');
        $email = auth()->user()->email;

        if ((new DomainHelper())->is_valid_domain_name($domain_name)) {
            $domain = Domains::create([
                'user_id' => auth()->id(),
                'domain' => $domain_name,
                'status' => 0
            ]);

            if ((new DomainHelper())->verifycname($domain_name)) {
                $job = (new GenerateSSLJob($domain_name, $email));
                dispatch($job);
            }

            return $domain;
        } else {
            return response()->json([
                'message' => $domain_name . 'is not a valid domain name. Ensure your domain name is valid',
            ], 406);
        }
    }
}

Вывод

: Вот и все. Мы автоматизировали процесс генерации и обновления SSL-сертификатов с помощью laravel.

Я надеюсь, что эта статья была проницательной и показала вам, как автоматизировать генерацию и продление SSL с помощью laravel.

Вы можете настроить логику в соответствии со своими потребностями. Что касается меня, я использовал простой пример сокращателя URL-адресов , и именно так я добился автоматизации генерации SSL.

Если у вас есть какие-либо вопросы, не стесняйтесь задавать их в разделе комментариев.

Спасибо, что прочитали.

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Об авторе CrazyBoy49z
WORK EXPERIENCE
Контакты
Ukraine, Lutsk
+380979856297