Skip to content

Commit

Permalink
feat: implem tls validation Redis
Browse files Browse the repository at this point in the history
  • Loading branch information
Nico-dl05 committed Jan 8, 2025
1 parent 5937270 commit 66a46b2
Show file tree
Hide file tree
Showing 12 changed files with 296 additions and 18 deletions.
5 changes: 4 additions & 1 deletion Adaptors/Redis/src/ServiceCollectionExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ public static IServiceCollection AddRedis(this IServiceCollection serviceCollect
X509Certificate2? authority = null;
if (!string.IsNullOrEmpty(redisOptions.CaPath))
{
logger.LogDebug("Loading Redis certificate from {path}",
redisOptions.CaPath);
if (!File.Exists(redisOptions.CaPath))
{
logger.LogError("Redis certificate file not found: {path}",
Expand All @@ -84,7 +86,7 @@ public static IServiceCollection AddRedis(this IServiceCollection serviceCollect

(validationCallback, authority) = CertificateValidatorFactory.CreateCallback(redisOptions.CaPath,
logger);
logger.LogDebug("Server certificate validation callback set");
logger.LogDebug("Server certificate Redis validation callback set");
}
else
{
Expand Down Expand Up @@ -116,6 +118,7 @@ public static IServiceCollection AddRedis(this IServiceCollection serviceCollect
logger.LogDebug("setup connection to Redis at {EndpointUrl} with user {user}",
redisOptions.EndpointUrl,
redisOptions.User);
config.AbortOnConnectFail = false;
var connection = ConnectionMultiplexer.Connect(config);

serviceCollection.AddSingleton<IConnectionMultiplexer>(connection);
Expand Down
4 changes: 3 additions & 1 deletion Utils/src/ServerCertificateValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ public static bool ValidateServerCertificate(object sender,
var isTrusted = certChain.ChainElements.Any(x => x.Certificate.Thumbprint == authority.Thumbprint);
if (isTrusted)
{
logger.LogInformation("SSL validation succeeded");
logger.LogInformation("SSL validation succeeded for certificate: {subject}, Thumbprint: {thumbprint}",
cert.Subject,
cert.Thumbprint);
}
else
{
Expand Down
10 changes: 6 additions & 4 deletions terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ module "database" {
}

module "object_redis" {
source = "./modules/storage/object/redis"
count = var.object_storage.name == "redis" ? 1 : 0
image = var.object_storage.image
network = docker_network.armonik.id
source = "./modules/storage/object/redis"
count = var.object_storage.name == "redis" ? 1 : 0
image = "redis:latest"
exposed_port = 6380
network = docker_network.armonik.id
redis_params = var.redis_params
}

module "object_minio" {
Expand Down
6 changes: 5 additions & 1 deletion terraform/modules/compute_plane/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ resource "docker_container" "polling_agent" {
target = var.polling_agent.shared_socket
source = docker_volume.socket_vol.name
}

mounts {
type = "volume"
target = "/redis/certs"
source = "redis_certs"
}
restart = "unless-stopped"

dynamic "mounts" {
Expand Down
66 changes: 66 additions & 0 deletions terraform/modules/storage/object/redis/certificates.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
resource "tls_private_key" "redis_private_key" {
algorithm = "RSA"
rsa_bits = 4096
}

# Certificat auto-signé pour la CA
resource "tls_self_signed_cert" "redis_ca" {
private_key_pem = tls_private_key.redis_private_key.private_key_pem
is_ca_certificate = true
validity_period_hours = 87600
allowed_uses = [
"cert_signing",
"key_encipherment",
"digital_signature"
]
subject {
organization = "ArmoniK Redis Root CA"
common_name = "ArmoniK Root Certificate Authority"
country = "FR"
}
}

# Demande de certificat pour Redis
resource "tls_cert_request" "redis_cert_request" {
private_key_pem = tls_private_key.redis_private_key.private_key_pem
subject {
country = "FR"
organization = "ArmoniK"
common_name = "redis"
}
ip_addresses = ["127.0.0.1", "172.20.0.6"]
dns_names = ["localhost", "redis"]
}

# Certificat signé pour Redis
resource "tls_locally_signed_cert" "redis_cert" {
cert_request_pem = tls_cert_request.redis_cert_request.cert_request_pem
ca_private_key_pem = tls_private_key.redis_private_key.private_key_pem
ca_cert_pem = tls_self_signed_cert.redis_ca.cert_pem
validity_period_hours = 87600
allowed_uses = [
"key_encipherment",
"digital_signature",
"server_auth",
"client_auth"
]
}

# Fichiers locaux pour stockage des certificats et clés
resource "local_file" "ca" {
content = tls_self_signed_cert.redis_ca.cert_pem
filename = "${path.module}/generated/redis/certs/ca.pem"
file_permission = "0644"
}

resource "local_file" "cert" {
content = tls_locally_signed_cert.redis_cert.cert_pem
filename = "${path.module}/generated/redis/certs/redis.crt"
file_permission = "0644"
}

resource "local_file" "key" {
content = tls_private_key.redis_private_key.private_key_pem
filename = "${path.module}/generated/redis/certs/redis.key"
file_permission = "0600"
}
17 changes: 16 additions & 1 deletion terraform/modules/storage/object/redis/inputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,20 @@ variable "network" {

variable "exposed_port" {
type = number
default = 6379
default = 6380
}

variable "redis_params" {
type = object({
host = string
port = number
user = string
password = string
tls_enabled = bool
Ssl = bool
ca_path = string
cert_path = string
key_path = string
credentials = string
})
}
112 changes: 106 additions & 6 deletions terraform/modules/storage/object/redis/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,118 @@ resource "docker_image" "object" {
keep_locally = true
}

resource "docker_volume" "redis_certs" {
name = "redis_certs"
}

resource "null_resource" "create_dirs" {
provisioner "local-exec" {
command = <<EOT
mkdir -p ${path.module}/logs
chmod 777 ${path.module}/logs
mkdir -p ${path.module}/data
chmod 755 ${path.module}/data
mkdir -p ${path.module}/generated/redis/certs
chmod 755 ${path.module}/generated/redis/certs
EOT
}
}

resource "null_resource" "prepare_certs" {
provisioner "local-exec" {
command = <<EOT
docker run --rm \
-v ${docker_volume.redis_certs.name}:/redis/certs \
-v ${abspath("${path.module}/generated/redis/certs")}:/certs:ro \
alpine sh -c "
if [ -f /certs/redis.key ] && [ -f /certs/redis.crt ] && [ -f /certs/ca.pem ]; then \
cp /certs/* /redis/certs/ && \
chown -R 1000:1000 /redis/certs && \
chmod 600 /redis/certs/redis.key && \
chmod 644 /redis/certs/redis.crt && \
chmod 644 /redis/certs/ca.pem; \
else \
echo 'Missing certificates'; exit 1; \
fi"
EOT
}

depends_on = [
docker_volume.redis_certs,
local_file.ca,
local_file.cert,
local_file.key
]
}

resource "local_file" "redis_conf" {
filename = "${path.module}/redis.conf"
content = <<EOT
bind 0.0.0.0
tls-port 6380
tls-cert-file /redis/certs/redis.crt
tls-key-file /redis/certs/redis.key
tls-ca-cert-file /redis/certs/ca.pem
tls-auth-clients no
logfile /redis/logs/redis.log
tls-protocols "TLSv1.2 TLSv1.3"
EOT
}

resource "docker_container" "object" {
name = "object"
name = "redis"
image = docker_image.object.image_id

command = ["redis-server"]
user = "1000:1000"

networks_advanced {
name = var.network
}

command = [
"redis-server",
"/etc/redis/redis.conf"
]

ports {
internal = 6379
external = var.exposed_port
internal = 6380
external = 6380 // si on utilise var ==> Erreur au déploiement
}

# Montage des certificats depuis le volume Docker
mounts {
target = "/redis/certs"
source = docker_volume.redis_certs.name
type = "volume"
read_only = false
}
}

# Montage du fichier de configuration Redis
mounts {
target = "/etc/redis/redis.conf"
source = abspath("${path.module}/redis.conf")
type = "bind"
read_only = true
}

# Montage des logs Redis
mounts {
target = "/redis/logs"
source = abspath("${path.module}/logs")
type = "bind"
read_only = false
}

mounts {
target = "/data"
source = abspath("${path.module}/data")
type = "bind"
read_only = false
}

depends_on = [
docker_image.object,
null_resource.prepare_certs,
null_resource.create_dirs,
local_file.redis_conf
]
}
28 changes: 27 additions & 1 deletion terraform/modules/storage/object/redis/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,35 @@
output "generated_env_vars" {
value = ({
"Redis__User" = var.redis_params.user
"Redis__Password" = var.redis_params.password
"Redis__Host" = var.redis_params.host
"Redis__Port" = var.redis_params.port
"Redis__Ssl" = var.redis_params.tls_enabled
"Redis__Scheme" = "redis"
"Redis__CaPath" = "/redis/certs/ca.pem"
"Redis__CertPath" = "/redis/certs/redis.crt"
"Redis__KeyPath" = "/redis/certs/redis.key"
"Redis_Timeout" = "20000"
"Components__ObjectStorage" = "ArmoniK.Adapters.Redis.ObjectStorage",
"Redis__EndpointUrl" = "object:${var.exposed_port}"
"Redis__EndpointUrl" = "${var.redis_params.host}:${var.redis_params.port}"
})
}

output "core_mounts" {
value = {
"/redis/certs/ca.pem" = local_file.ca.filename
"/redis/certs/redis.crt" = local_file.cert.filename
"/redis/certs/redis.key" = local_file.key.filename
}
}

locals {
redis_endpoints = {
ip = "redis"
port = 6380
}
}

output "volumes" {
description = "Volumes that agents and submitters must mount to access the object storage"
value = {}
Expand Down
20 changes: 19 additions & 1 deletion terraform/modules/submitter/inputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,27 @@ variable "mounts" {
type = map(string)
}

variable "redis_base_path" {
description = "Chemin de base pour les certificats Redis"
type = string
default = ""
}
variable "certs_path" {
description = "Chemin local vers les certificats Redis"
type = string
default = ""
}
variable "default_certs_path" {
description = "Chemin par défaut des certificats Redis"
type = string
default = "/../../storage/object/redis/generated/redis/certs"
}

variable "volumes" {
type = map(string)
default = {
"redis-data" = "/data"
}
}

variable "log_driver" {
Expand All @@ -32,4 +51,3 @@ variable "log_driver" {
log_opts = map(string),
})
}

13 changes: 13 additions & 0 deletions terraform/modules/submitter/locals.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
locals {
effective_certs_path = abspath("${path.module}/../storage/object/redis/generated/redis/certs")

redis_cert_mounts = {
"${local.effective_certs_path}/ca.pem" = "/redis/certs/ca.pem",
"${local.effective_certs_path}/redis.crt" = "/redis/certs/redis.crt",
"${local.effective_certs_path}/redis.key" = "/redis/certs/redis.key"
}

env = [
"Submitter__DefaultPartition=TestPartition0",
"Redis__Ssl=true",
"Redis__CaPath=/redis/certs/ca.pem",
"Redis__CertPath=/redis/certs/redis.crt",
"Redis__KeyPath=/redis/certs/redis.key",
"Redis__Timeout=20000"
]
gen_env = [for k, v in var.generated_env_vars : "${k}=${v}"]
}
Loading

0 comments on commit 66a46b2

Please sign in to comment.