Files
vault-para/100-project/Work/Nacos with Self Signed Certificate.md
2025-12-29 13:38:39 +08:00

14 KiB

Certainly! I can guide you through the process of using cfssl (Cloudflare's PKI toolkit) to generate a self-signed Certificate Authority (CA) and server certificate for your Nacos server. Then, I'll show you how to import the CA certificate into your Spring Boot application's Docker container so that it trusts the Nacos server's certificate.

This approach provides a robust and manageable way to handle certificates, especially when dealing with multiple services and environments.


Overview

  1. Install cfssl and cfssljson: Set up the cfssl toolkit.
  2. Generate a Self-Signed CA Certificate: Create a root CA using cfssl.
  3. Generate a Server Certificate for Nacos Signed by the CA: Create a certificate for your Nacos server.
  4. Configure the Nacos Server to Use the Server Certificate: Set up Nacos to use the generated certificate.
  5. Import the CA Certificate into Your Spring Boot Application's Docker Container: Ensure your application trusts the Nacos server's certificate.
  6. Configure Your Spring Boot Application: Update settings to communicate with the Nacos server over HTTPS.
  7. Test the Setup: Verify that everything works as expected.

Prerequisites

  • cfssl and cfssljson installed on your system.
  • Nacos server installed and running.
  • Docker installed and configured.
  • Spring Boot application ready to be containerized.

Step 1: Install cfssl and cfssljson

First, you need to install cfssl and cfssljson. These are command-line tools provided by Cloudflare for managing PKI.

1.1. Download the Binaries

For Linux:

# Download cfssl
curl -L -o cfssl https://github.com/cloudflare/cfssl/releases/download/v1.6.3/cfssl_linux-amd64

# Download cfssljson
curl -L -o cfssljson https://github.com/cloudflare/cfssl/releases/download/v1.6.3/cfssljson_linux-amd64

For macOS:

# Download cfssl
curl -L -o cfssl https://github.com/cloudflare/cfssl/releases/download/v1.6.3/cfssl_darwin-amd64

# Download cfssljson
curl -L -o cfssljson https://github.com/cloudflare/cfssl/releases/download/v1.6.3/cfssljson_darwin-amd64

1.2. Make the Binaries Executable

chmod +x cfssl cfssljson

1.3. Move the Binaries to Your PATH

sudo mv cfssl cfssljson /usr/local/bin/

Alternatively, you can add the directory containing cfssl and cfssljson to your PATH.

1.4. Verify Installation

cfssl version
cfssljson -version

Step 2: Generate a Self-Signed CA Certificate

We'll create a self-signed CA certificate using cfssl.

2.1. Create a CA Configuration File (ca-config.json)

Create a file named ca-config.json with the following content:

{
  "signing": {
    "default": {
      "expiry": "8760h"
    },
    "profiles": {
      "nacos": {
        "expiry": "87600h",
        "usages": ["signing", "key encipherment", "server auth", "client auth"]
      }
    }
  }
}

2.2. Create a CA Certificate Signing Request (ca-csr.json)

Create a file named ca-csr.json with the following content:

{
  "CN": "My Root CA",
  "key": {
    "algo": "rsa",
    "size": 4096
  },
  "names": [
    {
      "C": "US",
      "ST": "State",
      "L": "City",
      "O": "YourOrganization",
      "OU": "YourUnit"
    }
  ]
}

2.3. Generate the CA Certificate and Key

Run the following command:

cfssl gencert -initca ca-csr.json | cfssljson -bare ca

This command generates:

  • ca.pem: The CA certificate.
  • ca-key.pem: The CA private key.
  • ca.csr: The CA certificate signing request (not needed further).

Note: Keep ca-key.pem secure and do not share it.


Step 3: Generate a Server Certificate for Nacos Signed by the CA

3.1. Create a Server Certificate Signing Request (nacos-csr.json)

Create a file named nacos-csr.json with the following content:

{
  "CN": "nacos.example.com",
  "hosts": [
    "nacos.example.com",
    "127.0.0.1",
    "192.168.1.100"
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "US",
      "ST": "State",
      "L": "City",
      "O": "YourOrganization",
      "OU": "YourUnit"
    }
  ]
}
  • CN: Common Name. Should match the domain name used to access Nacos.
  • hosts: Include all DNS names and IP addresses that will be used to access the Nacos server.
    • Replace "nacos.example.com" and "192.168.1.100" with your server's actual domain and IP address.

