分类 DevOps 下的文章

Starting with MySQL 8 you no longer can (implicitly) create a user using the GRANT command. Use CREATE USER instead, followed by the GRANT statement:

mysql> CREATE USER 'root'@'%' IDENTIFIED BY 'root';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;

Caution about the security risks about WITH GRANT OPTION, see:

Grant all privileges on database

re: grant-all-privileges-to-root-user

前言

作为世界上最流行的开源数据库,MySQL各方面的功能都在不断完善,比如密码管理这一块,从一开始最简单的用户名密码、到 5.7 版本的 validate_password 插件、再到 8.0 版本丰富多彩的密码策略,已经完全可以媲美 DB2、Oracle、SQL Server 等大型商业数据库;今天就给大家带来 MySQL 8.0 新特性 — 密码管理。

密码管理

在MySQL 8.0版本中,针对密码管理这一块,做出了非常大的改进与完善,支持以下功能:

  1. 密码认证插件
  2. 密码过期策略
  3. 密码复用策略
  4. 密码修改验证策略
  5. 双重密码支持
  6. 密码强度策略
  7. 随机密码生成
  8. 登录失败追踪

密码认证插件

在MySQL 8.0版本中,支持以下3种密码认证插件:

(1)mysql_native_password:8.0之前默认

(2)caching_sha2_password:8.0默认

(3)sha256_password:可选

caching_sha2_password 作为 8.0 默认的密码认证插件,其安全性强于 mysql_native_password,性能优于sha256_password。但由于客户端和驱动的兼容性问题,建议还是采用 mysql_native_password 作为默认的密码认证插件。

如果采用 caching_sha2_password 作为默认的密码认证插件,那么在建立连接时,一定要指定RSA公钥,否则会报错 "ERROR 2061 (HY000): Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection."

密码过期策略

密码过期策略,可以通过系统参数进行设置,对所有用户生效

vim /etc/mysql/my.cnf

default_password_lifetime=180

也可以通过SQL语句,对指定用户进行设置

alter user [email protected]'%' password expire interval 180 day; -- 密码有效期180天
alter user [email protected]'%' password expire never;            -- 密码永不过期
alter user [email protected]'%' password expire default;          -- 采用默认的密码有效期

还可以手动指定某用户过期

mysql > alter user [email protected]'%' password expire;

密码复用策略

密码复用策略,可以通过系统参数进行设置,对所有用户生效

vim /etc/mysql/my.cnf

password_history = 6            -- 密码多少次不重复
password_reuse_interval = 365   -- 密码多少天不复用

也可以通过SQL语句,对指定用户进行设置

mysql > alter user [email protected]'%' password history 6;              -- 密码6次不复用
mysql > alter user [email protected]'%' password reuse interval 365 day; -- 密码365天不复用
mysql > alter user [email protected]'%' password history default reuse interval default; -- 采用默认复用策略

密码修改验证策略

密码修改前,需要指定旧密码,才能进行修改;这也是大大提高了安全性,大大降低了 客户端记住密码/临时离开工位 导致密码被别人篡改的风险。

可以通过系统参数进行设置,对所有用户生效

vim /etc/mysql/my.cnf

password_require_current = on --启用密码修改验证策略

也可以通过SQL语句,对指定用户进行设置

mysql > alter user [email protected]'%' password require current;          -- 启用密码修改验证策略
mysql > alter user [email protected]'%' password require optional;         -- 密码验证可选
mysql > alter user [email protected]'%' password require current default;  -- 采用默认密码验证策略

启用密码修改验证策略后,修改密码需要提供旧密码和新密码

mysql > alter user [email protected]'%' identified by 'new_password' replace 'old_password';

双重密码支持

相信很多的开发、管理员和 DBA 都遇见过这样一个场景:修改完数据库用户密码,业务系统某个/某些模块立刻不可用,报密码错误;其实这种情况很常见,业务系统模块那么多,有时候会有遗漏不奇怪。双重密码,支持旧密码和新密码同时登录,就可以很好地规避这个问题,平滑地实现密码修改。

保留旧密码

mysql > alter user [email protected]'%' identified by 'new_password' retain current password;

废弃旧密码

mysql > alter user [email protected]'%' discard old password;

密码强度策略

在 MySQL 5.7 版本中,提供了 validate_password 的插件,实现密码强度策略;在 MySQL 8.0 版本中,官方是将validate_password 改造成组件,并提供一系列系统参数,以实现密码强度策略。

首先,我们需要安装 validate_password 组件,通过以下SQL语句

mysql > INSTALL COMPONENT 'file://component_validate_password';
mysql > UNINSTALL COMPONENT 'file://component_validate_password';

