Saltar al contenido principal
Version: 1.8.1

Para realizar pruebas básicas se puede disponer de certificados creados por CAs propias y firmados por las mismas, recuerde que estos certificados NO son válidos para un entorno productivo y que los navegadores solicitarán agregar excepciones para permitir la navegación.

Previo a la generación de los certificados, asegurese de cumplir con los requisitos previos.

Generando CAs y certificados de prueba con OpenSSL

Estructura:

Antes de empezar, se recomienda correr el siguiente comando para generar la estructura de directorios completa que utilizaremos en la guía. Dichos directorios se ubicaran en /srv/tls.

mkdir -p /srv/tls/{certs,private,intermediate/{certs,csr,private}}

Asegurese que la estructura final haya quedado como muestra la siguiente captura

$ tree command image

Pasos para construir las CAs y sus certificados correspondientes

Ubiquese en la carpeta raíz de los certificados para continuar con los siguientes pasos: /srv/tls

cd /srv/tls

Creación de CA Raíz

1) Creacion de archivos para seguimiento de certificados

Se debe generar un archivo de serie, necesario para realizar un seguimiento del último número de serie que se utilizó para emitir un certificado:

echo 01 > serial

Luego debe crear un archivo vacio de nombre index.txt, el cual OpenSSL utilizará como "base de datos" para el seguimiento de los certificados emitidos por la CA

touch index.txt

Finalizado dicho paso, el contenido de /srv/tls debería quedar de la siguiente manera:

drwxr-xr-x 2 root root 4096 Apr  8 22:29 certs
-rw-r--r-- 1 root root 0 Apr 9 03:36 index.txt
drwxr-xr-x 5 root root 4096 Apr 9 03:34 intermediate
drwxr-xr-x 2 root root 4096 Apr 9 03:34 private
-rw-r--r-- 1 root root 3 Apr 9 03:37 serial

2) Configurar openssl.cnf para el certificado de CA raíz

A continuación se debe crear el archivo openssl.cnf en /srv/tls con el siguiente contenido:

HOME                    = .
#RANDFILE = $ENV::HOME/.rnd
oid_section = new_oids

#openssl_conf = default_modules

#[ default_modules ]
#ssl_conf = ssl_module

#[ ssl_module ]
#system_default = crypto_policy

#[ crypto_policy ]
#.include /etc/crypto-policies/back-ends/opensslcnf.config

[ new_oids ]

[ ca ]
default_ca = CA_default # The default ca section

[ CA_default ]
dir = . # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
database = $dir/index.txt # database index file.
# several certs with same subject.
new_certs_dir = $dir/certs # default place for new certs.
certificate = $dir/certs/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
private_key = $dir/private/cakey.pem # The private key

name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options

default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = sha256 # use SHA-256 by default
preserve = no # keep passed DN ordering
policy = policy_match

[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ req ]
default_bits = 4096
default_md = sha256
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
string_mask = nombstr

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = AR
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = BS-AS
localityName = Locality Name (eg, city)
localityName_default = CABA
0.organizationName = Organization Name (eg, company)
0.organizationName_default = Universidad
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64

