如果组织没有可用的证书颁发机构(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。











暂无评论内容