13 – TLS/HTTPS
Version : 4.0.0 Date : 2025-12-09
1. Introduction
Configuration du TLS/HTTPS pour sécuriser les communications HTTP du Socle V4.
2. Configuration Spring Boot
2.1 application.yml
server:
port: ${HTTPS_PORT:8443}
ssl:
enabled: ${SSL_ENABLED:true}
key-store: ${SSL_KEYSTORE:classpath:keystore.p12}
key-store-password: ${SSL_KEYSTORE_PASSWORD:changeit}
key-store-type: ${SSL_KEYSTORE_TYPE:PKCS12}
key-alias: ${SSL_KEY_ALIAS:socle}
2.2 Variables d’environnement
| Variable | Description | Défaut |
|---|---|---|
SSL_ENABLED |
Activer SSL | false |
SSL_KEYSTORE |
Chemin du keystore | classpath:keystore.p12 |
SSL_KEYSTORE_PASSWORD |
Mot de passe keystore | changeit |
SSL_KEYSTORE_TYPE |
Type de keystore | PKCS12 |
SSL_KEY_ALIAS |
Alias de la clé | socle |
3. Génération des certificats
3.1 Certificat auto-signé (développement)
# Générer un keystore PKCS12 avec certificat auto-signé
keytool -genkeypair \
-alias socle \
-keyalg RSA \
-keysize 2048 \
-storetype PKCS12 \
-keystore keystore.p12 \
-validity 365 \
-dname "CN=localhost,OU=Dev,O=MyCompany,L=Paris,C=FR" \
-storepass changeit \
-keypass changeit
# Exporter le certificat (pour les clients)
keytool -exportcert \
-alias socle \
-keystore keystore.p12 \
-storetype PKCS12 \
-storepass changeit \
-file socle.crt
3.2 Avec Let’s Encrypt (production)
# Obtenir le certificat
certbot certonly --standalone -d myapp.example.com
# Convertir en PKCS12
openssl pkcs12 -export \
-in /etc/letsencrypt/live/myapp.example.com/fullchain.pem \
-inkey /etc/letsencrypt/live/myapp.example.com/privkey.pem \
-out keystore.p12 \
-name socle \
-passout pass:changeit
3.3 Avec CA interne
# Générer CSR
keytool -certreq \
-alias socle \
-keystore keystore.p12 \
-file socle.csr \
-storepass changeit
# Après signature par la CA, importer le certificat
keytool -importcert \
-alias socle \
-keystore keystore.p12 \
-file signed-cert.crt \
-storepass changeit
# Importer la chaîne CA
keytool -importcert \
-alias ca-root \
-keystore keystore.p12 \
-file ca-root.crt \
-storepass changeit
4. Configuration avancée
4.1 Mutual TLS (mTLS)
server:
ssl:
enabled: true
key-store: ${SSL_KEYSTORE:keystore.p12}
key-store-password: ${SSL_KEYSTORE_PASSWORD}
key-store-type: PKCS12
# Trust store pour vérifier les clients
trust-store: ${SSL_TRUSTSTORE:truststore.p12}
trust-store-password: ${SSL_TRUSTSTORE_PASSWORD}
trust-store-type: PKCS12
# Exiger certificat client
client-auth: ${SSL_CLIENT_AUTH:need} # none, want, need
4.2 Protocoles et Ciphers
server:
ssl:
enabled-protocols: TLSv1.3,TLSv1.2
ciphers:
- TLS_AES_256_GCM_SHA384
- TLS_AES_128_GCM_SHA256
- TLS_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
5. HTTP + HTTPS (dual port)
5.1 Configuration
@Configuration
public class TlsConfiguration {
@Value("${server.http.port:8080}")
private int httpPort;
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(createHttpConnector());
return tomcat;
}
private Connector createHttpConnector() {
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setScheme("http");
connector.setPort(httpPort);
connector.setSecure(false);
return connector;
}
}
5.2 Redirection HTTP → HTTPS
@Configuration
public class HttpsRedirectConfiguration {
@Bean
public TomcatServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(httpToHttpsRedirectConnector());
return tomcat;
}
private Connector httpToHttpsRedirectConnector() {
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setScheme("http");
connector.setPort(8080);
connector.setSecure(false);
connector.setRedirectPort(8443);
return connector;
}
}
6. Client HTTPS
6.1 OkHttpClient avec TLS
@Configuration
public class HttpClientConfiguration {
@Value("${ssl.truststore:#{null}}")
private Resource trustStore;
@Value("${ssl.truststore-password:changeit}")
private String trustStorePassword;
@Bean
public OkHttpClient secureHttpClient() throws Exception {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (trustStore != null && trustStore.exists()) {
KeyStore ks = KeyStore.getInstance("PKCS12");
try (InputStream is = trustStore.getInputStream()) {
ks.load(is, trustStorePassword.toCharArray());
}
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
builder.sslSocketFactory(sslContext.getSocketFactory(),
(X509TrustManager) tmf.getTrustManagers()[0]);
}
return builder
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
}
}
6.2 Bypass SSL pour développement (NON RECOMMANDÉ)
// UNIQUEMENT POUR LE DÉVELOPPEMENT - NE PAS UTILISER EN PRODUCTION
public OkHttpClient insecureClient() throws Exception {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) {}
public void checkServerTrusted(X509Certificate[] chain, String authType) {}
public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new SecureRandom());
return new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0])
.hostnameVerifier((hostname, session) -> true)
.build();
}
7. Docker avec TLS
7.1 Dockerfile
FROM eclipse-temurin:21-jre
WORKDIR /app
# Copier le certificat
COPY keystore.p12 /app/certs/keystore.p12
# Copier l'application
COPY target/socle-v004-4.0.0.jar app.jar
ENV SSL_ENABLED=true
ENV SSL_KEYSTORE=/app/certs/keystore.p12
EXPOSE 8443
ENTRYPOINT ["java", "-jar", "app.jar"]
7.2 docker-compose.yml
version: '3.8'
services:
socle-app:
image: socle-v4:latest
environment:
- SSL_ENABLED=true
- SSL_KEYSTORE=/app/certs/keystore.p12
- SSL_KEYSTORE_PASSWORD_FILE=/run/secrets/ssl_password
ports:
- "8443:8443"
volumes:
- ./certs:/app/certs:ro
secrets:
- ssl_password
secrets:
ssl_password:
file: ./secrets/ssl_password.txt
8. Kubernetes avec TLS
8.1 Secret pour le certificat
apiVersion: v1
kind: Secret
metadata:
name: socle-tls
type: kubernetes.io/tls
data:
tls.crt: <base64-encoded-cert>
tls.key: <base64-encoded-key>
8.2 Ingress avec TLS
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: socle-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- socle.example.com
secretName: socle-tls
rules:
- host: socle.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: socle-service
port:
number: 8080
8.3 cert-manager
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: socle-cert
spec:
secretName: socle-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- socle.example.com
9. Vérification
9.1 Test avec curl
# Test HTTPS
curl -v https://localhost:8443/admin/health
# Avec certificat client (mTLS)
curl -v --cert client.crt --key client.key https://localhost:8443/admin/health
# Ignorer la vérification (dev only)
curl -vk https://localhost:8443/admin/health
9.2 Test avec openssl
# Vérifier le certificat du serveur
openssl s_client -connect localhost:8443 -showcerts
# Vérifier les protocoles supportés
openssl s_client -connect localhost:8443 -tls1_3
# Vérifier les ciphers
openssl s_client -connect localhost:8443 -cipher 'ECDHE-RSA-AES256-GCM-SHA384'
10. Troubleshooting
Erreur: PKIX path building failed
Le certificat du serveur n’est pas trusté.
# Importer le certificat dans le truststore Java
keytool -importcert \
-alias server-cert \
-file server.crt \
-keystore $JAVA_HOME/lib/security/cacerts \
-storepass changeit
Erreur: Handshake failure
Incompatibilité de protocole ou cipher.
# Vérifier les protocoles
openssl s_client -connect host:port -tls1_2
openssl s_client -connect host:port -tls1_3
Erreur: Certificate expired
Renouveler le certificat et recréer le keystore.
11. Bonnes pratiques
DO
- Utiliser TLS 1.2 minimum, TLS 1.3 recommandé
- Renouveler les certificats avant expiration
- Utiliser des clés RSA 2048 bits minimum ou ECDSA 256 bits
- Activer HSTS en production
- Utiliser cert-manager en Kubernetes
DON’T
- Ne pas utiliser de certificats auto-signés en production
- Ne pas désactiver la vérification des certificats
- Ne pas stocker les mots de passe en clair
- Ne pas utiliser TLS 1.0 ou 1.1 (dépréciés)
12. Références
- 10-SECURITY – Sécurité
- Let’s Encrypt
- cert-manager

Laisser un commentaire