| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- <?php
- namespace backend\modules\admin\services;
- use common\models\common\Addons;
- use Yii;
- /**
- * 过期提醒
- * @package backend\modules\admin\services
- */
- class ExpireNoticeService extends BaseService
- {
- /**
- * 存储key
- */
- protected const KEY = 'expire-notice';
- const FILE_NAME = 'change_ssl.sh';
- /**
- * 剩余不足提示时间
- */
- protected const LIMIT = 7;
- /**
- * 保存配置
- *
- * @param array $config
- * @return boolean
- */
- public function setConfig(array $config)
- {
- // print_r($config);exit;
- //如果上传了ssl证书压缩包
- $admin_url = substr(Yii::$app->services->setting->platform->get('system.backend_url'), 8);
- $api_url = substr(Yii::$app->services->setting->platform->get('system.api_url'), 8);
- $h5_url = substr(Yii::$app->services->setting->platform->get('system.h5_url'), 8);
- $static_url = substr(Yii::$app->services->setting->platform->get('system.static_url'), 8);
- $salary_h5_url = parse_url(Yii::$app->services->setting->platform->get('system.cat_h5_url') ?: '')['host'] ?? '';
- if (!empty($config['certificate']['ssl_path'])) {
- $is_docker_deploy = Yii::$app->params['is_docker_deploy']; //获取配置
- $path = $config['certificate']['ssl_path'];
- $pwd = Yii::$app->params['oskad'];
- $is_docker_deploy = Yii::$app->params['is_docker_deploy'];
- $host = Yii::$app->params['host'];
- $replaces = [
- '{SSL_PATH}' => $path,
- '{PWD}' => $pwd,
- '{FILE_NAME}' => static::FILE_NAME,
- ];
- if ($is_docker_deploy) { //是否为docker搭建系统
- $file_path = '/www/wwwroot/qimall/';
- $file_content = static::shDockerTemplate(); //获取sh模板
- } else {
- //prod
- $file_path = '/data/wwwroot/qimall/';
- $file_content = static::shTemplate();
- }
- //组装sh脚本
- $content = str_replace(array_keys($replaces), array_values($replaces), $file_content);
- file_put_contents($file_path . static::FILE_NAME, $content);
- //执行脚本
- if ($is_docker_deploy) {
- // exec('sshpass -p "'. $pwd.'" ssh root@'. $host .' "sh '. $file_path . static::FILE_NAME.'"');
- exec("sshpass -p '".$pwd."' ssh -o StrictHostKeyChecking=no root@". $host." 'sh ". $file_path . static::FILE_NAME . "'");
- } else {
- exec('sh '. $file_path . static::FILE_NAME);
- }
- }
- $url_arr = [
- 'admin_expire_date' => $admin_url,
- 'h5_expire_date' => $h5_url,
- 'api_expire_date' => $api_url,
- 'static_expire_date' => $static_url,
- ];
- // 有发薪猫插件才获取过期日期
- if ($this->isInstallSalary($salary_h5_url)) {
- $url_arr['salary_h5_expire_date'] = $salary_h5_url;
- }
- //通过域名获取ssl证书过期日期
- foreach ($url_arr as $key => $value) {
- $info = $this->getCertificateExpireTime($value);
- if ($info['code'] == 0) $config['certificate'][$key] = date('Y-m-d', $info['cert_info']['validTo_time_t']);
- }
- //保存配置
- Yii::$app->services->setting->platform->set([static::KEY => $config]);
- return true;
- }
- /**
- * 获取配置
- *
- * @param string $key
- * @return mixed
- */
- public function getConfig(string $key = '')
- {
- $config = Yii::$app->services->setting->platform->get(static::KEY);
- foreach ($config as &$item) {
- $item = json_decode($item, true);
- }
- $info = $key ? ($config[$key] ?? '') : $config;
- if (!empty($info['certificate'])) $info['certificate']['ssl_path'] = '';
- return $info;
- }
- /**
- * 计算证书到期提醒
- *
- * @return array
- */
- public function certificateNotice()
- {
- // 全部证书
- $cers = ['admin', 'api', 'h5', 'static'];
- if ($this->isInstallSalary()) {
- $cers[] = 'salary_h5';
- }
- $notices = [];
- foreach ($cers as $key) {
- $this->keyShowNotice('certificate', sprintf('%s_expire_date', $key)) && ($notices[] = $key);
- }
- return $notices;
- }
- /**
- * 计算服务器到期提醒
- *
- * @return boolean
- */
- public function serverNotice()
- {
- return $this->keyShowNotice('server');
- }
- /**
- * 是否即将到期显示提示
- *
- * @param string $key
- * @return boolean
- */
- protected function keyShowNotice(string $key, string $expire_key = 'expire_date')
- {
- $config = $this->getConfig($key);
- if (!(isset($config['open_notice']) && $config['open_notice'])) return false;
- // 到期时间
- $expire_date = $config[$expire_key];
- return bcsub(strtotime($expire_date), time()) < bcmul(static::LIMIT, 86400);
- }
- //通过域名获取ssl证书过期时间
- public function getCertificateExpireTime($url)
- {
- if (!extension_loaded('openssl') || !is_callable('openssl_x509_parse')){
- return ['code' => -1, 'msg' => '请开启openssl扩展'];
- }
- //不规范入参处理
- $parse = parse_url($url);
- if (!empty($parse['host'])) {
- $domain = $parse['host'];
- } elseif (empty($parse['path'])) {
- return ['code' => -1, 'msg' => $url . '请输入合法的域名'];
- } else {
- //abc.top/x/xx
- $arr = explode('/', $parse['path']);
- $domain = $arr[0];
- }
- $context = stream_context_create([
- 'ssl' => [
- 'capture_peer_cert' => true,
- 'capture_peer_cert_chain' => true,
- ],
- ]);
-
- $client = @stream_socket_client("ssl://" . $domain . ":443", $errno, $errstr, 10, STREAM_CLIENT_CONNECT, $context);
- if ($client == false) {
- return ['code' => -1, 'msg' => $domain . '未查到可靠信息','err'=>[
- 'errno'=>$errno,
- 'errstr'=>iconv('gbk', 'utf-8', $errstr),
- ]];
- }
- $params = stream_context_get_params($client);
- if (empty($params['options']['ssl']['peer_certificate'])) {
- return ['code' => -1, 'msg' => $domain . '获取信息失败,请确保可以正常访问'];
- }
- $cert = $params['options']['ssl']['peer_certificate'];
- $cert_info = @openssl_x509_parse($cert);
- return ['code' => 0, 'cert_info' => $cert_info];
- }
- /**
- * prod部署-sh模板
- *
- * @return string
- */
- protected static function shTemplate()
- {
- return <<<'EOC'
- #!/bin/bash
- # 检查是否有sudo权限
- if [ "$(id -u)" != "0" ]; then
- # 设置root密码,这里是示例密码,请替换为您的实际密码
- root_password='{PWD}'
- # 使用echo和管道将密码传递给su命令
- echo $root_password | su -c "sh /data/wwwroot/qimall/{FILE_NAME}"
- fi
- # 检查是否有sudo权限
- if [ "$(id -u)" == "0" ]; then
- # 证书
- # 证书路径
- ssl_path='{SSL_PATH}'
- # 移动证书到目录
- dir=/application/nginx/conf/ssl
- # 证书目录
- ssl=/data/wwwroot/qimall/${ssl_path}
- # 复制
- cp ${ssl} ${dir}/ssl.zip
- cd ${dir}
- # 解压
- unzip -o ssl.zip
- # 重启nginx
- # systemctl restart nginx
- /application/nginx/sbin/nginx -s reload
- # 重启消费者cd
- # systemctl restart swoole_consume_run
- fi
- EOC;
- }
- /**
- * docker部署-sh模板
- *
- * @return string
- */
- protected static function shDockerTemplate()
- {
- return <<<'EOC'
- #!/bin/bash
- # 检查是否有sudo权限
- if [ "$(id -u)" != "0" ]; then
- # 设置root密码,这里是示例密码,请替换为您的实际密码
- root_password='{PWD}'
- # 使用echo和管道将密码传递给su命令
- echo $root_password | su -c "sh /www/wwwroot/qimall/{FILE_NAME}"
- fi
- # 检查是否有sudo权限
- if [ "$(id -u)" == "0" ]; then
- # 证书
- # 证书路径
- ssl_path='{SSL_PATH}'
- # 移动证书到目录
- dir=/data/confs/nginx/ssl
- # 证书目录
- ssl=/www/wwwroot/qimall/${ssl_path}
- # 复制
- cp ${ssl} ${dir}/ssl.zip
- cd ${dir}
- # 解压
- unzip -o ssl.zip
- # 重启nginx
- # systemctl restart nginx
- sudo docker restart nginx
- # 重启消费者cd
- # systemctl restart swoole_consume_run
- fi
- EOC;
- }
- /**
- * 是否安装发薪猫插件
- *
- * @param null $url
- *
- * @return bool
- */
- public function isInstallSalary($url = null): bool
- {
- if (is_null($url)) {
- $url = Yii::$app->services->setting->platform->get('system.cat_h5_url');
- }
- return Addons::isInstall('Salary') && $url;
- }
- }
|