kafka证书配置实战

603 阅读2分钟

kafka证书配置实战

创建证书

生成CA证书

  • 生成CA证书
openssl req -new -x509 -keyout ca.key -out ca.crt -days 365 -passout pass:${PASSWD} -subj "/C=cn/ST=beijing/L=beijing/O=aspire/OU=aspire/CN=${HOSTNAME}"
  • 将CA证书加到客户端信任库,用来客户端认证服务器身份时,通过CA证书校验服务器证书的有效性
keytool -keystore client.truststore.jks -alias CARoot -import -file ca.crt -storepass ${PASSWD}
  • 将CA证书加到服务器端信任库,用来服务器端认证客户端身份时,通过CA证书校验客户端证书的有效性
keytool -keystore server.truststore.jks -alias CARoot -import -file ca.crt -storepass ${PASSWD}

生成服务器证书

  • 首先生成服务器端证书存储器keystore,在生成keystore容器时,同时默认也会生成server的自签名证书,如果没有别人给它签名,直接使用的话,它就是一个root证书
keytool -keystore server.keystore.jks -alias alias-${HOSTNAME} -validity 365 -genkey -keypass ${PASSWD} -keyalg RSA -dname "CN=${HOSTNAME},OU=aspire,O=aspire,L=beijing,S=beijing,C=cn" -storepass ${PASSWD} -ext SAN=DNS:${HOSTNAME},ip:127.0.0.1
# keytool -list -v -keystore server.keystore.jks
  • 通过server keystore中的keypair生成待签名csr文件,该文件是一个证书待签名请求文件,等待CA证书签名
keytool -keystore server.keystore.jks -alias alias-${HOSTNAME} -certreq -file server.csr -storepass ${PASSWD}
  • 使用CA证书签名csr文件,生成server证书

    首先创建server.ext配置文件

cat>server.ext<<EOF
[v3_req]
keyUsage = critical, digitalSignature, keyAgreement
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = test.it
IP.1 = 127.0.0.1
EOF
openssl x509 -req -CA ca.crt -CAkey ca.key -in server.csr -out server.signed.crt -days 365 -CAcreateserial -passin pass:${PASSWD} -extensions v3_req -extfile server.ext
  • 将CA证书导入到server keystore中,必须导入CA证书,因为导入server证书时需要用CA证书校验
keytool -keystore server.keystore.jks -alias CARoot -import -file ca.crt -storepass ${PASSWD}
  • 将签名后的server证书导入到server keystore中,注意该alias和创建keystore时的alias是一致的
keytool -keystore server.keystore.jks -alias alias-${HOSTNAME} -import -file server.signed.crt -storepass ${PASSWD}

生成客户端证书

  • 首先生成客户端证书存储器keystore,生成后,会创建客户端的公私钥
keytool -keystore client.keystore.jks -alias alias-${HOSTNAME} -validity 365 -genkey -keypass ${PASSWD} -keyalg RSA -dname "CN=${HOSTNAME},OU=aspire,O=aspire,L=beijing,S=beijing,C=cn" -ext SAN=DNS:${HOSTNAME},ip:127.0.0.1 -storepass ${PASSWD}
# keytool -list -v -keystore client.keystore.jks
  • 通过client keystore中的keypair生成待签名csr文件,该文件需要CA证书签名后才是真正的client证书
keytool -keystore client.keystore.jks -alias alias-${HOSTNAME} -certreq -file client.csr -storepass ${PASSWD}
  • 使用CA证书签名csr文件,生成server证书
openssl x509 -req -CA ca.crt -CAkey ca.key -in client.csr -out client.signed.crt -days 365 -CAcreateserial -passin pass:${PASSWD}
  • 将CA证书导入到client keystore中,必须导入CA证书,因为导入client证书时需要用CA证书校验
keytool -keystore client.keystore.jks -alias CARoot -import -file ca.crt -storepass ${PASSWD}
  • 将签名后的client证书导入到client keystore中,注意该alias和创建keystore时的alias是一致的
keytool -keystore client.keystore.jks -alias alias-${HOSTNAME} -import -file client.signed.crt -storepass ${PASSWD}

脚本

#!/bin/bash
#define
PASSWD=localhost
HOSTNAME=test.it

#precondition
# rm -f ca*
 rm -f client.*
 rm -f server.*
echo "create "

########## 生成CA证书
openssl req -new -x509 -keyout ca.key -out ca.crt -sha256 -days 365 -passout pass:${PASSWD} -subj "/C=cn/ST=beijing/L=beijing/O=aspire/OU=aspire/CN=ca.it"
keytool -keystore client.truststore.jks -alias CARoot -import -file ca.crt -storepass ${PASSWD}
keytool -keystore server.truststore.jks -alias CARoot -import -file ca.crt -storepass ${PASSWD}

########## 生成服务器证书
keytool -keystore server.keystore.jks -alias alias-${HOSTNAME} -validity 365 -genkey -keypass ${PASSWD} -keyalg RSA -dname "CN=${HOSTNAME},OU=aspire,O=aspire,L=beijing,S=beijing,C=cn" -storepass ${PASSWD} -ext SAN=DNS:${HOSTNAME},ip:127.0.0.1
# keytool -list -v -keystore server.keystore.jks

keytool -keystore server.keystore.jks -alias alias-${HOSTNAME} -certreq -file server.csr -storepass ${PASSWD}