3.2. Generate the Server Certificate and Key

Run the following command:

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=nacos nacos-csr.json | cfssljson -bare nacos

This command generates:

  • nacos.pem: The Nacos server certificate.
  • nacos-key.pem: The Nacos server private key.
  • nacos.csr: The Nacos server CSR (not needed further).

3.3. Verify the Certificates

You can inspect the server certificate:

openssl x509 -in nacos.pem -text -noout

Step 4: Configure the Nacos Server to Use the Server Certificate

Now, configure your Nacos server to use the generated nacos.pem and nacos-key.pem files.

4.1. Convert the Certificates to PKCS#12 Format (If Necessary)

Some servers require certificates in PKCS#12 format.

openssl pkcs12 -export -in nacos.pem -inkey nacos-key.pem -out nacos.p12 -name nacos -CAfile ca.pem -caname root -password pass:yourpassword
  • nacos.p12: The PKCS#12 keystore file.
  • yourpassword: Replace with a secure password.

4.2. Configure Nacos to Use SSL

Option A: Standalone Nacos (Embedded Tomcat)

If you're running Nacos in standalone mode using embedded Tomcat, you can configure SSL in application.properties or application.yml.

In application.properties:

server.port=8848
server.ssl.enabled=true
server.ssl.key-store=classpath:nacos.p12
server.ssl.key-store-password=yourpassword
server.ssl.key-store-type=PKCS12
  • Note: Place nacos.p12 in the classpath (e.g., in the resources directory).

Option B: Nacos with External Tomcat or Nginx

If you're using an external server (like Tomcat or Nginx), configure it to use nacos.pem and nacos-key.pem.

Example with Nginx:

server {
    listen 443 ssl;
    server_name nacos.example.com;

    ssl_certificate     /path/to/nacos.pem;
    ssl_certificate_key /path/to/nacos-key.pem;
    ssl_client_certificate /path/to/ca.pem;
    ssl_verify_client off; # Change to 'on' if you want to verify client certificates

    location / {
        proxy_pass http://localhost:8848;
    }
}

4.3. Restart the Nacos Server

After configuring SSL, restart your Nacos server to apply the changes.


Step 5: Import the CA Certificate into Your Spring Boot Application's Docker Container

Your Spring Boot application needs to trust the CA that signed the Nacos server's certificate. We'll import ca.pem into the Java trust store inside your Docker container.

5.1. Convert the CA Certificate to DER Format

Java keytool requires certificates in DER format.

openssl x509 -outform der -in ca.pem -out ca.der

5.2. Update Your Dockerfile

Modify your Dockerfile to include the CA certificate and import it into the Java trust store.

Example Dockerfile:

# Use an official OpenJDK runtime as a parent image
FROM openjdk:17-jdk-slim

# Set the working directory
WORKDIR /app

# Copy the application's JAR file into the container
COPY target/your-application.jar /app/your-application.jar

# Copy the CA certificate into the container
COPY ca.der /tmp/ca.der

# Import the CA certificate into Java's trust store
RUN keytool -importcert \
    -alias myca \
    -keystore $JAVA_HOME/lib/security/cacerts \
    -file /tmp/ca.der \
    -storepass changeit \
    -noprompt

# Clean up the temporary certificate file
RUN rm /tmp/ca.der

# Expose the application port
EXPOSE 8080

# Run the application
ENTRYPOINT ["java", "-jar", "/app/your-application.jar"]

Notes:

  • COPY ca.der /tmp/ca.der: Ensure ca.der is in the same directory as your Dockerfile.
  • $JAVA_HOME/lib/security/cacerts: Default Java trust store.
  • -storepass changeit: Default password for cacerts. Use the correct password if it's different.

5.3. Build the Docker Image

docker build -t your-application-image .

5.4. Run the Docker Container

docker run -p 8080:8080 your-application-image

Step 6: Configure Your Spring Boot Application

Ensure your application is configured to communicate with the Nacos server over HTTPS.

6.1. Update Application Properties

In your application.properties or application.yml, update the Nacos server address to use https and the correct port.

Example (application.properties):

spring.cloud.nacos.server-addr=https://nacos.example.com:8848
spring.cloud.nacos.username=your-username
spring.cloud.nacos.password=your-password

6.2. Disable Hostname Verification (If Necessary)

