生成自签名证书

如果组织没有可用的证书颁发机构(CA),但希望将 OpenSearch 用于非演示用途,可以用 OpenSSL 生成自己的自签名证书。

操作系统的包管理器通常提供 OpenSSL。在 CentOS 上使用 Yum:

sudo yum install openssl

在 macOS 上使用 Homebrew:

brew install openssl

生成私钥

首先用 openssl genrsa 生成私钥。顾名思义,这个文件应保持私密。私钥长度必须足以满足安全需要,原文示例指定 2048 位:

openssl genrsa -out root-ca-key.pem 2048

可以添加 -aes256 选项,使用 AES-256 加密私钥;此选项需要密码。

生成根证书

使用私钥为根 CA 生成自签名证书。为了让 CA 正常工作并避免潜在的 Java SSL 错误,必须加入描述证书角色和能力的 X.509 v3 扩展:

openssl req -new -x509 -sha256 -key root-ca-key.pem -out root-ca.pem -days 730 \
  -addext 'basicConstraints = critical, CA:TRUE, pathlen:0' \
  -addext 'keyUsage = critical, keyCertSign, cRLSign' \
  -addext 'authorityKeyIdentifier = keyid'

-days 默认值30天只适合测试。示例设置730天,即两年;组织应根据自己的需求设置有效期。

  • -x509 表示生成自签名证书,而非证书请求。
  • -sha256 将散列算法设置为 SHA-256。较新 OpenSSL 版本默认使用 SHA-256,早期版本可能使用 SHA-1。
  • -addext 添加 X.509 v3 扩展:basicConstraints = critical, CA:TRUE, pathlen:0 表示该 CA 可以签发终端实体证书,但不能签发下级 CA;keyUsage = critical, keyCertSign, cRLSign 允许签发证书和证书撤销列表;authorityKeyIdentifier = keyid 帮助识别 CA 公钥,用于证书链验证。

这些扩展用于满足 X.509 v3 要求,并帮助避免 Java 应用中的底层 SSL 错误。详情见 OpenSSL x509v3_config 文档。按提示填写组织信息,这些字段共同构成 CA 的可分辨名称(DN)。

生成管理员证书

先创建新密钥:

openssl genrsa -out admin-key-temp.pem 2048

随后将密钥转换为 Java 使用的 PKCS#8 格式。原文命令同时指定与 PKCS#12 兼容的算法(3DES):

openssl pkcs8 -inform PEM -outform PEM -in admin-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out admin-key.pem

再创建证书签名请求(CSR),它相当于向 CA 申请已签名证书:

openssl req -new -key admin-key.pem -out admin.csr

按提示填写信息,不必设置挑战密码。OpenSSL Cookbook 指出,挑战密码不会以任何方式提高 CSR 的安全性。

生成 TLS 证书且将 transport.ssl.enforce_hostname_verification 设为默认值 true 时,每个 CSR 的通用名称(CN)应匹配目标节点对应的 DNS A 记录。

如果希望所有节点共用同一节点证书(原文不推荐),原文建议关闭主机名验证。更多信息见配置 TLS 证书。

私钥和签名请求准备完成后,生成证书:

openssl x509 -req -in admin.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out admin.pem -days 730

与根证书一样,用 -days 指定超过30天的有效期。

可选:生成节点和客户端证书

步骤与管理员证书类似,但每个节点以及所需客户端证书都应使用新文件名。例如可分别为 OpenSearch Dashboards 和 Python 客户端生成证书。每张证书应有独立私钥,以及唯一的 CSR;SAN 扩展应对应目标主机。管理员证书不绑定特定主机,因而不需要 SAN。

生成节点或客户端证书,先创建新密钥:

openssl genrsa -out node1-key-temp.pem 2048

再转换为 PKCS#8 格式:

openssl pkcs8 -inform PEM -outform PEM -in node1-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out node1-key.pem

创建 CSR:

openssl req -new -key node1-key.pem -out node1.csr

为符合 RFC 2818(HTTP Over TLS),主机和客户端证书应指定主题备用名称(SAN)。SAN 应与 CN 匹配,使二者指向同一 DNS A 记录。

签发证书前,创建 SAN 扩展文件,描述主机 DNS A 记录;如果只通过 IPv4 或 IPv6 地址连接,使用 IP 语法。

不使用 IP

echo 'subjectAltName=DNS:node1.dns.a-record' > node1.ext

使用 IP

echo subjectAltName=IP:127.0.0.1 > node1.ext

配置完成后,生成证书:

openssl x509 -req -in node1.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out node1.pem -days 730 -extfile node1.ext

生成自签名 PEM 证书的示例脚本

已知证书信息、不希望逐项交互填写时,可在根证书和 CSR 命令里使用 -subj。以下脚本创建根证书、管理员证书、两个节点证书与一个客户端证书,全部有效期为730天:

#!/bin/sh
# Root CA
openssl genrsa -out root-ca-key.pem 2048
openssl req -new -x509 -sha256 -key root-ca-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=root.dns.a-record" -out root-ca.pem -days 730 \
  -addext 'basicConstraints = critical, CA:TRUE, pathlen:0' \
  -addext 'keyUsage = critical, keyCertSign, cRLSign' \
  -addext 'authorityKeyIdentifier = keyid'
