vault backup: 2026-01-05 13:03:55
This commit is contained in:
@@ -0,0 +1,508 @@
|
||||
|
||||
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:**
|
||||
|
||||
```bash
|
||||
# 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:**
|
||||
|
||||
```bash
|
||||
# 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**
|
||||
|
||||
```bash
|
||||
chmod +x cfssl cfssljson
|
||||
```
|
||||
|
||||
### **1.3. Move the Binaries to Your PATH**
|
||||
|
||||
```bash
|
||||
sudo mv cfssl cfssljson /usr/local/bin/
|
||||
```
|
||||
|
||||
Alternatively, you can add the directory containing `cfssl` and `cfssljson` to your `PATH`.
|
||||
|
||||
### **1.4. Verify Installation**
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```json
|
||||
{
|
||||
"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:
|
||||
|
||||
```json
|
||||
{
|
||||
"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:
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```json
|
||||
{
|
||||
"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:
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```bash
|
||||
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.
|
||||
|
||||
```bash
|
||||
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`:**
|
||||
|
||||
```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:**
|
||||
|
||||
```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.
|
||||
|
||||
```bash
|
||||
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:**
|
||||
|
||||
```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**
|
||||
|
||||
```bash
|
||||
docker build -t your-application-image .
|
||||
```
|
||||
|
||||
### **5.4. Run the Docker Container**
|
||||
|
||||
```bash
|
||||
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`):**
|
||||
|
||||
```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:
|
||||
|
||||
```bash
|
||||
-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**
|
||||
|
||||
```dockerfile
|
||||
# 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**
|
||||
|
||||
```dockerfile
|
||||
# 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**
|
||||
|
||||
```dockerfile
|
||||
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**
|
||||
|
||||
```dockerfile
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```dockerfile
|
||||
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**
|
||||
|
||||
- [cfssl GitHub Repository](https://github.com/cloudflare/cfssl)
|
||||
- [Nacos Documentation](https://nacos.io/en-us/docs/what-is-nacos.html)
|
||||
- [Spring Boot SSL Configuration](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-configure-ssl)
|
||||
|
||||
---
|
||||
|
||||
Feel free to ask if you have any questions or need further assistance with any of the steps!
|
||||
Reference in New Issue
Block a user