然后,我们可以通过以下系统参数,进行密码强度策略设置:

mysql> SHOW VARIABLES LIKE 'validate_password%';
+--------------------------------------+--------+
| Variable_name                        | Value  |
+--------------------------------------+--------+
| validate_password.check_user_name    | ON     |
| validate_password.dictionary_file    |        |
| validate_password.length             | 8      |
| validate_password.mixed_case_count   | 1      |
| validate_password.number_count       | 1      |
| validate_password.policy             | MEDIUM |
| validate_password.special_char_count | 1      |
+--------------------------------------+--------+
7 rows in set (0.06 sec)

关于 mysql 密码策略相关参数:

validate_password.length  固定密码的总长度;
validate_password.dictionary_file 指定密码验证的文件路径;
validate_password.mixed.case_count  整个密码中至少要包含大/小写字母的总个数;
validate_password.number_count  整个密码中至少要包含阿拉伯数字的个数;
validate_password_special_char_count 整个密码中至少要包含特殊字符的个数;
validate_password.policy 指定密码的强度验证等级,默认为 MEDIUM;
    关于 validate_password.policy 的取值:
        0/LOW:只验证长度;
        1/MEDIUM:验证长度、数字、大小写、特殊字符;
        2/STRONG:验证长度、数字、大小写、特殊字符、字典文件;
mysql> set global validate_password.length=4;
mysql> set global validate_password.policy='LOW';

修改密码验证策略后我们就可以使用简单的密码进行登录了。

密码随机生成

在 MySQL 8.0 中,还支持随机密码生成

mysql > alter user [email protected]'%' identified by random password;

可以通过以下系统参数,对随机密码生成的长度进行控制

generated_random_password_length = 20  -- 随机密码生成长度

登录失败追踪

最后,再来看一下登录失败的问题;我们可以设置连续登录失败多少次,账号会被锁定多少天,具体如下:

mysql > alter user [email protected]'%' failed_login_attempts 3 password_lock_time 3; -- 失败3次锁定3天

总结

在 MySQL 8.0 版本中,密码管理这一块功能日趋完善,大大提高了MySQL数据库的安全性,尤其对政务行业、金融行业等监管要求高的企业来说,更具有吸引力。

通过 proxy_pass 代理的时候,如果文件比较大就会出现文件还没有传输完毕就被关闭的情况,只需要在 nginx 站点配置增加这个就可以解决了:

server {
    ...

    location / {
        ...
        proxy_buffers 8 1024k;  
        proxy_buffer_size 1024k;
    }
}

loap.jpg

从上面这张图我们可以直观的看到 PostStart 和 PreStop 包括 liveness 和 readiness 是属于主容器的生命周期范围内的,而 Init Container 是独立于主容器之外的,当然他们都属于 Pod 的生命周期范畴之内的,现在我们应该明白 Init Container 和钩子函数之类的区别了吧。

我们说Init Container主要是来做初始化容器工作的,那么他有哪些应用场景呢?

等待其他模块Ready:这个可以用来解决服务之间的依赖问题,比如我们有一个 Web 服务,该服务又依赖于另外一个数据库服务,但是在我们启动这个 Web 服务的时候我们并不能保证依赖的这个数据库服务就已经启动起来了,所以可能会出现一段时间内 Web 服务连接数据库异常。要解决这个问题的话我们就可以在 Web 服务的 Pod 中使用一个InitContainer,在这个初始化容器中去检查数据库是否已经准备好了,准备好了过后初始化容器就结束退出,然后我们的主容器 Web 服务被启动起来,这个时候去连接数据库就不会有问题了。

做初始化配置:比如集群里检测所有已经存在的成员节点,为主容器准备好集群的配置信息,这样主容器起来后就能用这个配置信息加入集群。

其它场景:如将Pod注册到一个中央数据库、配置中心等。

参考链接:初始化容器

将当前用户加入到 docker 用户组

因为 Docker 运行时需要特殊权限,所以默认执行命令时都必须在前面加上 sudo。但这样做确实使人厌烦,一个可行的解决方法是把用户放进 docker 用户组里。在 Ubuntu 下你可以输入:

sudo usermod -aG docker $USER

重启 docker

sudo systemctl restart docker

重新 ssh 登录

ssh [email protected]

此时运行 docker version 就不会报 Got permission denied 错误了

[email protected]:~$ docker version
Client:
 Version:           18.09.6
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        481bc77
 Built:             Sat May  4 02:35:57 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.6
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.8
  Git commit:       481bc77
  Built:            Sat May  4 01:59:36 2019
  OS/Arch:          linux/amd64
  Experimental:     false