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
- Install cfssl and cfssljson: Set up the cfssl toolkit.
- Generate a Self-Signed CA Certificate: Create a root CA using cfssl.
- Generate a Server Certificate for Nacos Signed by the CA: Create a certificate for your Nacos server.
- Configure the Nacos Server to Use the Server Certificate: Set up Nacos to use the generated certificate.
- Import the CA Certificate into Your Spring Boot Application's Docker Container: Ensure your application trusts the Nacos server's certificate.
- Configure Your Spring Boot Application: Update settings to communicate with the Nacos server over HTTPS.
- 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.
- Replace
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.p12in theclasspath(e.g., in theresourcesdirectory).
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: Ensureca.deris in the same directory as yourDockerfile.$JAVA_HOME/lib/security/cacerts: Default Java trust store.-storepass changeit: Default password forcacerts. 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.pemandnacos-key.pemare 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
CNorhostsin the certificate. - Solution:
- Ensure the Nacos server's domain matches the
CNor is included in thehostsfield. - Use the correct domain or IP address when accessing the server.
- As a temporary measure, disable hostname verification (not recommended for production).
- Ensure the Nacos server's domain matches the
Keytool Not Found
- Cause:
keytoolis 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
storepassused 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
COPYcommand and file paths in theDockerfile.
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!