[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true

[ v3_intermediate_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

De este archivo, observe que la variable dir esta referenciando al path relativo de su ubicación en el momento (es decir, .). Por este motivo, asegurese nuevamente de que se encuentre ubicado en la carpeta /srv/tls (o en su defecto, cambie el valor de dir = . por dir = /srv/tls)

Con esto ya tendría completa la configuración del archivo openssl.cnf que utilizará para la creación de certificados

3) Generacion de Root CA Private Key

Para generar la private key de la root CA, cree un archivo sin extensión denominado mypass con una contraseña como contenido del mismo. Reemplace la palabra secret en el comando de abajo con la contraseña que usted elija:

echo secret > mypass

Una vez creado el archivo mypass, se lo encriptará utilizando un comando de OpenSSL. Al correr dicho comando nos pedirá una contraseña para la encripción. Como output se creará el archivo mypass.enc con el secret encriptado

openssl enc -aes256 -pbkdf2 -salt -in mypass -out mypass.enc

Puede verificar que el archivo quedó encriptado de la siguiente manera:

cat mypass.enc

De ser necesario, se puede descifrar utilizando este comando:

openssl enc -aes256 -pbkdf2 -salt -d -in mypass.enc
enter aes-256-cbc decryption password:

Una vez que haya verificado y confirmado que posee el archivo mypass.enc, finalmente debe crear la key privada de la CA raíz usando 4096 bits y encriptación 3DES. En el mismo comando se utilizará mypass.enc para proporcionar la frase de contraseña para la key privada. Se guardará esta clave privada en srv/tls/private

openssl genrsa -des3 -passout file:mypass.enc -out private/cakey.pem 4096

IMPORTANTE: Si la clave se filtra o es robada, la integridad de toda la CA se ve comprometida, lo que implica que los certificados emitidos (se hayan emitido antes o después de que la clave se viera comprometida) no son más confiables.

4) Creacion certificado de CA raíz

Nota: Es recomendado distinguir el common name (CN) de cada uno de los certificados a la hora de crearlos, ejemplo:

CA Root -->  CN --> Root CA
CA Intermedia --> CN --> Intermedia

Asigne al certificado raíz una fecha de caducidad larga, ya que una vez que caduca el certificado raíz, todos los certificados firmados por la CA pierden su validez:

openssl req -new -x509 -days 3650 -passin file:mypass.enc -config openssl.cnf -extensions v3_ca -key private/cakey.pem -out certs/cacert.pem

Cambie el formato de CRT a formato PEM:

openssl x509 -in certs/cacert.pem -out certs/cacert.pem -outform PEM

Ejecute el siguiente comando para que OpenSSL verifique el certificado de CA raíz:

openssl x509 -noout -text -in certs/cacert.pem

Creación de CA Intermedia

5) Creacion de archivo para seguimiento de certificados intermedios

Cree nuevamente los archivos index.txt y serial para los subdirectorios de la CA intermedia en /srv/tls/intermediate.

touch intermediate/index.txt
echo 01 > intermediate/serial

Se debe además agregar un nuevo archivo crlnumber, que utilizará la CA intermedia para realizar un seguimiento de las listas de revocación de certificados.

echo 01 > intermediate/crlnumber