cat>server.ext<<EOF
[v3_req]
keyUsage = critical, digitalSignature, keyAgreement
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = test.it
IP.1 = 127.0.0.1
EOF

#openssl x509 -req -CA ca.crt -CAkey ca.key -in server.csr -out server.signed2.crt -days 365 -CAcreateserial -passin pass:${PASSWD} -extensions v3_req -extfile server.ext
# the default signed algorithm is sha1WithRSAEncryption
openssl x509 -req -CA ca.crt -CAkey ca.key -in server.csr -out server.signed.crt -sha256 -days 365 -CAcreateserial -passin pass:${PASSWD} -extensions v3_req -extfile server.ext

keytool -keystore server.keystore.jks -alias CARoot -import -file ca.crt -storepass ${PASSWD}

keytool -keystore server.keystore.jks -alias alias-${HOSTNAME} -import -file server.signed.crt -storepass ${PASSWD}

########## 生成客户端证书

keytool -keystore client.keystore.jks -alias alias-${HOSTNAME} -validity 365 -genkey -keypass ${PASSWD} -keyalg RSA -dname "CN=${HOSTNAME},OU=aspire,O=aspire,L=beijing,S=beijing,C=cn" -ext SAN=DNS:${HOSTNAME},ip:127.0.0.1 -storepass ${PASSWD}
# keytool -list -v -keystore client.keystore.jks

keytool -keystore client.keystore.jks -alias alias-${HOSTNAME} -certreq -file client.csr -storepass ${PASSWD}

openssl x509 -req -CA ca.crt -CAkey ca.key -in client.csr -out client.signed.crt -sha256 -days 365 -CAcreateserial -passin pass:${PASSWD}

keytool -keystore client.keystore.jks -alias CARoot -import -file ca.crt -storepass ${PASSWD}

keytool -keystore client.keystore.jks -alias alias-${HOSTNAME} -import -file client.signed.crt -storepass ${PASSWD}


服务器配置

单项认证配置

# 该配置配置的是内网ip
listeners=PLAINTEXT://172.31.95.70:9092,SSL://172.31.95.70:9093
# advertised  配置是提供给外网使用
advertised.listeners=PLAINTEXT://127.0.0.1:9092,SSL://127.0.0.1:9093
ssl.keystore.location=/home/ec2-user/ssl/server.keystore.jks
ssl.keystore.password=localhost
ssl.key.password=localhost
ssl.enabled.protocols=TLSv1.2,TLSv1.1,TLSv1
ssl.keystore.type=JKS
ssl.client.auth=none
#ssl.endpoint.identification.algorithm=

双向认证配置

# 该配置配置的是内网ip
listeners=PLAINTEXT://172.31.95.70:9092,SSL://172.31.95.70:9093
# advertised  配置是提供给外网使用
advertised.listeners=PLAINTEXT://127.0.0.1:9092,SSL://127.0.0.1:9093

ssl.keystore.location=/home/ec2-user/ssl/server.keystore.jks
ssl.keystore.password=localhost
ssl.key.password=localhost
ssl.truststore.location=/home/ec2-user/ssl/server.truststore.jks
ssl.truststore.password=localhost
ssl.enabled.protocols=TLSv1.2,TLSv1.1,TLSv1
ssl.keystore.type=JKS
ssl.truststore.type=JKS
ssl.client.auth=required
#ssl.endpoint.identification.algorithm=

客户端配置

单向认证客户端生产者代码

public class Producer {
    public static void main(String[] args) throws InterruptedException {

        String server = "test.it:9093";
        Properties props = new Properties();
        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, server);
        props.put(ProducerConfig.CLIENT_ID_CONFIG, "DemoProducer");

        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());

        props.put("security.protocol", "SSL");
        props.put("ssl.truststore.location", "/Users/10100100010b/Downloads/ssl/client.truststore.jks");
        props.put("ssl.truststore.password", "localhost");
        KafkaProducer<Integer, String> producer = new KafkaProducer<>(props);

        String topic = "test";
        String message = "hello, kafka";
        producer.send(new ProducerRecord<>(topic, message), (metadata, exception) -> {
            System.out.println(metadata);
            if (exception != null) {
                System.out.println(exception);
            }
        });

        Thread.currentThread().join();
    }
}

双向认证客户端配置

public static void main(String[] args) throws InterruptedException {
        System.setProperty("javax.net.debug=all", "all");
        String server = "test.it:9093";
        Properties props = new Properties();
        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, server);
        props.put(ProducerConfig.CLIENT_ID_CONFIG, "DemoProducer");

        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());

        props.put("security.protocol", "SSL");
        props.put("ssl.keystore.location", "/Users/10100100010b/Downloads/ssl/client.keystore.jks");
        props.put("ssl.keystore.password", "localhost");
        props.put("ssl.key.password", "localhost");
        props.put("ssl.truststore.location", "/Users/10100100010b/Downloads/ssl/client.truststore.jks");
        props.put("ssl.truststore.password", "localhost");
        KafkaProducer<Integer, String> producer = new KafkaProducer<>(props);

        String topic = "test";
        String message = "hello, kafka";
        producer.send(new ProducerRecord<>(topic, message), (metadata, exception) -> {
            System.out.println(metadata);
            if (exception != null) {
                System.out.println(exception.getCause());
            }
        });

        Thread.currentThread().join();
}

host配置

# 外网ip对应的域名
127.0.0.1 test.it