# Admin cert
openssl genrsa -out admin-key-temp.pem 2048
openssl pkcs8 -inform PEM -outform PEM -in admin-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out admin-key.pem
openssl req -new -key admin-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=A" -out admin.csr
openssl x509 -req -in admin.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out admin.pem -days 730
# Node cert 1
openssl genrsa -out node1-key-temp.pem 2048
openssl pkcs8 -inform PEM -outform PEM -in node1-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out node1-key.pem
openssl req -new -key node1-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=node1.dns.a-record" -out node1.csr
echo 'subjectAltName=DNS:node1.dns.a-record' > node1.ext
openssl x509 -req -in node1.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out node1.pem -days 730 -extfile node1.ext
# Node cert 2
openssl genrsa -out node2-key-temp.pem 2048
openssl pkcs8 -inform PEM -outform PEM -in node2-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out node2-key.pem
openssl req -new -key node2-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=node2.dns.a-record" -out node2.csr
echo 'subjectAltName=DNS:node2.dns.a-record' > node2.ext
openssl x509 -req -in node2.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out node2.pem -days 730 -extfile node2.ext
# Client cert
openssl genrsa -out client-key-temp.pem 2048
openssl pkcs8 -inform PEM -outform PEM -in client-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out client-key.pem
openssl req -new -key client-key.pem -subj "/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=client.dns.a-record" -out client.csr
echo 'subjectAltName=DNS:client.dns.a-record' > client.ext
openssl x509 -req -in client.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out client.pem -days 730 -extfile client.ext
# Cleanup
rm admin-key-temp.pem
rm admin.csr
rm node1-key-temp.pem
rm node1.csr
rm node1.ext
rm node2-key-temp.pem
rm node2.csr
rm node2.ext
rm client-key-temp.pem
rm client.csr
rm client.ext

将 PEM 证书转换为密钥库与信任库的示例脚本

下面脚本使用先前生成的 PEM 证书构建 keystore 和 truststore:

#!/bin/sh
# Convert node certificate
cat root-ca.pem node1.pem node1-key.pem > combined-node1.pem
echo "Enter password for node1-cert.p12"
openssl pkcs12 -export -in combined-node1.pem -out node1-cert.p12 -name node1
echo "Enter password for keystore.jks"
keytool -importkeystore -srckeystore node1-cert.p12 -srcstoretype pkcs12 -destkeystore keystore.jks
# Convert admin certificate
cat root-ca.pem admin.pem admin-key.pem > combined-admin.pem
echo "Enter password for admin-cert.p12"
openssl pkcs12 -export -in combined-admin.pem -out admin-cert.p12 -name admin
echo "Enter password for keystore.jks"
keytool -importkeystore -srckeystore admin-cert.p12 -srcstoretype pkcs12 -destkeystore keystore.jks

# Import certificates to truststore
keytool -importcert -keystore truststore.jks -file root-ca.cer -storepass changeit -trustcacerts -deststoretype pkcs12
# Cleanup
rm combined-admin.pem
rm combined-node1.pem

将 DN 加入 opensearch.yml

必须在所有节点的 opensearch.yml 中指定所有管理员和节点证书的 DN。使用前面的证书,配置片段如下:

plugins.security.authcz.admin_dn:
  - 'CN=A,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
plugins.security.nodes_dn:
  - 'CN=node1.dns.a-record,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
  - 'CN=node2.dns.a-record,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'

但查看证书的 subject 时,可能看到不同格式:

subject=/C=CA/ST=ONTARIO/L=TORONTO/O=ORG/OU=UNIT/CN=node1.dns.a-record

对照上述字符串,需要反转字段顺序,并将斜杠改为逗号。使用下面命令得到正确格式:

openssl x509 -subject -nameopt RFC2253 -noout -in node.pem

再将输出复制到 opensearch.yml。

将证书文件加入 opensearch.yml

上述过程生成多个文件;每个节点需要加入以下文件:

  • root-ca.pem
  • 可选:admin.pem
  • 可选:admin-key.pem
  • 可选:node1.pem
  • 可选:node1-key.pem

对多数用户而言,仅准备运行 securityadmin 脚本或重新加载证书的节点需要管理员证书和私钥。详情见应用配置文件变更。如果直接从节点运行该脚本,该节点必须拥有这两个文件的副本。

其中一个节点的安全配置示例如下:

plugins.security.ssl.transport.pemcert_filepath: node1.pem
plugins.security.ssl.transport.pemkey_filepath: node1-key.pem
plugins.security.ssl.transport.pemtrustedcas_filepath: root-ca.pem
transport.ssl.enforce_hostname_verification: false
plugins.security.ssl.http.enabled: true
plugins.security.ssl.http.pemcert_filepath: node1.pem
plugins.security.ssl.http.pemkey_filepath: node1-key.pem
plugins.security.ssl.http.pemtrustedcas_filepath: root-ca.pem
plugins.security.authcz.admin_dn:
  - 'CN=A,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
plugins.security.nodes_dn:
  - 'CN=node1.dns.a-record,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'
  - 'CN=node2.dns.a-record,OU=UNIT,O=ORG,L=TORONTO,ST=ONTARIO,C=CA'

更多信息见 Docker 的基本安全设置、配置 TLS 证书及客户端证书身份验证。

OpenSearch Dashboards

使用根 CA 与客户端证书为 Dashboards 启用 TLS,见配置 OpenSearch Dashboards TLS。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容