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
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ónalt_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 suscacert.pem
eintermediate.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.