6) Configurar `openssl.cnf para el certificado de CA intermedio

Se debe copiar el archivo openssl.cnf utilizado para el Certificado de CA raíz de /srv/tls/openssl.cnf a /srv/tls/intermediate/openssl.cnf.

cp openssl.cnf intermediate/

Una vez hecho esto, modifique los siguientes parámetros del intermediate/openssl.cnf con su editor de texto favorito:

certificate     = $dir/certs/intermediate.cacert.pem   # The CA certificate
private_key = $dir/private/intermediate.cakey.pem # The private key
policy = policy_anything

7) Generar CA intermedia

Genere la clave CA intermedia ca-intermediate.key. usando openssl genrsa con cifrado 3DES y el archivo de frase de contraseña cifrada mypass.enc.

openssl genrsa -des3 -passout file:mypass.enc -out intermediate/private/intermediate.cakey.pem 4096

8) Crear immediate CA Certificate Signing Request (CSR)

Debe utilizar la intermediate CA key para crear la solicitud de firma de certificado (CSR).

Los detalles deben coincidir con la CA raíz.

El Common Name, sin embargo, debe ser diferente (ej: EEI CSR Intermediate CA).

openssl req -new -sha256 -config intermediate/openssl.cnf -passin file:mypass.enc  -key intermediate/private/intermediate.cakey.pem -out intermediate/csr/intermediate.csr.pem

9) Firmar y generar certificado CA intermedio

Para el último paso debe crear un certificado de CA intermedio utilizando nuestra solicitud de firma de certificado que creamos en el paso anterior. El siguiente comando utilizará la extensión v3_intermediate_ca de /srv/tls/openssl.cnf para crear el certificado de CA intermedio en /srv/tls/intermediate/certs/intermediate.cacert.pem

openssl ca -config openssl.cnf -extensions v3_intermediate_ca -days 2650 -notext -batch -passin file:mypass.enc -in intermediate/csr/intermediate.csr.pem -out intermediate/certs/intermediate.cacert.pem

Si desea verificar el certificado intermedio puede ejecutar el siguiente comando:

openssl x509 -noout -text -in intermediate/certs/intermediate.cacert.pem

A continuación, realice un chequeo para verificar el certificado intermedio contra el certificado raíz. Un OK indica que la cadena de confianza está intacta y correcta. En caso de haber un error en este paso, deberá volver a crear los certificados.

openssl verify -CAfile certs/cacert.pem intermediate/certs/intermediate.cacert.pem

Si la verificación anterior dio OK, convierta el formato de CRT a formato PEM

openssl x509 -in intermediate/certs/intermediate.cacert.pem -out intermediate/certs/intermediate.cacert.pem -outform PEM

10) Creacion de cadena de confianza entre los certificados de la CA raíz y la CA intermedia (Certificate Chain)

Se combina los certificados CA raíz e intermedio para abrir una cadena de certificados en Linux. Este archivo se utilizará más adelante para verificar los certificados firmados por la CA intermedia.

cat intermediate/certs/intermediate.cacert.pem certs/cacert.pem > intermediate/certs/ca-chain-bundle.cert.pem

Para verificar la cadena de las CAs, utilice el siguiente comando:

openssl verify -CAfile certs/cacert.pem intermediate/certs/ca-chain-bundle.cert.pem

Una vez verificada la cadena de CAs, puede proceder finalmente a la creación de los certificados del servidor.

Certificados para el servidor

Crear la clave privada del servidor (server.key.pem) usando el comando openssl.

openssl genrsa -out server.key.pem 4096

Crear Certificate Signing Request (CSR) usando la clave del servidor

Se utilizará la clave del servidor server.key.pem para generar el Certificate Signing Request (CSR) server.csr usando el comando openssl. En este paso es muy importante que proporcione el DNS o el valor de la dirección IP de su nodo de servidor en Common Name, o fallará la creación del CSR.

openssl req -new -key server.key.pem -out server.csr

Configurar las extensiones de openssl x509 para el certificado del servidor

Debemos crear un archivo en /srv/tls/ llamado server_cert_ext.cnf. con los siguientes parámetros (mas info):

Nota: En caso de que se utilice un conjunto de subdominios en el entorno, es necesario descomentar las secciones subjectAltName y la extensión alt_names. Debajo de esta última extension es donde debe especificar cada uno de los subdominios que deben quedar contemplados en el certificado (a modo de ejemplo, se encuentra comentado el DNS.1 = universidad.edu.ar, DNS.2 = sudocu.universidad.edu.ar, DNS.3 = usuarios.universidad.edu.ar). Tenga en cuenta que también es posible utilizar un subdominio wildcard (ejemplo: DNS.4 = *.universidad.edu.ar) que matcheará para todos los subdominios que no cuenten con un prefijo especificado.

cat <<EOF > server_cert_ext.cnf
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "Ambiente EEI dev"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
#subjectAltName = @alt_names

#[ alt_names ]
#DNS.1 = universidad.edu.ar
#DNS.2 = sudocu.universidad.edu.ar
#DNS.3 = usuarios.universidad.edu.ar
#DNS.4 = *.universidad.edu.ar
EOF

Crear certificado de servidor

Utilizará el certificado de CA (certificate bundle) y la clave de CA del apartado anterior para emitir y firmar el certificado. Este comando creará un certificado de servidor server.cert.pem

openssl x509 -req -in server.csr -passin file:mypass.enc -CA intermediate/certs/ca-chain-bundle.cert.pem -CAkey intermediate/private/intermediate.cakey.pem -out server.cert.pem -CAcreateserial -days 365 -sha256 -extfile server_cert_ext.cnf

Una vez que tenga el server.cert.pem puede verificar que tenga el contenido correcto utilizando el siguiente comando:

openssl x509 -noout -text -in server.cert.pem

Finalmente, debe agregar una nueva cadena de certificados en donde incluirá el certificado del servidor, junto con el certificado de la CA Intermedia y la CA Root. Esta nueva cadena de certificados será la que terminará mostrandose al dirigirse a su dominio mediante un navegador.

cat server.cert.pem intermediate/certs/ca-chain-bundle.cert.pem > server-fullchain.pem

Actualizacion de certificados en traefik

Una vez que posea el server.key.pem y server-fullchain.pem debe agregarlos al proxy reverso traefik con los siguientes comandos de docker:

docker secret create traefik_tls_key /srv/tls/server.key.pem
docker config create traefik_tls_cert /srv/tls/server-fullchain.pem

Para finalizar y aplicar lo nuevo, debe redeployear el servicio traefik.yml:

docker stack deploy -c traefik.yml traefik

Mapeo de certificado en contenedores (opcional)

Para mapear los contenedores de los servicios de docker, es necesario extraer ca-certificates.crt del contenedor de arai-usuarios/idm para así luego poder mapearlo en el resto:

  • Se provee el siguiente comando para extraer el ca-certificate. En este, se debe setear dos variables de entorno (RUTA_CACERT_PEM y RUTA_INTERMEDIATE_CACERT_PEM) con el path absoluto de donde se encuentren sus cacert.pem e intermediate.cacert.pem:
RUTA_CACERT_PEM=/srv/tls/certs
RUTA_INTERMEDIATE_CACERT_PEM=/srv/tls/intermediate/certs

Luego debe ejecutar el comando:

docker run --rm --name cert-build \
-v $RUTA_CACERT_PEM/cacert.pem:/usr/local/share/ca-certificates/cacert.pem \
-v $RUTA_INTERMEDIATE_CACERT_PEM/intermediate.cacert.pem:/usr/local/share/ca-certificates/intermediate.cacert.pem \
-v $RUTA_CACERT_PEM:/tmp \
hub.siu.edu.ar:5005/siu/expedientes/arai-usuarios/idm:v3.1.9 \
-- "update-ca-certificates && cp /etc/ssl/certs/ca-certificates.crt /tmp"

Este le traerá el archivo ca-certificates.crt a la carpeta certs/ dentro de tls/

Una vez que posea dicho archivo, este ya puede ser mapeado en los servicios necesarios (ej: sudocu_api-server , huarpe_webapp, etc):

Para esto, primeramente se genera un config de docker:

docker config create ca-certificates ca-certificates.crt

Luego el mismo debe ser agregado en el yml del servicio que requiera dicho certificado (solo debe cambiar el yml del siguiente comando por el cual necesite):

sed -i -e 's/^\    configs:/\    configs:\n\      -\ source:\ ca-certificates\n\        target:\ \/etc\/ssl\/certs\/ca-certificates.crt/' huarpe.yml

y config global

sed -i -e 's/^configs:/configs:\n\  ca-certificates:\n\    external:\ true/' huarpe.yml

Mapeo de certificados en servidor (opcional)

Si requiere incluir los certificados previamente creado (cacert.pem y intermediate.cacert.pem) en un servidor para realizar pruebas, debe hacerlo de la siguiente manera:

En Debian

Nota: debian solo soporta certificados en form X509, es decir con extension .crt

mv cacert.pem /usr/local/share/ca-certificates/cacert.crt
mv intermediate.cacert.pem /usr/local/share/ca-certificates/intermediate.cacert.crt
update-ca-certificates

En alpine

apk add ca-certificates
mv cacert.pem /usr/local/share/ca-certificates/
mv intermediate.cacert.pem /usr/local/share/ca-certificates/
update-ca-certificates

Luego de realizados estos pasos, continue con el procedimiento de despliegue.