If the hostname verification fails, you may need to disable it (not recommended for production).

Add the following JVM option:

-Dcom.sun.net.ssl.checkRevocation=false -Djavax.net.ssl.trustStore=$JAVA_HOME/lib/security/cacerts

Alternatively, set up a custom HostnameVerifier in your code.


Step 7: Test the Setup

After starting your Docker container, test your application to ensure it communicates securely with the Nacos server.

  • Check Logs: Look for any SSL-related errors.
  • Verify Communication: Ensure your application can register with Nacos or retrieve configurations.

Additional Considerations

Using a Custom Trust Store

Instead of modifying the default Java trust store (cacerts), you can create and use a custom trust store.

5.2.1. Create a Custom Trust Store

# Create a custom trust store and import the CA certificate
RUN keytool -importcert \
    -alias myca \
    -keystore /app/truststore.jks \
    -file /tmp/ca.der \
    -storepass yourtruststorepassword \
    -noprompt

5.2.2. Set JVM Options to Use the Custom Trust Store

# Set environment variable for JVM options
ENV JAVA_OPTS="-Djavax.net.ssl.trustStore=/app/truststore.jks -Djavax.net.ssl.trustStorePassword=yourtruststorepassword"

5.2.3. Update the ENTRYPOINT

ENTRYPOINT ["java", "$JAVA_OPTS", "-jar", "/app/your-application.jar"]

Handling Sensitive Information

Avoid hardcoding passwords in your Dockerfile. Use build arguments or environment variables.

Using Build Arguments

# Build argument for trust store password
ARG TRUSTSTORE_PASS=yourtruststorepassword

# Use the build argument in the RUN command
RUN keytool -importcert \
    -alias myca \
    -keystore /app/truststore.jks \
    -file /tmp/ca.der \
    -storepass $TRUSTSTORE_PASS \
    -noprompt

# Set JVM options
ENV JAVA_OPTS="-Djavax.net.ssl.trustStore=/app/truststore.jks -Djavax.net.ssl.trustStorePassword=$TRUSTSTORE_PASS"

Build the Docker image with:

docker build --build-arg TRUSTSTORE_PASS=yourtruststorepassword -t your-application-image .

Securing Private Keys

  • Do Not Include Private Keys in Docker Images: Ensure that ca-key.pem and nacos-key.pem are not copied into the Docker image.
  • Secure Storage: Store private keys securely and avoid committing them to version control.

Troubleshooting

Common Issues and Solutions

SSLHandshakeException

  • Cause: The application doesn't trust the Nacos server's certificate.
  • Solution: Ensure the CA certificate is correctly imported into the trust store.

Hostname Verification Failure

  • Cause: The hostname used to access the Nacos server doesn't match the CN or hosts in the certificate.
  • Solution:
    • Ensure the Nacos server's domain matches the CN or is included in the hosts field.
    • Use the correct domain or IP address when accessing the server.
    • As a temporary measure, disable hostname verification (not recommended for production).

Keytool Not Found

  • Cause: keytool is not available in the base Docker image.
  • Solution: Use a JDK-based Docker image (e.g., openjdk:17-jdk-slim) instead of a JRE image.

Incorrect Keystore Password

  • Cause: Wrong storepass used when importing the certificate.
  • Solution: Verify the trust store password.

Certificate Not Found

  • Cause: The certificate file is not correctly copied or the path is incorrect.
  • Solution: Verify the COPY command and file paths in the Dockerfile.

Testing the Trust Store

List the certificates in the trust store to confirm the import:

RUN keytool -list -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit

Summary

By using cfssl, you've:

  • Created a self-signed CA certificate.
  • Generated a server certificate for your Nacos server signed by the CA.
  • Configured your Nacos server to use the new SSL certificate.
  • Imported the CA certificate into your Spring Boot application's Docker container, ensuring trust.
  • Configured your application to communicate with the Nacos server over HTTPS.

This setup enhances security by establishing a trusted SSL connection between your application and the Nacos server.


Next Steps

  • Automate Certificate Management: Consider automating certificate renewal and distribution.
  • Use a Trusted CA in Production: For production environments, obtain certificates from a trusted Certificate Authority.
  • Monitor SSL Connections: Implement monitoring to detect and resolve SSL issues promptly.

References


Feel free to ask if you have any questions or need further assistance with any of the steps!