One place for hosting & domains

      Cómo instalar y configurar una entidad de certificación (CA) en Ubuntu 20.04


      Introducción

      Las entidades de certificación (CA) son responsables de emitir certificados digitales para verificar identidades en Internet. Las CA públicas son una opción popular para verificar la identidad de sitios web y otros servicios que se proporcionan al público en general, y las CA privadas suelen usarse para grupos cerrados y servicios privados.

      Compilar una entidad de certificación privada le permitirá configurar, probar y ejecutar programas que requieren conexiones cifradas entre un cliente y un servidor. Con una CA privada, puede emitir certificados para usuarios, servidores o programas y servicios individuales dentro de su infraestructura.

      Algunos ejemplos de programas de Linux que utilizan su propia CA privada son OpenVPN y Puppet. También puede configurar su servidor web para que use certificados emitidos por una CA privada a fin de que los entornos de desarrollo y ensayo se adapten a los servidores de producción que utilizan TLS para cifrar conexiones.

      En esta guía, aprenderá a instalar una entidad de certificación privada en un servidor de Ubuntu 20.04 y a generar y firmar un certificado de prueba con su CA nueva. También aprenderá a importar el certificado público del servidor de CA al almacén de certificados de su sistema operativo para poder verificar la cadena de confianza entre los usuarios o servidores remotos y la CA. Por último, aprenderá a revocar certificados y a distribuir una lista de revocación de certificados para asegurarse de que solo usuarios y sistemas autorizados puedan usar los servicios que se basan en su CA.

      Requisitos previos

      Para completar este tutorial, necesitará acceso a un servidor Ubuntu 20.04 a fin de alojar su servidor de CA. Antes de comenzar a seguir los pasos de esta guía, deberá configurar un non-root user con privilegios sudo. Puede seguir nuestra guía de configuración inicial de servidores para Ubuntu 20.04 para configurar un usuario con los permisos adecuados. A través del tutorial del enlace también se podrá configurar un firewall, que para esta guía se supone que está instalado.

      En este tutorial, emplearemos el término servidor de CA para hacer referencia a este servidor.

      Asegúrese de que el sistema del servidor de CA sea independiente. Se usará únicamente para importar, firmar y revocar solicitudes de certificados. No debe ejecutar ningún otro servicio y lo ideal es que se desconecte o desactive por completo cuando usted no esté trabajando activamente con su CA.

      Nota: La última sección de este tutorial es opcional si desea aprender a firmar y revocar certificados. Si decide completar esos pasos de prueba, necesitará un segundo servidor de Ubuntu 20.04 o, de forma alternativa, puede usar su propia computadora local de Linux con Debian o Ubuntu, o distribuciones derivadas de cualquiera de ellos.

      Paso 1: Instalar Easy-RSA

      La primera tarea de este tutorial es instalar el conjunto de secuencias de comandos easy-rsa en su servidor de CA. easy-rsa es una herramienta de gestión de entidades de certificación que utilizará para generar una clave privada y un certificado root público que, luego, usará para firmar las solicitudes de los clientes y servidores que se basarán en su CA.

      Inicie sesión en su servidor de CA con el non-root sudo user que creó en los pasos de configuración iniciales y ejecute lo siguiente:

      • sudo apt update
      • sudo apt install easy-rsa

      Se le solicitará descargar e instalar el paquete. Presione y para confirmar que desea instalarlo.

      En este punto, tiene todo lo que necesita para usar Easy-RSA. En el siguiente paso, creará una infraestructura de clave pública y, luego, empezará a crear su entidad de certificación.

      Paso 2: Preparar un directorio para la infraestructura de clave pública

      Ahora que instaló easy-rsa, es el momento de crear una infraestructura de clave pública (PKI) de esqueleto en el servidor de CA. Verifique que siga conectado con su non-root user y cree un directorio easy-rsa. Asegúrese de no utilizar sudo para ejecutar ninguno de los siguientes comandos, dado que su usuario normal debe administrar la CA e interactuar con ella sin privilegios elevados.

      Con esto se creará un directorio nuevo llamado easy-rsa en su carpeta de inicio. Usaremos este directorio para crear enlaces simbólicos que apunten a los archivos del paquete easy-rsa que instalamos en el paso anterior. Estos archivos se encuentran en la carpeta /usr/share/easy-rsa en el servidor de CA.

      Cree los enlaces simbólicos con el comando ln:

      • ln -s /usr/share/easy-rsa/* ~/easy-rsa/

      Nota: Aunque en otras guías se le indique copiar los archivos del paquete easy-rsa a su directorio de la PKI, en este tutorial, usaremos enlaces simbólicos. Como resultado, toda actualización del paquete easy-rsa se reflejará automáticamente en las secuencias de comandos de su PKI.

      Para restringir el acceso a su nuevo directorio de la PKI, asegúrese de que solo el propietario pueda acceder a él usando el comando chmod:

      • chmod 700 /home/sammy/easy-rsa

      Por último, inicie la PKI dentro del directorio easy-rsa:

      • cd ~/easy-rsa
      • ./easyrsa init-pki

      Output

      init-pki complete; you may now create a CA or requests. Your newly created PKI dir is: /home/sammy/easy-rsa/pki

      Después de completar esta sección, tendrá un directorio con todos los archivos necesarios para crear una entidad de certificación. En la siguiente sección, creará la clave privada y el certificado público para su CA.

      Paso 3: Crear una entidad de certificación

      Para poder crear la clave privada y el certificado de su CA, debe crear y completar un archivo llamado vars con algunos valores predeterminados. Primero, usará cd para ingresar al directorio easy-rsa y, luego, creará y editará el archivo vars con nano o el editor de texto que prefiera:

      Una vez que se abra el archivo, pegue las siguientes líneas y sustituya cada valor resaltado por la información de su propia organización. Lo importante aquí es asegurarse de no dejar ninguno de los valores en blanco:

      ~/easy-rsa/vars

      set_var EASYRSA_REQ_COUNTRY "US" set_var EASYRSA_REQ_PROVINCE "NewYork" set_var EASYRSA_REQ_CITY "New York City" set_var EASYRSA_REQ_ORG "DigitalOcean" set_var EASYRSA_REQ_EMAIL "admin@example.com" set_var EASYRSA_REQ_OU "Community" set_var EASYRSA_ALGO "ec" set_var EASYRSA_DIGEST "sha512"

      Cuando termine, guarde y cierre el archivo. Si utiliza nano, puede hacerlo pulsando CTRL+X, Y y ENTER para confirmar. Con esto, estará listo para crear su CA.

      Para crear el certificado root público y el par de claves privadas para su entidad de certificación, vuelva a ejecutar el comando ./easy-rsa, aunque esta vez con la opción build-ca:

      En el resultado, verá algunas líneas sobre la versión de OpenSSL y se le solicitará ingresar una frase de contraseña para su par de claves. Asegúrese de elegir una frase de contraseña segura y anótela en un lugar resguardado. Deberá ingresar la frase de contraseña siempre que deba interactuar con su CA, por ejemplo, para firmar o revocar un certificado.

      También se le solicitará confirmar el nombre común (CN) de su CA. El nombre común es el que se usa para hacer referencia a esta máquina en el contexto de la entidad de certificación. Puede ingresar cualquier secuencia de caracteres para el nombre común de la CA; sin embargo, para hacerlo más simple presione ENTER para aceptar el nombre predeterminado.

      Output

      . . . Enter New CA Key Passphrase: Re-Enter New CA Key Passphrase: . . . Common Name (eg: your user, host, or server name) [Easy-RSA CA]: CA creation complete and you may now import and sign cert requests. Your new CA certificate file for publishing is at: /home/sammy/easy-rsa/pki/ca.crt

      Nota: Si no desea que se le solicite una contraseña cada vez que interactúe con su CA, puede ejecutar el comando build-ca con la opción nopass, de la siguiente forma:

      • ./easyrsa build-ca nopass

      Ahora, tiene dos archivos importantes, ~/easy-rsa/pki/ca.crt y ~/easy-rsa/pki/private/ca.key, que conforman los componentes públicos y privados de una entidad de certificación.

      • ca.crt es el archivo del certificado público de la CA. Los usuarios, los servidores y los clientes utilizarán este certificado para verificar que sean parte de la misma red de confianza. Todos los usuarios y los servidores que usen su CA deberán tener una copia de este archivo. Todas las partes se basarán en el certificado público para asegurarse de que nadie suplante un sistema y realice un ataque con intermediario.

      • ca.key es la clave privada que usa la CA para firmar certificados para servidores y clientes. Si un atacante obtiene acceso a su CA y, a la vez, a su archivo ca.key, deberá destruir la CA. Esta es la razón por la cual su archivo ca.key deberá estar únicamente en su máquina de CA. A su vez, lo ideal sería que su máquina de CA estuviera desconectada cuando no firme solicitudes de certificados como medida de seguridad adicional.

      Con esto, estableció su CA y esta se encuentra lista para emplearse en la firma de solicitudes de certificados y revocar certificados.

      Paso 4: Distribuir el certificado público de su entidad de certificación

      Ahora, su CA está configurada y lista para funcionar como root de confianza para cualquier sistema que desee que la use. Puede agregar el certificado de la CA a sus servidores de OpenVPN, web y de correo, entre otros. Cualquier usuario o servidor que necesite verificar la identidad de otro usuario o servidor de su red debe contar con una copia del archivo ca.crt importada en el almacén de certificados de su sistema operativo.

      Para importar el certificado público de la CA a un segundo sistema de Linux, como otro servidor o una computadora local, primero debe obtener una copia del archivo ca.crt de su servidor de CA. Puede usar el comando cat para ver el resultado en una terminal y, luego, copiarlo y pegarlo en un archivo en la segunda computadora en la que se importe el certificado. También puede usar herramientas como scp y rsync para transferir el archivo entre sistemas. Sin embargo, usaremos el método de copiar y pegar con nano en este paso, ya que funciona en todos los sistemas.

      Como non-root user en el servidor de CA, ejecute el siguiente comando:

      • cat ~/easy-rsa/pki/ca.crt

      El resultado en su terminal será similar al siguiente:

      Output

      -----BEGIN CERTIFICATE----- MIIDSzCCAjOgAwIBAgIUcR9Crsv3FBEujrPZnZnU4nSb5TMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAwwLRWFzeS1SU0EgQ0EwHhcNMjAwMzE4MDMxNjI2WhcNMzAw . . . . . . -----END CERTIFICATE-----

      Copie todo, incluso las líneas -----BEGIN CERTIFICATE----- y -----END CERTIFICATE----- y los guiones.

      En su segundo sistema de Linux, use nano o el editor de texto que prefiera para abrir un archivo llamado /tmp/ca.crt:

      Pegue lo que acaba de copiar del servidor de CA en el editor. Cuando termine, guarde y cierre el archivo. Si utiliza nano, puede hacerlo pulsando CTRL+X y, luego, Y y ENTER para confirmar.

      Ahora que tiene una copia del archivo ca.crt en su segundo sistema de Linux, es momento de importar el certificado al almacén de certificados de su sistema operativo.

      En los sistemas basados en Ubuntu y Debian, ejecute los siguientes comandos como non-root user para importar el certificado:

      Ubuntu and Debian derived distributions

      • sudo cp /tmp/ca.crt /usr/local/share/ca-certificates/
      • sudo update-ca-certificates

      Para importar el certificado del servidor de CA en un sistema basado en CentOS, Fedora o RedHat, copie el contenido del archivo y péguelo en el sistema, como en el ejemplo anterior, en un archivo denominado /tmp/ca.crt. A continuación, copie el certificado en /etc/pki/ca-trust/source/anchors/ y luego ejecute el comando update-ca-trust.

      CentOS, Fedora, RedHat distributions

      • sudo cp /tmp/ca.crt /etc/pki/ca-trust/source/anchors/
      • sudo update-ca-trust

      Ahora, su segundo sistema de Linux confiará en cualquier certificado firmado por el servidor de CA.

      Nota: Si utiliza su CA con servidores web y usa Firefox como navegador, deberá importar el certificado público ca.crt directamente a Firefox. Firefox no usa el almacén de certificados del sistema operativo local. Para obtener información sobre cómo agregar el certificado de su CA a Firefox, consulte el artículo de asistencia de Mozilla sobre configuración de entidades de certificación (CA) en Firefox.

      Si usa su CA para la integración con un entorno de Windows o computadoras de escritorio, consulte la documentación sobre cómo usar certutil.exe para instalar un certificado de CA.

      Si completa este tutorial como requisito previo para otro o está familiarizado con la forma de firmar y revocar certificados, puede detenerse aquí. Si desea obtener más información sobre cómo firmar y revocar certificados, en la siguiente sección opcional, se explicará cada proceso en detalle.

      (Opcional): Crear solicitudes de firma de certificados y revocar certificados

      Las siguientes secciones del tutorial son opcionales. Si completó todos los pasos anteriores, dispondrá de una entidad de certificación completamente configurada y funcional que podrá utilizar como requisito previo para otros tutoriales. Puede importar el archivo ca.crt de su CA y verificar los certificados de su red firmados por su CA.

      Si desea practicar y obtener más información sobre cómo firmar solicitudes de certificados y cómo revocarlos, en estas secciones opcionales se explicará cómo funcionan estos dos procesos.

      (Opcional): Crear y firmar una solicitud de certificado de prueba

      Ahora que tiene una CA lista para usar, puede practicar generar una clave privada y una solicitud de certificado para familiarizarse con el proceso de firma y distribución.

      Las solicitudes de firma de certificados (CSR) constan de tres partes: una clave pública, información de identificación sobre el sistema solicitante y una firma de la solicitud misma, que se crea utilizando la clave privada de la parte solicitante. La clave privada se mantendrá en secreto y se usará para cifrar información que luego podrá descifrar quien tenga el certificado público firmado.

      Los siguientes pasos se ejecutarán en su segundo sistema de Debian o Ubuntu, o en una distribución derivada de cualquiera de ellos. Puede ser otro servidor remoto o una máquina local de Linux, como una computadora portátil o de escritorio. Debido a que easy-rsa no está disponible por defecto en todos los sistemas, usaremos la herramienta openssl para crear una clave privada y un certificado de prueba.

      openssl suele instalarse por defecto en la mayoría de las distribuciones de Linux. Sin embargo, para estar seguro, ejecute lo siguiente en su sistema:

      • sudo apt update
      • sudo apt install openssl

      Cuando se le solicite instalar openssl ingrese y para proceder con los pasos de la instalación. Ahora, está listo para crear una CSR de prueba con openssl.

      El primer paso para crear una CSR es generar una clave privada. Para crear una clave privada usando openssl, cree un directorio practice-csr y luego genere una clave dentro de este. En vez de crear un certificado para identificar usuarios u otras CA, crearemos esta solicitud para un servidor ficticio llamado sammy-server.

      • mkdir ~/practice-csr
      • cd ~/practice-csr
      • openssl genrsa -out sammy-server.key

      Output

      Generating RSA private key, 2048 bit long modulus (2 primes) . . . . . . e is 65537 (0x010001)

      Ahora que tiene una clave privada, puede crear una CSR correspondiente y volver a usar la utilidad openssl. Se le solicitará completar varios campos, como Country, State y City. Puede ingresar . si desea dejar un campo en blanco, pero tenga en cuenta que, si se tratara de una CSR real, sería mejor usar los valores correctos de su ubicación y su organización:

      • openssl req -new -key sammy-server.key -out sammy-server.req

      Output

      . . . ----- Country Name (2 letter code) [XX]:US State or Province Name (full name) []:New York Locality Name (eg, city) [Default City]:New York City Organization Name (eg, company) [Default Company Ltd]:DigitalOcean Organizational Unit Name (eg, section) []:Community Common Name (eg, your name or your server's hostname) []:sammy-server Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:

      Si desea agregar esos valores automáticamente como parte de la invocación de openssl en lugar de hacerlo por medio de la solicitud interactiva, puede pasar el argumento -subj a OpenSSL. Asegúrese de editar los valores resaltados para que coincidan con la ubicación, la organización y el nombre del servidor de prueba:

      • openssl req -new -key sammy-server.key -out server.req -subj
      • /C=US/ST=New York/L=New York City/O=DigitalOcean/OU=Community/CN=sammy-server

      Para verificar el contenido de una CSR, puede leer el archivo de la solicitud con openssl y examinar los campos que contiene:

      • openssl req -in sammy-server.req -noout -subject

      Output

      subject=C = US, ST = New York, L = New York City, O = DigitalOcean, OU = Community, CN = sammy-server

      Una vez que esté conforme con el asunto de la solicitud de certificado de prueba, copie el archivo sammy-server.req a su servidor de CA utilizando scp:

      • scp sammy-server.req sammy@your_ca_server_ip:/tmp/sammy-server.req

      En este paso, generó una solicitud de firma de certificado para un servidor ficticio llamado sammy-server. En una situación real, la solicitud podría provenir, por ejemplo, de un servidor web de un entorno de ensayo o desarrollo que requiera un certificado TLS para pruebas o de un servidor de OpenVPN que solicite un certificado para que los usuarios puedan conectarse a una VPN. En el siguiente paso, procederemos a firmar la solicitud de firma de certificado usando la clave privada del servidor de CA.

      (Opcional): Firmar una CSR

      En el paso anterior, creó una solicitud de certificado y una clave de prueba para un servidor ficticio. La copió al directorio /tmp de su servidor de CA, simulando el proceso que seguiría si clientes o servidores reales le enviaran solicitudes de firma de certificados.

      Continuando con la situación ficticia, ahora, el servidor de CA debe importar el certificado de prueba y firmarlo. Una vez que la CA valida una solicitud de certificado y la vuelve a enviar a un servidor, los clientes que confían en la entidad de certificación también podrán confiar en el nuevo certificado emitido.

      Debido a que operaremos dentro de la PKI de la CA, donde está disponible la utilidad easy-rsa, utilizaremos esta utilidad easy-rsa en los pasos de firma para facilitar la tarea, en vez de usar openssl directamente como hicimos en el ejemplo anterior.

      El primer paso para firmar la CSR ficticia es importar la solicitud de certificado usando la secuencia de comandos easy-rsa:

      • cd ~/easy-rsa
      • ./easyrsa import-req /tmp/sammy-server.req sammy-server

      Output

      . . . The request has been successfully imported with a short name of: sammy-server You may now use this name to perform signing operations on this request.

      Ahora, puede firmar la solicitud ejecutando la secuencia de comandos easyrsa con la opción sign-req, seguida del tipo de solicitud y el nombre común incluido en la CSR. El tipo de solicitud puede ser client, server o ca. Debido a que estamos practicando con un certificado para un servidor ficticio, asegúrese de utilizar el tipo de solicitud server:

      • ./easyrsa sign-req server sammy-server

      En el resultado, se le solicitará verificar que la solicitud provenga de una fuente de confianza. Escriba yes y luego presione ENTER para confirmarlo:

      Output

      You are about to sign the following certificate. Please check over the details shown below for accuracy. Note that this request has not been cryptographically verified. Please be sure it came from a trusted source or that you have verified the request checksum with the sender. Request subject, to be signed as a server certificate for 3650 days: subject= commonName = sammy-server Type the word 'yes' to continue, or any other input to abort. Confirm request details: yes . . . Certificate created at: /home/sammy/easy-rsa/pki/issued/sammy-server.crt

      Si cifró su clave de la CA, se le solicitará ingresar la contraseña en este punto.

      Al completar esos pasos, firmó la CSR de sammy-server.req usando la clave privada del servidor de CA en /home/sammy/easy-rsa/pki/private/ca.key. El archivo sammy-server.crt resultante contiene la clave de cifrado pública del servidor de prueba, así como una nueva firma del servidor de CA. El objetivo de la firma es indicar a quienes confían en la CA que también pueden confiar en el certificado de sammy-server.

      Si esta solicitud fuera para un servidor real, como un servidor web o VPN, el último paso en el servidor de CA sería distribuir los nuevos archivos sammy-server.crt y ca.crt del servidor de CA al servidor remoto que realizó la solicitud de firma de certificado:

      • scp pki/issued/sammy-server.crt sammy@your_server_ip:/tmp
      • scp pki/ca.crt sammy@your_server_ip:/tmp

      En este punto, podría utilizar el certificado emitido con, por ejemplo, un servidor web, una VPN, una herramienta de administración de configuración o un sistema de base de datos, o para la autenticación de clientes.

      (Opcional): Revocar un certificado

      De tanto en tanto, es posible que deba revocar un certificado para evitar que un usuario o un servidor lo use, por ejemplo, si roban la computadora portátil de alguien, si se compromete un servidor web o si un empleado o contratista deja de trabajar con su organización.

      Estos son los pasos del proceso general para revocar un certificado:

      1. Revoque el certificado con el comando ./easyrsa revoke client-name.
      2. Genere una nueva CRL con el comando ./easyrsa gen-crl.
      3. Transfiera el archivo crl.pem actualizado al servidor o los servidores que se basan en su CA y, en esos sistemas, cópielo al directorio o los directorios necesarios de los programas que hagan referencia a él.
      4. Reinicie todos los servicios que utilicen su CA y el archivo CRL.

      Puede utilizar este proceso para revocar cualquier certificado que haya emitido anteriormente en cualquier momento. Analizaremos cada paso en detalle en las siguientes secciones, comenzando por el comando revoke.

      Revocar un certificado

      Para revocar un certificado, diríjase al directorio easy-rsa en su servidor de CA:

      Luego, ejecute la secuencia de comandos easyrsa con la opción revoke seguida del nombre del cliente que desee revocar: Siguiendo el ejemplo práctico anterior, el nombre común del certificado es sammy-server:

      • ./easyrsa revoke sammy-server

      Con esto, se solicitará que confirme el rechazo ingresando yes:

      Output

      Please confirm you wish to revoke the certificate with the following subject: subject= commonName = sammy-server Type the word 'yes' to continue, or any other input to abort. Continue with revocation: yes . . . Revoking Certificate 8348B3F146A765581946040D5C4D590A . . .

      Observe el valor resaltado en la línea Revoking Certificate. Este valor es el número de serie único del certificado que se revocará. Necesitará este valor si desea examinar la lista de revocación en el último paso de esta sección para verificar que el certificado se encuentre en ella.

      Una vez que se confirme la acción, la CA revocará el certificado. Sin embargo, los sistemas remotos que se basan en la CA no tienen forma de verificar si se revocó un certificado. Los usuarios y los servidores podrán seguir utilizando el certificado hasta que la lista de revocación de certificados (CRL) se distribuya a todos los sistemas que se basan en la CA.

      En el siguiente paso, generará una CRL o actualizará un archivo crl.pem existente.

      Generar una lista de revocación de certificados

      Ahora que revocó un certificado, es importante actualizar la lista de certificados revocados en su servidor de CA. Una vez que tenga una lista de revocación actualizada, podrá indicar los usuarios y sistemas que tienen certificados válidos en su CA.

      Para generar una CRL, ejecute el comando easy-rsa con la opción gen-crl mientras se encuentre en el directorio ~/easy-rsa:

      Si usó una frase de contraseña cuando creó su archivo ca.key, se le solicitará ingresarla. El comando gen-crl generará un archivo llamado crl.pem, que contiene la lista actualizada de los certificados revocados de esa CA.

      A continuación, deberá transferir el archivo crl.pem actualizado a todos los servidores y clientes que se basan en esta CA cada vez que ejecute el comando gen-crl. De lo contrario, los clientes y sistemas podrán seguir accediendo a los servicios y sistemas que utilizan su CA, dado que esos servicios tienen que conocer el estado de revocación del certificado.

      Transferir una lista de revocación de certificados

      Ahora que generó una CRL en su servidor de CA, deberá transferirla a los sistemas remotos que se basan en su CA. Para transferir este archivo a sus servidores, puede usar el comando scp.

      Nota: En este tutorial, se explica la forma de generar y distribuir una CRL manualmente. Si bien hay métodos más sólidos y automatizados para distribuir y verificar las listas de revocación, como OCSP-Stapling, la configuración de esos métodos está fuera del alcance de este artículo.

      Asegúrese de estar conectado a su servidor de CA como non-root user y ejecute lo siguiente; sustituya your_server_ip por el IP de su servidor o su nombre de DNS:

      • scp ~/easy-rsa/pki/crl.pem sammy@your_server_ip:/tmp

      Ahora que el archivo se encuentra en el sistema remoto, el último paso es actualizar todos los servicios con la nueva copia de la lista de revocación.

      Actualizar servicios que admiten una CRL

      En este tutorial, no se enumeran los pasos necesarios para actualizar los servicios que utilizan el archivo crl.pem. En general, deberá copiar el archivo crl.pem a la ubicación que el servicio espera y, luego, reiniciarlo mediante systemctl.

      Una vez que actualice sus servicios con el nuevo archivo crl.pem, podrán rechazar las conexiones de clientes o servidores que usen un certificado revocado.

      Examinar y verificar los componentes de una CRL

      Si desea examinar un archivo CRL, por ejemplo, para confirmar una lista de certificados revocados, utilice el siguiente comando openssl desde el directorio easy-rsa de su servidor de CA:

      • cd ~/easy-rsa
      • openssl crl -in pki/crl.pem -noout -text

      También puede ejecutar este comando en cualquier servidor o sistema que tenga la herramienta openssl instalada con una copia del archivo crl.pem. Por ejemplo, si transfirió el archivo crl.pem a su segundo sistema y desea verificar que el certificado de sammy-server se haya revocado, puede usar un comando openssl, como el siguiente, sustituyendo el número de serie resaltado aquí por el que observó anteriormente cuando revocó el certificado:

      • openssl crl -in /tmp/crl.pem -noout -text |grep -A 1 8348B3F146A765581946040D5C4D590A

      Output

      Serial Number: 8348B3F146A765581946040D5C4D590A Revocation Date: Apr 1 20:48:02 2020 GMT

      Observe que se usa el comando grep para verificar el número de serie único que observó en el paso de revocación. Ahora, puede verificar el contenido de su lista de revocación de certificados en cualquier sistema que se base en ella para restringir el acceso a usuarios y servicios.

      Conclusión

      En este tutorial, creó una entidad de certificación privada usando el paquete Easy-RSA en un servidor independiente de Ubuntu 20.04. Aprendió sobre el funcionamiento del modelo de confianza entre partes que se basan en la CA. También creó y firmó una solicitud de firma de certificado (CSR) para un servidor de prueba y, luego, aprendió a revocar certificados. Por último, aprendió a generar y distribuir una lista de revocación de certificados (CRL) para cualquier sistema que se base en su CA con el fin de garantizar que los usuarios o servidores que no deban tener acceso a los servicios no puedan tenerlo.

      Ahora, puede emitir certificados para usuarios y usarlos con servicios como OpenVPN. También puede usar su CA para configurar servidores web de desarrollo o ensayo con certificados para proteger sus entornos de no producción. El uso de una CA con certificados TLS durante el desarrollo puede ayudarlo a asegurarse de que su código y sus entornos se adapten en la mayor medida posible a su entorno de producción.

      Si desea saber más sobre cómo usar OpenSSL, nuestro tutorial Conceptos básicos de OpenSSL: Trabajar con certificados SSL, claves privadas y CSR contiene mucha información adicional para ayudarlo a familiarizarse con los fundamentos de OpenSSL.



      Source link

      Cómo crear una aplicación Web usando Flask en Python 3


      El autor seleccionó la Free and Open Source Fund para recibir una donación como parte del programa Write for DOnations.

      Introducción

      Flask es un marco web de Python pequeño y ligero que proporciona herramientas y funciones útiles que hacen que crear aplicaciones web en Python sea más fácil. Ofrece a los desarrolladores flexibilidad y un marco más accesible para los nuevos desarrolladores ya que puede crear una aplicación web rápidamente usando únicamente un archivo Python. Flask también es extensible y no fuerza una estructura de directorio concreta ni requiere código estándar complicado antes de iniciarse.

      Como parte de este tutorial, usará el kit de herramientas Bootstrap para dar estilo a su aplicación, para que sea más atractiva visualmente. Bootstrap le ayudará a incorporar páginas web reactivas en su aplicación web para que también funcione bien en navegadores móviles sin tener que escribir su propio código HTML, CSS y JavaScript para conseguir estos objetivos. El kit de herramientas le permitirá centrarse en aprender cómo funciona Flask.

      Flask utiliza el motor de plantillas Jinja para crear dinámicamente páginas HTML usando conceptos Python familiares como variables, bucles, listas, etcétera. Usará estas plantillas como parte de este proyecto.

      En este tutorial, creará un pequeño blog web usando Flask y SQLite en Python 3. Los usuarios de la aplicación pueden ver todas las entradas del blog en su base de datos y hacer clic sobre el título de una entrada para ver su contenido, con la capacidad de añadir una nueva publicación a la base de datos y editar o eliminar una entrada existente.

      Requisitos previos

      Antes de comenzar con esta guía, necesitará lo siguiente:

      Paso 1: Instalar Flask

      En este paso, activará su entorno Python e instalará Flask usando el instalador de paquetes pip.

      Si aún no ha activado su entorno de programación, asegúrese de que está en el directorio de su proyecto (flask_blog) y utilice el siguiente comando para activar el entorno:

      Una vez activado su entorno de programación, su línea de comandos ahora tendrá un prefijo env que puede tener el siguiente aspecto:

      Este prefijo es una indicación de que el entorno env está activo actualmente, y puede tener otro nombre dependiendo de cómo lo llamó durante la creación.

      Nota: Puede utilizar Git, un sistema de control de versiones, para administrar y realizar un seguimiento de forma efectiva del proceso de desarrollo de su proyecto. Para aprender cómo usar Git, es posible que desee consultar nuestro artículo Introducción a la instalación de Git, uso y ramificaciones.

      Si está usando Git, es una buena idea ignorar el recién creado directorio env en su archivo .gitignore para evitar realizar un seguimiento de los archivos no relacionados con el proyecto.

      Ahora, instalará los paquetes Python y aislará el código de su proyecto de la instalación del sistema principal de Python. Hará esto usando pip y python.

      Para instalar Flask, ejecute el siguiente comando:

      Una vez que se complete la instalación, ejecute el siguiente comando para confirmar la instalación:

      • python -c "import flask; print(flask.__version__)"

      Utiliza la interfaz de la línea de comandos python con la opción -c para ejecutar el código Python. A continuación, importa el paquete flask con import flask; luego imprime la versión de Flask, que encontrará a través de la variable flask._version_.

      El resultado será un número de versión similar al siguiente:

      Output

      1.1.2

      Ha creado la carpeta del proyecto, un entorno virtual, e instalado Flask. Ahora está listo para configurar su aplicación básica.

      Paso 2: Crear una aplicación básica

      Ahora que tiene su entorno de programación configurado, comenzará a usar Flask. En este paso, creará una pequeña aplicación web dentro de un archivo Python, y la ejecutará para iniciar el servidor, que mostrará cierta información en el navegador.

      En su directorio flask_blog, abra un archivo llamado hello.py para su edición; para ello utilice nano o su editor de texto favorito:

      Este archivo hello.py servirá como ejemplo mínimo de cómo gestionar solicitudes HTTP. Dentro, importará el objeto Flask, y creará una función que devuelva una respuesta HTTP. Escriba el siguiente código dentro de hello.py:

      flask_blog/hello.py

      from flask import Flask
      
      app = Flask(__name__)
      
      
      @app.route('/')
      def hello():
          return 'Hello, World!'
      

      En el bloque de código anterior, primero importa el objeto Flask desde el paquete flask. A continuación lo usará para crear su instancia de aplicación Flask con el nombre app. Pasa la variable especial __name__ que alberga el nombre del módulo Pyhthon actual. Se utiliza para indicar a la instancia dónde está ubicada. Necesitará hacerlo porque Flask configura algunas rutas en segundo plano.

      Una vez que cree la instancia app, la utiliza para gestionar las solicitudes web entrantes y enviar respuestas al usuario. @app.route es un decorador que convierte una función Python regular en una función vista de Flask, que convierte el valor de devolución de la función en una respuesta HTTP que se mostrará mediante un cliente HTTP, como un navegador web. Pasa el valor '/' a @app.route() para indicar que esta función responderá a las solicitudes web para la URL /, que es la URL principal.

      La función de vista hello() devuelve la cadena 'Hello, World!'​​ como respuesta.

      Guarde y cierre el archivo.

      Para ejecutar su aplicación web, primero indicará a Flask dónde encontrar la aplicación (el archivo hello.py en su caso) con la variable de entorno FLASK_APP:

      A continuación, ejecútela en modo de desarrollo con la variable de entorno FLASK_ENV:

      • export FLASK_ENV=development

      Por último, ejecute la aplicación usando el comando flask run:

      Una vez que la aplicación se esté ejecutando, el resultado será algo similar a esto:

      Output

      * Serving Flask app "hello" (lazy loading) * Environment: development * Debug mode: on * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 813-894-335

      El resultado anterior tiene varias informaciones, como:

      • El nombre de la aplicación que está ejecutando.
      • El entorno en el cual se ejecuta la aplicación.
      • Debug mode: on significa que el depurador de Flask se está ejecutando. Esto es útil durante el desarrollo porque nos proporciona mensajes de error detallados cuando algo va mal, lo que hace que sea más fácil resolver los problemas.
      • La aplicación se ejecuta localmente sobre la URL http://127.0.0.1:5000/, 127.0.0.1 es la IP que representa el localhost de su equipo y :5000 es el número de puerto.

      Abra un navegador y escriba la URL http://127.0.0.1:5000; recibirá la cadena Hello, World! como respuesta. Esto confirma que su aplicación se está ejecutando correctamente.

      Advertencia Flask utiliza un servidor web sencillo para presentar nuestra aplicación en un entorno de desarrollo, lo que también significa que el depurador de Flask se ejecuta para hacer que sea más fácil ver los errores. Este servidor de desarrollo no debería usarse en una implementación de producción. Consulte la página Opciones de implementación en la documentación de Flask para obtener más información; también puede consultar este tutorial de Implementación Flask.

      Ahora puede dejar el servidor de desarrollo en ejecución en el terminal y abrir otra ventana del terminal. Vaya a la carpeta del proyecto donde está hello.py, active el entorno virtual, establezca las variables del entorno FLASK_ENV y FLASK_APP y continúe a los siguientes pasos. (Estos comandos se han enumerado antes en este paso).

      Nota: Cuando abra un nuevo terminal, es importante recordar activar el entorno virtual y configurar las variables de entorno FLASK_ENV y FLASK_APP.

      Mientras un servidor de desarrollo de la aplicación de Flask esté ejecutándose, no es posible ejecutar otra aplicación Flask con el mismo comando flask run. Esto es porque flask run utiliza el número de puerto 5000 por defecto, y una vez utilizado, no está disponible para ejecutar otra aplicación, de forma que recibiría un error similar al siguiente:

      Output

      OSError: [Errno 98] Address already in use

      Para resolver este problema, detenga el servidor que se está ejecutando actualmente mediante CTRL+C, luego ejecute flask run de nuevo, o si desea que ambos se ejecuten a la vez, puede pasar un número de puerto diferente al argumento -p; por ejemplo, para ejecutar otra aplicación en el puerto 5001 utilice el siguiente comando:

      Ahora tiene una aplicación web Flask pequeña. Ha ejecutado su aplicación y mostrado información en el navegador web. A continuación, utilizará los archivos HTML en su aplicación.

      Paso 3: Usar plantillas HTML

      Actualmente, su aplicación solo muestra un mensaje sencillo sin HTML. Las aplicaciones web utilizan principalmente HTML para mostrar información al visitante, de forma que ahora trabajará para incorporar archivos HTML en su aplicación, que puede ser mostrada en el navegador web.

      Flask proporciona una función de ayuda render_template() que permite el uso del motor de plantillas Jinja. Esto hará que gestionar HTML sea mucho más fácil escribiendo su código HTML en archivos .html, además de utilizar la lógica en su código HTML. Usará estos archivos HTML, (plantillas), para crear todas las páginas de su aplicación, de igual forma que la página principal donde mostrará las entradas actuales del blog, la página de la entrada del blog, la página donde el usuario puede añadir una nueva entrada, etcétera.

      En este paso, creará su aplicación Flask principal en un nuevo archivo.

      Primero, en su directorio flask_blog, utilice nano o su editor de texto favorito para crear y editar su archivo app.py. Éste albergará todo el código que usará para crear la aplicación de blog:

      En este nuevo archivo, importará el objeto Flask para crear una instancia de aplicación Flask, como hizo antes. También importará la función de ayuda render_template() que le permite representar archivos de plantilla HTML que existen en la carpeta templates que está a punto de crear. El archivo tendrá una función de vista única que será responsable de gestionar las solicitudes a la ruta principal /. Añada el siguiente contenido:

      flask_blog/app.py

      from flask import Flask, render_template
      
      app = Flask(__name__)
      
      @app.route('/')
      def index():
          return render_template('index.html')
      

      La función de vista index() devuelve el resultado de invocar render_template() con index.html como argumento; esto indica a render_template() que busque un archivo llamado index.html en la carpeta templates. La carpeta y el archivo no existen aún, y recibirá un error si ejecutase la aplicación en este momento. De todas formas la va a ejecutar, para que se familiarice con esta excepción que se encuentra comúnmente. Luego lo resolverá creando la carpeta y archivo necesarios.

      Guarde el archivo y ciérrelo.

      Detenga el servidor de desarrollo en su otro terminal que ejecuta la aplicación hello con CTRL+C.

      Antes de ejecutar la aplicación, asegúrese de especificar correctamente el valor para la variable de entorno FLASK_APP, ya que ahora no está usando la aplicación hello.

      • export FLASK_APP=app
      • flask run

      Al abrir la URL http://127.0.0.1:5000 en su navegador, se mostrará la página del depurador informándole de que no se ha encontrado la plantilla index.html. La línea de código principal en el código responsable de este error se resaltará. En este caso, es la línea return render_template('index.html').

      Si hace clic en esta línea, el depurador revelará más código de forma que tenga más contexto para ayudarle a resolver el problema.

      El Depurador de Flask

      Para solucionar este error, cree un directorio llamado templates dentro de su directorio flask_blog. Dentro de él, abra un archivo llamado index.html para su edición:

      • mkdir templates
      • nano templates/index.html

      A continuación, añada el siguiente código HTML dentro de index.html:

      flask_blog/templates/index.html

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>FlaskBlog</title>
      </head>
      <body>
         <h1>Welcome to FlaskBlog</h1>
      </body>
      </html>
      

      Guarde el archivo y utilice su navegador para navegar a http://127.0.0.1:500 de nuevo, o actualice la página. Esta vez, el navegador debería mostrar el texto Welcome to FlaskBlog en una etiqueta <h1>.

      Además de la carpeta templates, las aplicaciones web de Flask también tienen normalmente una carpeta estática para albergar archivos, como los archivos CSS, archivos JavaScript, e imágenes que utiliza la aplicación.

      Puede crear un archivo de hoja de estilo style.css para añadir CSS a su aplicación. Primero, cree un directorio llamado static dentro de su directorio flask_blog principal:

      Luego cree otro directorio llamado css dentro del directorio static para albergar los archivos .css. Esto normalmente se hace para organizar archivos estáticos en carpetas dedicadas y, en consecuencia, los archivos JavaScript dentro de un directorio llamado js, las imágenes se ponen en un directorio llamado images (o img), etcétera. El siguiente comando creará el directorio css dentro del directorio static:

      Luego abra un archivo style.css dentro del directorio css para su edición:

      • nano static/css/style.css

      Añada la siguiente regla CSS a su archivo style.css:

      flask_blog/static/css/style.css

      h1 {
          border: 2px #eee solid;
          color: brown;
          text-align: center;
          padding: 10px;
      }
      

      El código CSS añadirá un borde, cambiará el color a marrón, centrará el texto y añadirá un pequeño relleno a las etiquetas <h1>.

      Guarde y cierre el archivo.

      A continuación, abra el archivo de plantilla index.html para su edición:

      • nano templates/index.html

      Añadirá un enlace al archivo style.css dentro de la sección <head> del archivo de plantilla index.html:

      flask_blog/templates/index.html

      . . .
      <head>
          <meta charset="UTF-8">
          <link rel="stylesheet" href="https://www.digitalocean.com/{{ url_for("static', filename="css/style.css") }}">
          <title>FlaskBlog</title>
      </head>
      . . .
      

      Aquí utiliza la función de ayuda url_for() para generar la ubicación apropiada del archivo. El primer argumento especifica que está vinculando a un archivo estático, y el segundo argumento es la ruta del archivo dentro del directorio estático.

      Guarde y cierre el archivo.

      Tras actualizar la página de índice de su aplicación, observará que el texto Welcome to FlaskBlog es ahora marrón, está centrado y se encuadra dentro de un borde.

      Puede utilizar el lenguaje CSS para dar estilo a la aplicación y hacer que sea más atractiva usando su propio diseño. Sin embargo, si no es un diseñador web, o no está familiarizado con CSS, puede usar el kit de herramientas Bootstrap, que ofrece componentes fáciles de usar para dar estilo a su aplicación. En este proyecto, usaremos Bootstrap.

      Quizá haya imaginado que crear otra plantilla HTML significará repetir la mayoría del código HTML que ya escribió en la plantilla index.html. Puede evitar la repetición innecesaria de código con la ayuda de un archivo de plantilla base, desde el cual heredarán todos sus archivos HTML. Consulte Herencia de plantillas en Jinja para obtener más información.

      Para crear una plantilla base, primero cree un archivo llamado base.html dentro de su directorio templates:

      Escriba el siguiente código en su plantilla base.html:

      flask_blog/templates/base.html

      <!doctype html>
      <html lang="en">
        <head>
          <!-- Required meta tags -->
          <meta charset="utf-8">
          <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
      
          <!-- Bootstrap CSS -->
          <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
      
          <title>{% block title %} {% endblock %}</title>
        </head>
        <body>
          <nav class="navbar navbar-expand-md navbar-light bg-light">
              <a class="navbar-brand" href="https://www.digitalocean.com/{{ url_for('index')}}">FlaskBlog</a>
              <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
                  <span class="navbar-toggler-icon"></span>
              </button>
              <div class="collapse navbar-collapse" id="navbarNav">
                  <ul class="navbar-nav">
                  <li class="nav-item active">
                      <a class="nav-link" href="https://www.digitalocean.com/#">About</a>
                  </li>
                  </ul>
              </div>
          </nav>
          <div class="container">
              {% block content %} {% endblock %}
          </div>
      
          <!-- Optional JavaScript -->
          <!-- jQuery first, then Popper.js, then Bootstrap JS -->
          <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
          <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
          <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
        </body>
      </html>
      

      Guarde y cierre el archivo una vez que haya terminado de editarlo.

      La mayor parte del código en el bloque anterior es HTML estándar y el código necesario para Bootstrap. Las etiquetas <meta> proporcionan información para el navegador web, la etiqueta <link> enlaza los archivos CSS de Boostrap y las etiquetas <script> son enlaces a código JavaScript que permite algunas funciones adicionales de Boostrap; consulte la documentación de Boostrap para obtener más información.

      Sin embargo, las siguientes partes resaltadas son específicas para el motor de plantillas Jinja:

      • {% block title %} {% endblock %}: un bloque que sirve como marcador de posición para un título. Más adelante lo usará en otras plantillas para dar un título personalizado a cada página de su aplicación sin tener que reescribir toda la sección <head> cada vez.
      • {{ url_for('index')}: una invocación de función que devolverá la URL para la función de vista index(). Esto es diferente a la invocación anterior url_for() que utilizó para vincular a un archivo CSS estático, porque solo requiere un argumento, que es el nombre de la función de vista, y enlaza a la ruta asociada con la función en vez de con un archivo estático.
      • {% block content %} {% endblock %}: otro bloque que se sustituirá por contenido dependiendo de la plantilla secundaria (plantillas que heredan de base.html) que lo anulará.

      Ahora que tiene una plantilla base, puede aprovecharla usando la herencia. Abra el archivo index.html:

      • nano templates/index.html

      Sustituya su contenido con lo siguiente:

      flask_blog/templates/index.html

      {% extends 'base.html' %}
      
      {% block content %}
          <h1>{% block title %} Welcome to FlaskBlog {% endblock %}</h1>
      {% endblock %}
      

      En esta nueva versión de la plantilla index.html, utiliza la etiqueta {% extends %} para que herede de la plantilla base.html. Luego la extiende sustituyendo el bloque content en la plantilla base con lo que está dentro del bloque content en el bloque de código anterior.

      Este bloque content contiene una etiqueta <h1> con el texto Welcome to FlaskBlog dentro de un bloque title, que a su vez sustituye el bloque title original en la plantilla base.html con el texto Welcome to FlaskBlog. De esta forma, puede evitar repetir el mismo texto dos veces, ya que funciona como título para la página y como encabezado que aparece bajo la barra de navegación heredada de la plantilla base.

      La herencia de plantillas también le ofrece la capacidad de reutilizar el código HTML que tiene en otras plantillas (base.html en este caso), sin tener que repetirlo cada vez que sea necesario.

      Guarde y cierre el archivo y actualice la página de índice en su navegador. Verá su página con una barra de navegación y un título con estilo.

      Página de índice con Bootstrap

      Utilizó plantillas HTML y archivos estáticos en Flask. También ha utilizado Bootstrap para comenzar a refinar el aspecto de su página y una plantilla base para evitar la repetición del código. En el siguiente paso, configurará una base de datos que almacenará los datos de su aplicación.

      Paso 4: Configurar la base de datos

      En este paso, configurará una base de datos para almacenar los datos, es decir, las entradas del blog para su aplicación. También completará la base de datos con algunas entradas de ejemplo.

      Usará un archivo de base de datos SQLite para guardar sus datos porque el módulo sqlite3, que utilizaremos para interactuar con la base de datos, está disponible en la biblioteca Python. Para obtener más información sobre SQLite, consulte este tutorial.

      Primero, ya que los datos de SQLite se guardan en tablas y columnas, y ya que sus datos principalmente son entradas de blog, primero deberá crear una tabla llamada posts con las columnas necesarias. Creará un archivo .sql que contiene comandos SQL para crear la tabla posts con algunas columnas. A continuación usará este archivo para crear la base de datos.

      Abra un archivo llamado schema.sql dentro de su directorio flask_blog:

      Escriba los siguientes comandos SQL dentro de este archivo:

      flask_blog/schema.sql

      DROP TABLE IF EXISTS posts;
      
      CREATE TABLE posts (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
          title TEXT NOT NULL,
          content TEXT NOT NULL
      );
      

      Guarde y cierre el archivo.

      El primer comando SQL es DROP TABLE IF EXISTS posts;, esto elimina cualquier tabla que exista llamada posts para que no tenga un comportamiento confuso. Observe que esto eliminará todo el contenido que tenga en la base de datos siempre que utilice estos comandos SQL, de forma que asegúrese de no escribir ningún contenido importante en la aplicación web hasta que haya terminado con este tutorial y experimente con el resultado final. A continuación, CREATE TABLE posts se utiliza para crear la tabla posts con las siguientes columnas:

      • id: es un entero que representa una clave primaria. La base de datos asignará un valor único para cada entrada (es decir, una entrada blog).
      • created: la hora en que se creó la entrada de blog. NOT NULL significa que esta columna no debería estar vacía y el valor DEFAULT es el valor CURRENT_TIMESTAMP, que es la hora en la cual la entrada se añadió a la base de datos. Igual que el id, no necesita especificar un valor para esta columna, y que se completará automáticamente.
      • title: el título de la entrada.
      • content: el contenido de la entrada.

      Ahora que tiene un esquema SQL en el archivo schema.sql, lo usará para crear la base de datos usando un archivo Python que generará un archivo base de datos .db de SQLite. Abra un archivo llamado init_db.py dentro del directorio flask_blog usando su editor preferido:

      Y luego añada el siguiente código.

      flask_blog/init_db.py

      import sqlite3
      
      connection = sqlite3.connect('database.db')
      
      
      with open('schema.sql') as f:
          connection.executescript(f.read())
      
      cur = connection.cursor()
      
      cur.execute("INSERT INTO posts (title, content) VALUES (?, ?)",
                  ('First Post', 'Content for the first post')
                  )
      
      cur.execute("INSERT INTO posts (title, content) VALUES (?, ?)",
                  ('Second Post', 'Content for the second post')
                  )
      
      connection.commit()
      connection.close()
      

      Primero importe el módulo sqlite3 y luego abra una conexión con el archivo de la base de datos llamada database.db, que se creará una vez que ejecute el archivo Python. Luego utilice la función open() para abrir el archivo schema.sql. A continuación, ejecute su contenido utilizando el método executescript() que ejecuta múltiples instrucciones SQL a la vez, lo que creará la tabla posts. Crea un objeto Cursor que le permite usar su método execute() para ejecutar dos instrucciones SQL INSERT para permitir dos entradas de blog en su tabla posts. Finalmente, confirma los cambios y cierra la conexión.

      Guarde y cierre el archivo y a continuación ejecútelo en el terminal usando el comando python:

      Una vez que el archivo termine su ejecución, aparecerá un nuevo archivo llamado database.db en su directorio flask_blog. Esto significa que la configurado correctamente su base de datos.

      En el siguiente paso, recuperará las entradas que insertó en su base de datos y las mostrará en la página de inicio de su aplicación.

      Paso 5: Mostrar todas las entradas

      Ahora que ha configurado su base de datos, puede modificar la función de vista index() para mostrar todas las entradas que tiene en su base de datos.

      Abra el archivo app.py para realizar las siguientes modificaciones:

      Para su primera modificación, importará el módulo sqlite3 en la parte superior del archivo:

      flask_blog/app.py

      import sqlite3
      from flask import Flask, render_template
      
      . . .
      

      A continuación, creará una función que cree una conexión de base de datos y la devolverá. Añádala directamente tras las importaciones:

      flask_blog/app.py

      . . .
      from flask import Flask, render_template
      
      def get_db_connection():
          conn = sqlite3.connect('database.db')
          conn.row_factory = sqlite3.Row
          return conn
      
      . . .
      

      Esta función get_db_connection() abra una conexión con el archivo de base de datos database.db, y luego establece el atributo row_factory a sqlite3. Row para poder tener acceso basado en nombre a las columnas. Esto significa que la conexión con la base de datos devolverá filas que se comportan como diccionarios Python regulares. Por último, la función devuelve el objeto de conexión conn que usará para acceder a la base de datos.

      Tras definir la función get_db_connection, modifique la función index() para que tenga el siguiente aspecto:

      flask_blog/app.py

      . . .
      
      @app.route('/')
      def index():
          conn = get_db_connection()
          posts = conn.execute('SELECT * FROM posts').fetchall()
          conn.close()
          return render_template('index.html"https://www.digitalocean.com/, posts=posts)
      

      En esta nueva versión de la función index(), primero abre una conexión de base de datos usando la función get_db_connection() que definió antes. A continuación, ejecuta una consulta SQL para seleccionar todas las entradas de la tabla post. Implementa el método fetchall() para recuperar todas las filas del resultado de la consulta. Esto devolverá una lista de las entradas que insertó en la base de datos en el paso anterior.

      Cierra la conexión con la base de datos usando el método close() y devuelve el resultado de representar la plantilla index.html. También pasará el objeto posts como argumento, que contiene los resultados que obtuvo de la base de datos; esto le permitirá acceder a las entradas del blog en la plantilla index.html.

      Con estas modificaciones implementadas, guarde y cierre el archivo app.py.

      Ahora que ha pasado las entradas que recuperó de la base de datos a la plantilla index.html, puede usar un bucle for para mostrar cada entrada en su página de índice.

      Abra el archivo index.html:

      • nano templates/index.html

      A continuación, modifíquelo como sigue:

      flask_blog/templates/index.html

      {% extends 'base.html' %}
      
      {% block content %}
          <h1>{% block title %} Welcome to FlaskBlog {% endblock %}</h1>
          {% for post in posts %}
              <a href="https://www.digitalocean.com/#">
                  <h2>{{ post['title'] }}</h2>
              </a>
              <span class="badge badge-primary">{{ post['created'] }}</span>
              <hr>
          {% endfor %}
      {% endblock %}
      

      Aquí, la sintaxis {% for post in posts %} es un bucle for Jinja, que es similar a un bucle for Python, excepto que tiene que ser cerrado posteriormente con la sintaxis {% endfor %}. Utiliza esta sintaxis para realizar un bucle sobre cada elemento en la lista posts que se pasó por la función index() en la línea return render_template('index.html', posts=posts). Dentro de este bucle for, muestra el título de la entrada en un encabezado <h2> dentro de una etiqueta <a> (más tarde utilizará esta etiqueta para vincular con cada entrada individualmente).

      Muestra el título utilizando un delimitador variable literal ({{ ... }}). Recuerde que post será un objeto similar a un diccionario, para que pueda acceder al título de la entrada con post['title']​​​. También muestra la fecha de creación de la entrada usando el mismo método.

      Una vez que haya terminado de editar el archivo, guarde y ciérrelo. Luego navegue a la página de índice en su navegador. Verá las dos entradas que añadió a la base de datos en su página.

      Página de índice con entradas mostradas

      Ahora que ha modificado la función de vista index() para mostrar todas las entradas que tiene en la base de datos en la página de inicio de su aplicación, pasará a mostrar cada entrada en una única página y permitirá que los usuarios vinculen a cada entrada individual.

      Paso 6: Mostrar una entrada única

      En este paso, creará una nueva ruta Flask con una función de vista y una nueva plantilla HTML para mostrar una entrada de blog individual por su ID.

      Al final de este paso, la URL http://127.0.0.1:5000/1 será una página que muestra la primera entrada (porque tiene el ID 1). La URL http://127.0.0.1:5000/ID mostrará la entrada con el número ID asociado si existe.

      Abra app.py para su edición:

      Ya que necesitará obtener una entrada de blog por su ID de la base de datos en múltiples ubicación más adelante en este proyecto, creará una función independiente llamada get_post(). Puede invocarla pasándole un ID y recibiendo la entrada de blog asociada con el ID proporcionado, o hacer que Flask responsa con un mensaje 404 Not Found si la entrada de blog no existe.

      Para responder con una página 404, deberá importar la función abort() desde la biblioteca Wekzeug, que se instaló junto con Flask en la parte superior del archivo:

      flask_blog/app.py

      import sqlite3
      from flask import Flask, render_template
      from werkzeug.exceptions import abort
      
      . . .
      

      A continuación, añada la función get_post() justo tras la función get_db_connection() que creó en el paso anterior:

      flask_blog/app.py

      . . .
      
      def get_db_connection():
          conn = sqlite3.connect('database.db')
          conn.row_factory = sqlite3.Row
          return conn
      
      
      def get_post(post_id):
          conn = get_db_connection()
          post = conn.execute('SELECT * FROM posts WHERE id = ?',
                              (post_id,)).fetchone()
          conn.close()
          if post is None:
              abort(404)
          return post
      
      . . .
      

      Esta nueva función tiene el argumento post_id que determina qué entrada de blog recuperar.

      Dentro de la función, utiliza la función get_db_connection() para abrir una conexión de base de datos y ejecutar una consulta SQL para obtener la entada de blog asociada con el valor post_id dado. Añade el método fetchone() para obtener el resultado y almacenarlo en la variable post. Luego, cierre la conexión. Si la variable post tiene el valor None, lo que significa que no se ha encontrado ningún resultado en la base de datos, utiliza la función abort() que importó anteriormente para responder con un código de error 404 y la función terminará la ejecución. Si, sin embargo, se encuentra una entrada, devuelve el valor de la variable post.

      A continuación, añada la siguiente función de vista al final del archivo app.py:

      flask_blog/app.py

      . . .
      
      @app.route('/<int:post_id>')
      def post(post_id):
          post = get_post(post_id)
          return render_template('post.html', post=post)
      

      En esta nueva función de vista, añade una regla de variable <int:post_id> para especificar que la parte tras la barra (/) es un entero positivo (marcado con el conversor int) que necesita para acceder en su función de vista. Flask reconoce esto y pasa su valor al argumento de palabra clave post_id de su función de vista post(). A continuación, utiliza la función get_post() para obtener la entrada de blog asociada con el ID especificado y almacenar el resultado en la variable post, que pasa por una plantilla post.html que pronto creará.

      Guarde el archivo app.py y abra un nuevo archivo de plantilla post.html para su edición:

      Escriba el siguiente código en este nuevo archivo post.html. Esto será similar al archivo index.html, excepto que solo mostrará una única entrada además de mostrar el contenido de la entrada:

      flask_blog/templates/post.html

      {% extends 'base.html' %}
      
      {% block content %}
          <h2>{% block title %} {{ post['title'] }} {% endblock %}</h2>
          <span class="badge badge-primary">{{ post['created'] }}</span>
          <p>{{ post['content'] }}</p>
      {% endblock %}
      

      Añade el bloque title que definió en la plantilla base.html para hacer que el título de la página refleje el título de la entrada que se muestra en un encabezado <h2> al mismo tiempo.

      Guarde y cierre el archivo.

      Ahora puede navegar a la siguiente URL para ver las dos entradas que tiene en su base de datos, junto con una página que indica al usuario que no se encontró la entrada del blog solicitada (ya que no hay una entrada con el número de ID 3 hasta ahora):

      http://127.0.0.1:5000/1
      http://127.0.0.1:5000/2
      http://127.0.0.1:5000/3
      

      Volviendo a la página de índice, creará cada enlace al título de la entrada a su página respectiva. Hará esto usando la función url_for(). Primero, abra la plantilla index.html para su edición:

      • nano templates/index.html

      A continuación cambie el valor del atributo href de # a {{ url_for('post', post_id=post['id']) }} de forma que el bucle for tendrá el siguiente aspecto:

      flask_blog/templates/index.html

      {% for post in posts %}
          <a href="https://www.digitalocean.com/{{ url_for('post', post_id=post['id']) }}">
              <h2>{{ post['title'] }}</h2>
          </a>
          <span class="badge badge-primary">{{ post['created'] }}</span>
          <hr>
      {% endfor %}
      

      Aquí, pasa 'post' a la función url_for() como primer argumento. Este es el nombre de la función de vista post() y ya que acepta un argumento post_id, le da el valor post['id']. La función url_for() devolverá la URL adecuada para cada entrada según su ID.

      Guarde y cierre el archivo.

      Los enlaces en la página de índice ahora funcionarán como se espera. Con esto, ha terminado de crear la parte de la aplicación responsable de mostrar las entradas de blog en su base de datos. A continuación, añadirá la capacidad de crear, editar y eliminar entradas de blog en su aplicación.

      Paso 7: Modificar entradas

      Ahora que ha terminado de mostrar las entradas de blog que están presentes en la base de datos en la aplicación web, deberá permitir a los usuarios de su aplicación escribir nuevas entradas de blog y añadirlas a la base de datos, editar las existentes y eliminar las entradas de blog innecesarias.

      Crear una nueva entrada

      Hasta este momento, tiene una aplicación que muestra las entradas en su base de datos pero no ofrece ninguna forma de añadir una nueva entrada a menos que conecte directamente con la base de datos SQLite y añada una manualmente. En esta sección, creará una página sobre la cual podrá crear una entrada proporcionando su título y contenido.

      Abra el archivo app.py para su edición:

      Primero, importará lo siguiente desde el marco Flask:

      • El objeto global request para acceder a los datos de solicitud entrantes que se enviarán a través de un formato HTML.
      • La función url_for() para generar URLs.
      • La función flash() para mostrar un mensaje cuando se procesa una solicitud.
      • La función redirect() para redirigir al cliente a una ubicación diferente.

      Añada las importaciones a su archivo de la siguiente forma:

      flask_blog/app.py

      import sqlite3
      from flask import Flask, render_template, request, url_for, flash, redirect
      from werkzeug.exceptions import abort
      
      . . .
      

      La función flash() almacena los mensajes mostrados en la sesión del navegador del cliente, lo que requiere configurar una clave secreta. Esta clave secreta se utiliza para proteger las sesiones, lo que permite a Flask recordar la información de una solicitud a la otra, como pasar desde la nueva página de entrada a la página de índice. El usuario puede acceder a la información almacenada en la sesión, pero no puede modificarla a menos que tenga la clave secreta, de forma que nunca permita que nadie acceda a la clave secreta. Consulte la documentación de Flask para sesiones para obtener más información.

      Para establecer una_ clave_ secreta, añadirá una configuración SECRET_KEY a su aplicación a través del objeto app.config. Añádala directamente siguiendo la definición app antes de definir la función de vista index():

      flask_blog/app.py

      . . .
      app = Flask(__name__)
      app.config['SECRET_KEY'] = 'your secret key'
      
      
      @app.route('/')
      def index():
          conn = get_db_connection()
          posts = conn.execute('SELECT * FROM posts').fetchall()
          conn.close()
          return render_template('index.html', posts=posts)
      
      . . .
      

      Recuerde que la clave secreta debería ser una cadena aleatoria larga.

      Tras establecer una clave secreta, creará una función de vista que mostrará una plantilla que muestra un formulario que puede completar para crear una nueva entrada de blog. Añada esta nueva función en la parte inferior del archivo:

      flask_blog/app.py

      . . .
      
      @app.route('/create', methods=('GET', 'POST'))
      def create():
          return render_template('create.html')
      

      Esto crea una ruta /create que acepta las solicitudes GET y POST. Las solicitudes GET se aceptan por defecto. También acepta las solicitudes POST que se envía el navegador cuando se envían formularios. Pasará un tuple con los tipos de solicitudes aceptadas al argumento methods del decorador @app.route().

      Guarde y cierre el archivo.

      Para crear la plantilla, abra un archivo llamado create.html dentro de su carpeta templates:

      • nano templates/create.html

      Añada el siguiente código dentro de este nuevo archivo:

      flask_blog/templates/create.html

      {% extends 'base.html' %}
      
      {% block content %}
      <h1>{% block title %} Create a New Post {% endblock %}</h1>
      
      <form method="post">
          <div class="form-group">
              <label for="title">Title</label>
              <input type="text" name="title"
                     placeholder="Post title" class="form-control"
                     value="{{ request.form['title'] }}"></input>
          </div>
      
          <div class="form-group">
              <label for="content">Content</label>
              <textarea name="content" placeholder="Post content"
                        class="form-control">{{ request.form['content'] }}</textarea>
          </div>
          <div class="form-group">
              <button type="submit" class="btn btn-primary">Submit</button>
          </div>
      </form>
      {% endblock %}
      

      La mayor parte de este código es HTML estándar. Mostrará un cuadro de entrada para el título de la entrada, un área de texto para el contenido de la entrada y un botón para enviar el formulario.

      El valor de la entrada del título de la entrada es {{ request.form['title'] }},​​​ y el área de texto tiene el valor {{ request.form['content'] }}. Esto se hace para que los datos que introduce no se pierdan si algo sale mal. Por ejemplo, si escribe una entrada larga y olvida darle un título, se mostrará un mensaje que le informa de que el título es necesario. Esto sucederá sin perder la entrada que escribió ya que se almacenará en el objeto global request al que tiene acceso en sus plantillas.

      Ahora, con el servidor de desarrollo en ejecución, utilice su navegador para navegar a la ruta /create:

      http://127.0.0.1:5000/create
      

      Verá una página Create a New Post con un cuadro para un título y contenido:

      Crear una nueva página de entrada

      Este formulario envía una solicitud POST a su función de vista create(). Sin embargo, aún no hay ningún código para gestionar una solicitud POST en la función, de forma que no sucederá nada tras completar el formulario y enviarlo.

      Gestionará la solicitud POST entrante cuando se envía un formulario. Lo hará dentro de la función de vista create(). Puede gestionar por separado la solicitud POST comprobando el valor de request.method. Cuando su valor se establece a 'POST', significa que la solicitud es una solicitud POST. Luego extraerá los datos enviados, los validará y los insertará en su base de datos.

      Abra el archivo app.py para su edición:

      Modifique la función de vista create() para que tenga exactamente el siguiente aspecto:

      flask_blog/app.py

      . . .
      
      @app.route('/create', methods=('GET', 'POST'))
      def create():
          if request.method == 'POST':
              title = request.form['title']
              content = request.form['content']
      
              if not title:
                  flash('Title is required!')
              else:
                  conn = get_db_connection()
                  conn.execute('INSERT INTO posts (title, content) VALUES (?, ?)',
                               (title, content))
                  conn.commit()
                  conn.close()
                  return redirect(url_for('index'))
      
          return render_template('create.html')
      

      En la instrucción if asegura que el código que le sigue solo se ejecuta cuando la solicitud es una solicitud POST a través de la comparativa request.method == 'POST'.

      A continuación, extrae el título enviado y el contenido desde el objeto request.form que le proporciona acceso a los datos del formulario en la solicitud. Si no se proporciona el título, la condición if not title se cumplirá, mostrando un mensaje al usuario informándole de que el título es obligatorio. Si, por otro lado, se proporciona el título, abrirá una conexión con la función get_db_connection() e insertará el título y el contenido que recibió en la tabla posts.

      Luego confirma los cambios en la base de datos y cierra la conexión. Tras añadir la entrada de blog a la base de datos, redirige al cliente a la página de índice usando la función redirect() pasándole la URL generada por la función url_for() con el valor 'index' como argumento.

      Guarde y cierre el archivo.

      Ahora, navegue a la ruta /create usando su navegador web:

      http://127.0.0.1:5000/create
      

      Complete el formulario con un título y algo de contenido. Una vez que envíe el formulario, verá la nueva entrada listada en la página de índice.

      Por último, mostrará los mensajes generados y añadirá un enlace a la barra de navegación en la plantilla base.html para tener un acceso fácil a esta nueva página. Abra el archivo de plantilla:

      Edite el archivo añadiendo una nueva etiqueta <li> tras el enlace About dentro de la etiqueta <nav>. A continuación, añada un nuevo bucle for directamente sobre el bloque content para mostrar los mensajes generados bajo la barra de navegación. Estos mensajes están disponibles en la función especial get_flashed_messages() que Flask ofrece:

      flask_blog/templates/base.html

      <nav class="navbar navbar-expand-md navbar-light bg-light">
          <a class="navbar-brand" href="https://www.digitalocean.com/{{ url_for("index')}}">FlaskBlog</a>
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
              <span class="navbar-toggler-icon"></span>
          </button>
          <div class="collapse navbar-collapse" id="navbarNav">
              <ul class="navbar-nav">
              <li class="nav-item">
                  <a class="nav-link" href="https://www.digitalocean.com/#">About</a>
              </li>
              <li class="nav-item">
                  <a class="nav-link" href="https://www.digitalocean.com/{{url_for("create')}}">New Post</a>
              </li>
              </ul>
          </div>
      </nav>
      <div class="container">
          {% for message in get_flashed_messages() %}
              <div class="alert alert-danger">{{ message }}</div>
          {% endfor %}
          {% block content %} {% endblock %}
      </div>
      

      Guarde y cierre el archivo. La barra de navegación ahora tendrá un elemento New Post que enlaza a la ruta /create.

      Editar una entrada

      Para que un blog esté actualizado, deberá poder editar sus entradas existentes. Esta sección le guiará en la creación de una nueva página en su aplicación para simplificar el proceso de editar una entrada.

      Primero, añadirá una nueva ruta al archivo app.py. Su función de vista recibirá el ID de la entrada que debe ser editada, la URL estará en el formato /post_id/edit con la variable post_id siendo el ID de la entrada. Abra el archivo app.py para su edición:

      A continuación, añada la siguiente función de vista edit() al final del archivo. Editar una entrada existente es similar a crear una nueva, de forma que esta función de vista será similar a la función de vista create():

      flask_blog/app.py

      . . .
      
      @app.route('/<int:id>/edit', methods=('GET', 'POST'))
      def edit(id):
          post = get_post(id)
      
          if request.method == 'POST':
              title = request.form['title']
              content = request.form['content']
      
              if not title:
                  flash('Title is required!')
              else:
                  conn = get_db_connection()
                  conn.execute('UPDATE posts SET title = ?, content = ?'
                               ' WHERE id = ?',
                               (title, content, id))
                  conn.commit()
                  conn.close()
                  return redirect(url_for('index'))
      
          return render_template('edit.html', post=post)
      

      La entrada que edita viene determinada por la URL y Flask pasará el número de ID a la función edit() a través del argumento id. Añade este valor a la función get_post() para recuperar la entrada asociada con el ID proporcionado desde la base de datos. Los nuevos datos vendrán en una solicitud POST, que se gestiona dentro de la condición if request.method == 'POST'.

      Igual que cuando creó una nueva entrada, primero extrae los datos del objeto request.form, luego muestra un mensaje si el título tiene un valor vacío, de lo contrario, abre una conexión con la base de datos. Luego actualiza la tabla posts estableciendo un nuevo título y nuevo contenido donde el ID de la entrada en la base de datos es igual al ID que estaba en la URL.

      En el caso de una solicitud GET, representa una plantilla edit.html pasando la variable post que alberga el valor devuelto de la función get_post(). Usará esto para mostrar el título existente y el contenido en la página de edición.

      Guarde y cierre el archivo, y cree una nueva plantilla edit.html:

      Escriba el siguiente código dentro de este nuevo archivo:

      flask_blog/templates/edit.html

      {% extends 'base.html' %}
      
      {% block content %}
      <h1>{% block title %} Edit "{{ post['title'] }}" {% endblock %}</h1>
      
      <form method="post">
          <div class="form-group">
              <label for="title">Title</label>
              <input type="text" name="title" placeholder="Post title"
                     class="form-control"
                     value="{{ request.form['title'] or post['title'] }}">
              </input>
          </div>
      
          <div class="form-group">
              <label for="content">Content</label>
              <textarea name="content" placeholder="Post content"
                        class="form-control">{{ request.form['content'] or post['content'] }}</textarea>
          </div>
          <div class="form-group">
              <button type="submit" class="btn btn-primary">Submit</button>
          </div>
      </form>
      <hr>
      {% endblock %}
      

      Guarde y cierre el archivo.

      Este código sigue el mismo patrón excepto por la sintaxis {{ request.form['title'] or post['title'] }} y {{ request.form['content'] or post['content'] }}. Esto muestra los datos guardados en la solicitud si existe, de lo contrario, muestra los datos de la variable post que se pasó a la plantilla que contiene los datos actuales de la base de datos.

      Ahora, navegue a la siguiente URL para editar la primera entrada:

      http://127.0.0.1:5000/1/edit
      

      Verá una página Edit “First Post”.

      Editar la página de una entrada

      Edite la entrada y envíe el formulario, luego asegúrese de que la entrada se ha actualizado.

      Ahora necesita añadir un enlace que apunte a la página de edición para cada entrada en la página de índice. Abra el archivo de plantilla index.html:

      • nano templates/index.html

      Edite el archivo para que tenga exactamente el siguiente aspecto:

      flask_blog/templates/index.html

      {% extends 'base.html' %}
      
      {% block content %}
          <h1>{% block title %} Welcome to FlaskBlog {% endblock %}</h1>
          {% for post in posts %}
              <a href="https://www.digitalocean.com/{{ url_for("post', post_id=post['id']) }}">
                  <h2>{{ post['title'] }}</h2>
              </a>
              <span class="badge badge-primary">{{ post['created'] }}</span>
              <a href="https://www.digitalocean.com/{{ url_for("edit', id=post['id']) }}">
                  <span class="badge badge-warning">Edit</span>
              </a>
              <hr>
          {% endfor %}
      {% endblock %}
      

      Guarde y cierre el archivo.

      Aquí añade una etiqueta <a> para enlazar a la función de vista edit(), pasando el valor post['id'] al enlace para editar la página de cada entrada con el enlace Edit.

      Eliminar una entrada

      A veces, no es necesario que una entrada siga estando disponible públicamente, y por eso la funcionalidad de eliminar una entrada es crucial. En este paso, añadirá la funcionalidad de eliminación a su aplicación.

      Primero, añadirá una nueva ruta /ID/delete que acepta solicitudes POST, de forma similar a la función de vista edit(). Su nueva función de vista delete() recibirá el ID de la entrada que será eliminada de la URL. Abra el archivo app.py:

      Añada la siguiente función de vista en la parte inferior del archivo:

      flask_blog/app.py

      # ....
      
      @app.route('/<int:id>/delete', methods=('POST',))
      def delete(id):
          post = get_post(id)
          conn = get_db_connection()
          conn.execute('DELETE FROM posts WHERE id = ?', (id,))
          conn.commit()
          conn.close()
          flash('"{}" was successfully deleted!'.format(post['title']))
          return redirect(url_for('index'))
      

      Esta función de vista solo acepta solicitudes POST. Esto significa que navegar a la ruta /ID/delete en su navegador devolverá un error porque los navegadores web van de forma predeterminada a las solicitudes GET.

      Sin embargo, puede acceder a esta ruta mediante un formulario que envía una solicitud POST pasando el ID de la entrada que desea eliminar. La función recibirá el valor de ID y lo usará para obtener la entrada de la base de datos con la función get_post().

      A continuación, abrirá una conexión de base de datos y ejecutará un comando SQL DELETE FROM para eliminar la entrada. Confirma el cambio en la base de datos y cierra la conexión mientras muestra un mensaje para informar al usuario de que la entrada se eliminó correctamente y redirigirlo a la página de índice.

      Observe que no reproduce un archivo de plantilla. Esto es porque añadirá un botón Delete a la página de edición.

      Abra el archivo de plantilla edit.html:

      Luego, añada la siguiente etiqueta <form> tras la etiqueta <hr> y directamente antes de la línea {% endblock %}:

      flask_blog/templates/edit.html

      <hr>
      
      <form action="https://www.digitalocean.com/{{ url_for("delete', id=post['id']) }}" method="POST">
          <input type="submit" value="Delete Post"
                  class="btn btn-danger btn-sm"
                  onclick="return confirm('Are you sure you want to delete this post?')">
      </form>
      
      {% endblock %}
      

      Utiliza el método confirm() para mostrar un mensaje de confirmación antes de enviar la solicitud.

      Ahora, navegue de nuevo a la página de edición de una entrada de blog e intente eliminarla:

      http://127.0.0.1:5000/1/edit
      

      Al final de este paso, el código fuente de su proyecto tendrá el aspecto del código en esta página.

      Con esto, los usuarios de su aplicación pueden escribir nuevas entradas de blog y añadirlas a la base de datos, editar entradas y eliminar las entradas existentes.

      Conclusión

      Este tutorial ha introducido los conceptos esenciales del marco Flask Python. Ha aprendido a crear una pequeña aplicación web, ejecutarla en un servidor de desarrollo y a permitir al usuario proporcionar datos personalizados a través de parámetros URL y formularios web. También utilizó el motor de plantillas Jinja para reutilizar los archivos HTMP y usar lógica en ellos. Al final de este tutorial, tendrá un blog web completamente funcional que interactúa con una base de datos SQLite para crear, mostrar, editar y eliminar entradas de blog usando el lenguaje Python y las consultas SQL.

      Puede seguir desarrollando esta aplicación añadiendo autenticación del usuario de forma que solo los usuarios registrados puedan crear o modificar entradas de blog. También puede añadir comentarios y etiquetas para cada entrada de blog, y añadir subidas de archivos para dar a los usuarios la capacidad de incluir imágenes en la entrada del blog. Consulte la documentación de Flask para obtener más información.

      Flask cuenta con muchas extensiones Flask creadas por la comunidad. A continuación verá una lista de extensiones que quizá quiera considerar usar para que su proceso de desarrollo sea más fácil:

      • Flask-Login: gestiona la sesión del usuario y el inicio y cierre de sesión, además de recordar a los usuarios con sesión iniciada.
      • Flask-SQLAlchemy: simplifica el uso de Flask con SQLAlchemy, un kit de herramientas Python SQL y un Asignador relacional de objetos para interactuar con bases de datos SQL.
      • Flask-Mail: ayuda con la tarea de enviar mensajes de correo electrónico en su aplicación Flask.



      Source link

      Cómo instalar y configurar una entidad de certificación (CA) en CentOS 8


      Introducción

      Las entidades de certificación (CA) son responsables de emitir certificados digitales para verificar identidades en Internet. Las CA públicas son una opción popular para verificar la identidad de sitios web y otros servicios que se proporcionan al público en general, y las CA privadas suelen usarse para grupos cerrados y servicios privados.

      La compilación de una entidad de certificación privada le permitirá configurar, probar y ejecutar programas que requieren conexiones cifradas entre un cliente y un servidor. Con una CA privada, puede emitir certificados para usuarios, servidores o programas y servicios individuales dentro de su infraestructura.

      Algunos ejemplos de programas de Linux que utilizan su propia CA privada son OpenVPN y Puppet. También puede configurar su servidor web para que use certificados emitidos por una CA privada con el fin de que los entornos de desarrollo y ensayo se adapten a los servidores de producción que utilizan TLS para cifrar conexiones.

      A través de esta guía, aprenderá a instalar una entidad de certificación privada en un servidor de CentOS 8 y a generar y firmar un certificado de prueba con esa CA nueva. También aprenderá a importar el certificado público del servidor de CA al almacén de certificados de su sistema operativo para poder verificar la cadena de confianza entre los usuarios o servidores remotos y la CA. Por último, aprenderá a revocar certificados y a distribuir una lista de revocación de certificados para asegurarse de que solo usuarios y sistemas autorizados puedan usar servicios que se basen en su CA.

      Requisitos previos

      Para este tutorial, necesitará un servidor de CentOS 8 con un usuario no root habilitado para sudo y un firewall configurado con firewalld. Puede seguir nuestra guía Configuración inicial para servidores con CentOS 8 para completar esa configuración.

      En este tutorial, emplearemos el término servidor de CA para hacer referencia a este servidor.

      Asegúrese de que el sistema del servidor de CA sea independiente. Se usará únicamente para importar, firmar y revocar solicitudes de certificados. No debe ejecutar ningún otro servicio y lo ideal es que se desconecte o desactive por completo cuando usted no esté trabajando activamente con su CA.

      Nota: La última sección de este tutorial es opcional si desea aprender a firmar y revocar certificados. Si decide completar esos pasos de práctica, necesitará un segundo servidor de CentOS 8 o, alternativamente, puede usar su propia computadora de Linux local con CentOS 8, Fedora o un derivado de RedHat.

      Paso 1: Instalar Easy-RSA

      La primera tarea de este tutorial es instalar el conjunto de secuencias de comandos easy-rsa en su servidor de CA. easy-rsa es una herramienta de gestión de entidades de certificación que utilizará para generar una clave privada y un certificado root público, que luego usará para firmar solicitudes de clientes y servidores que se basarán en su CA.

      El paquete easy-rsa no está disponible por defecto en CentOS 8, por lo que tendrá que habilitar el repositorio Extra Packages for Enterprise Linux (EPEL). El Proyecto Fedora gestiona el EPEL, que contiene paquetes no estándares, pero populares para Fedora, CentOS y otras distribuciones de Linux que utilizan el formato de paquete RPM. Inicie sesión en su servidor de CA con el usuario sudo no root que creó en los pasos de configuración iniciales y ejecute lo siguiente:

      • sudo dnf install epel-release

      Se le solicitará descargar e instalar el paquete. Presione y para confirmar que desea instalarlo.

      Ahora, instale el paquete easy-rsa e ingrese y nuevamente cuando se le solicite:

      • sudo dnf install easy-rsa

      En este punto, tiene todo lo que necesita para usar Easy-RSA. En el siguiente paso, creará una infraestructura de clave pública y, luego, empezará a crear su entidad de certificación.

      Paso 2: Preparar un directorio para la infraestructura de clave pública

      Ahora que instaló easy-rsa, es el momento de crear una infraestructura de clave pública (PKI) de esqueleto en el servidor de CA. Verifique que siga conectado con su usuario no root y cree un directorio easy-rsa. Asegúrese de no utilizar sudo para ejecutar ninguno de los siguientes comandos, dado que su usuario normal debe administrar la CA e interactuar con ella sin privilegios elevados.

      Esto creará un directorio nuevo llamado easy-rsa en su carpeta de inicio. Usaremos este directorio para crear enlaces simbólicos que apunten a los archivos del paquete easy-rsa que instalamos en el paso anterior. Estos archivos se encuentran en la carpeta /usr/share/easy-rsa/3 en el servidor de CA.

      Cree los enlaces simbólicos con el comando ln:

      • ln -s /usr/share/easy-rsa/3/* ~/easy-rsa/

      Nota: Aunque en otras guías se le indique copiar los archivos del paquete easy-rsa a su directorio de la PKI, en este tutorial, usaremos enlaces simbólicos. Como resultado, toda actualización del paquete easy-rsa se reflejará automáticamente en las secuencias de comandos de su PKI.

      Para restringir el acceso a su nuevo directorio de la PKI, asegúrese de que solo el propietario pueda acceder a él usando el comando chmod:

      • chmod 700 /home/sammy/easy-rsa

      Por último, inicie la PKI dentro del directorio easy-rsa:

      • cd ~/easy-rsa
      • ./easyrsa init-pki

      Output

      init-pki complete; you may now create a CA or requests. Your newly created PKI dir is: /home/sammy/easy-rsa/pki

      Después de completar esta sección, tendrá un directorio con todos los archivos necesarios para crear una entidad de certificación. En la siguiente sección, creará la clave privada y el certificado público para su CA.

      Paso 3: Crear una entidad de certificación

      Para poder crear la clave privada y el certificado de su CA, debe crear y completar un archivo llamado vars con algunos valores predeterminados. Primero, usará cd para ingresar al directorio easy-rsa y, luego, creará y editará el archivo vars con nano o el editor de texto que prefiera.

      El editor de texto predeterminado que viene con CentOS 8 es vi. vi es extremadamente potente, pero puede ser un tanto obtuso para los usuarios que carecen de experiencia con él. Posiblemente desee instalar un editor más sencillo, como nano, para facilitar la edición de los archivos de configuración en su servidor de CentOS 8.

      Cuando se le solicite instalar nano ingrese y para proceder con los pasos de la instalación. Con eso, estará listo para editar el archivo vars:

      Una vez que se abra el archivo, pegue las siguientes líneas y sustituya cada valor resaltado por la información de su propia organización. Lo importante aquí es asegurarse de no dejar ninguno de los valores en blanco:

      ~/easy-rsa/vars

      set_var EASYRSA_REQ_COUNTRY "US" set_var EASYRSA_REQ_PROVINCE "NewYork" set_var EASYRSA_REQ_CITY "New York City" set_var EASYRSA_REQ_ORG "DigitalOcean" set_var EASYRSA_REQ_EMAIL "admin@example.com" set_var EASYRSA_REQ_OU "Community" set_var EASYRSA_ALGO "ec" set_var EASYRSA_DIGEST "sha512"

      Cuando termine, guarde y cierre el archivo. Si utiliza nano, puede hacerlo pulsando CTRL+X y, luego, Y e INTRO para confirmar. Con esto, estará listo para crear su CA.

      Para crear el certificado root público y el par de claves privadas para su entidad de certificación, vuelva a ejecutar el comando ./easy-rsa, pero, esta vez, con la opción build-ca:

      En el resultado, verá algunas líneas sobre la versión de OpenSSL y se le solicitará ingresar una frase de contraseña para su par de claves. Asegúrese de elegir una frase de contraseña segura y anótela en un lugar resguardado. Deberá ingresar la frase de contraseña siempre que deba interactuar con su CA, por ejemplo, para firmar o revocar un certificado.

      También se le solicitará confirmar el nombre común (CN) de su CA. El nombre común es el que se usa para hacer referencia a esta máquina en el contexto de la entidad de certificación. Puede ingresar cualquier secuencia de caracteres para el nombre común de la CA. Para hacerlo más simple, no obstante, presione INTRO a fin de aceptar el nombre predeterminado.

      Output

      . . . Enter New CA Key Passphrase: Re-Enter New CA Key Passphrase: . . . Common Name (eg: your user, host, or server name) [Easy-RSA CA]: CA creation complete and you may now import and sign cert requests. Your new CA certificate file for publishing is at: /home/sammy/easy-rsa/pki/ca.crt

      Nota: Si no desea que se le solicite una contraseña cada vez que interactúe con su CA, puede ejecutar el comando build-ca con la opción nopass, de la siguiente forma:

      • ./easyrsa build-ca nopass

      Ahora, tiene dos archivos importantes, ~/easy-rsa/pki/ca.crt y ~/easy-rsa/pki/private/ca.key, que conforman los componentes públicos y privados de una entidad de certificación.

      • ca.crt es el archivo del certificado público de la CA. Los usuarios, los servidores y los clientes utilizarán este certificado para verificar que sean parte de la misma red de confianza. Todos los usuarios y los servidores que usen su CA deberán tener una copia de este archivo. Todas las partes se basarán en el certificado público para asegurarse de que nadie suplante un sistema y realice un ataque con intermediario.

      • ca.key es la clave privada que usa la CA para firmar certificados para servidores y clientes. Si un atacante obtiene acceso a su CA y, a la vez, a su archivo ca.key, deberá destruir la CA. Esta es la razón por la cual su archivo ca.key deberá estar únicamente en su máquina de CA. A su vez, lo ideal sería que su máquina de CA estuviera desconectada cuando no firme solicitudes de certificados como medida de seguridad adicional.

      Con esto, estableció su CA y esta se encuentra lista para emplearse en la firma de solicitudes de certificados y revocar certificados.

      Paso 4: Distribuir el certificado público de su entidad de certificación

      Ahora, su CA está configurada y lista para funcionar como root de confianza para cualquier sistema que desee que la use. Puede agregar el certificado de la CA a sus servidores de OpenVPN, web y de correo, entre otros. Cualquier usuario o servidor que necesite verificar la identidad de otro usuario o servidor de su red debe contar con una copia del archivo ca.crt importada en el almacén de certificados de su sistema operativo.

      Para importar el certificado público de la CA a un segundo sistema de Linux, como otro servidor o una computadora local, primero debe obtener una copia del archivo ca.crt de su servidor de CA. Puede usar el comando cat para ver el resultado en una terminal y, luego, copiarlo y pegarlo en un archivo en la segunda computadora a la que se importe el certificado. También puede usar herramientas como scp y rsync para transferir el archivo entre sistemas. Sin embargo, usaremos el método de copiar y pegar con nano en este paso, ya que funciona en todos los sistemas.

      Como usuario no root en el servidor de CA, ejecute el siguiente comando:

      • cat ~/easy-rsa/pki/ca.crt

      El resultado en su terminal será similar al siguiente:

      Output

      -----BEGIN CERTIFICATE----- MIIDSzCCAjOgAwIBAgIUcR9Crsv3FBEujrPZnZnU4nSb5TMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAwwLRWFzeS1SU0EgQ0EwHhcNMjAwMzE4MDMxNjI2WhcNMzAw . . . . . . -----END CERTIFICATE-----

      Copie todo, incluso las líneas -----BEGIN CERTIFICATE----- y -----END CERTIFICATE----- y los guiones.

      En su segundo sistema de Linux, use nano o el editor de texto que prefiera para abrir un archivo llamado /tmp/ca.crt:

      Pegue lo que acaba de copiar del servidor de CA en el editor. Cuando termine, guarde y cierre el archivo. Si utiliza nano, puede hacerlo pulsando CTRL+X y, luego, Y e INTRO para confirmar.

      Ahora que tiene una copia del archivo ca.crt en su segundo sistema de Linux, es momento de importar el certificado al almacén de certificados de su sistema operativo.

      En CentOS, Fedora u otros sistemas de Linux derivados de RedHat, ejecute los siguientes comandos para importar el certificado:

      CentOS, Fedora, RedHat distributions

      • sudo cp /tmp/ca.crt /etc/pki/ca-trust/source/anchors/
      • update-ca-trust

      Para importar el certificado del servidor de CA en un sistema basado en Debian o Ubuntu, copie y pegue el contenido del archivo en el sistema, como en el ejemplo anterior, en un archivo llamado /tmp/ca.crt. A continuación, copie el certificado en /usr/local/share/ca-certificates/ y, luego, ejecute el comando update-ca-certificates.

      Debian and Ubuntu derived distributions

      • sudo cp /tmp/ca.crt /usr/local/share/ca-certificates/
      • update-ca-certificates

      Ahora, su segundo sistema de Linux confiará en cualquier certificado firmado por el servidor de CA.

      Nota: Si utiliza su CA con servidores web y usa Firefox como navegador, deberá importar el certificado público ca.crt directamente a Firefox. Firefox no usa el almacén de certificados del sistema operativo local. Para obtener información sobre cómo agregar el certificado de su CA a Firefox, consulte el artículo de asistencia de Mozilla sobre configuración de entidades de certificación (CA) en Firefox.

      Si usa su CA para la integración con un entorno de Windows o computadoras de escritorio, consulte la documentación sobre cómo usar certutil.exe para instalar un certificado de CA.

      Si completa este tutorial como requisito previo para otro o está familiarizado con la forma de firmar y revocar certificados, puede detenerse aquí. Si desea obtener más información sobre cómo firmar y revocar certificados, en la siguiente sección opcional, se explicará cada proceso en detalle.

      (Opcional): Crear solicitudes de firma de certificados y revocar certificados

      Las siguientes secciones del tutorial son opcionales. Si completó todos los pasos anteriores, dispondrá de una entidad de certificación completamente configurada y funcional que podrá utilizar como requisito previo para otros tutoriales. Puede importar el archivo ca.crt de su CA y verificar los certificados de su red firmados por su CA.

      Si desea practicar y obtener más información sobre cómo firmar solicitudes de certificados y cómo revocarlos, en estas secciones opcionales, se explicará cómo funcionan estos dos procesos.

      (Opcional): Crear y firmar una solicitud de certificado de prueba

      Ahora que tiene una CA lista para usar, puede practicar generar una clave privada y una solicitud de certificado para familiarizarse con el proceso de firma y distribución.

      Las solicitudes de firma de certificados (CSR) constan de tres partes: una clave pública, información de identificación sobre el sistema solicitante y una firma de la solicitud misma, que se crea utilizando la clave privada de la parte solicitante. La clave privada se mantendrá en secreto y se usará para cifrar información que luego podrá descifrar quien tenga el certificado público firmado.

      Los siguientes pasos se ejecutarán en su segundo sistema de Linux con CentOS, Fedora u otra distribución de Linux derivada de RedHat. Puede ser otro servidor remoto o una máquina local de Linux, como una computadora portátil o de escritorio. Como easy-rsa no está disponible por defecto en todos los sistemas, usaremos la herramienta openssl para crear una clave privada y un certificado de prueba.

      openssl suele instalarse por defecto en la mayoría de las distribuciones de Linux, pero, para estar seguro, ejecute lo siguiente en su sistema:

      Cuando se le solicite instalar openssl, ingrese y para proceder con los pasos de la instalación. Ahora, está listo para crear una CSR de prueba con openssl.

      El primer paso para crear una CSR es generar una clave privada. Para crear una clave privada usando openssl, cree un directorio practice-csr y luego genere una clave dentro de este. En vez de crear un certificado para identificar usuarios u otras CA, crearemos esta solicitud para un servidor ficticio llamado sammy-server.

      • mkdir ~/practice-csr
      • cd ~/practice-csr
      • openssl genrsa -out sammy-server.key

      Output

      Generating RSA private key, 2048 bit long modulus (2 primes) . . . . . . e is 65537 (0x010001)

      Ahora que tiene una clave privada, puede crear una CSR correspondiente y volver a usar la utilidad openssl. Se le solicitará completar varios campos, como Country, State y City. Puede ingresar . si desea dejar un campo en blanco, pero tenga en cuenta que, si se tratara de una CSR real, sería mejor usar los valores correctos de su ubicación y su organización:

      • openssl req -new -key sammy-server.key -out sammy-server.req

      Output

      . . . ----- Country Name (2 letter code) [XX]:US State or Province Name (full name) []:New York Locality Name (eg, city) [Default City]:New York City Organization Name (eg, company) [Default Company Ltd]:DigitalOcean Organizational Unit Name (eg, section) []:Community Common Name (eg, your name or your server's hostname) []:sammy-server Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:

      Si desea agregar esos valores automáticamente como parte de la invocación de openssl en lugar de hacerlo por medio de la solicitud interactiva, puede pasar el argumento -subj a OpenSSL. Asegúrese de editar los valores resaltados para que coincidan con la ubicación, la organización y el nombre del servidor de prueba:

      • openssl req -new -key sammy-server.key -out sammy-server.req -subj
      • /C=US/ST=New York/L=New York City/O=DigitalOcean/OU=Community/CN=sammy-server

      Para verificar el contenido de una CSR, puede leer el archivo de la solicitud con openssl y examinar los campos que contiene:

      • openssl req -in sammy-server.req -noout -subject

      Output

      subject=C = US, ST = New York, L = New York City, O = DigitalOcean, OU = Community, CN = sammy-server

      Una vez que esté conforme con el asunto de la solicitud de certificado de prueba, copie el archivo sammy-server.req a su servidor de CA utilizando scp:

      • scp sammy-server.req sammy@your_ca_server_ip:/tmp/sammy-server.req

      En este paso, generó una solicitud de firma de certificado para un servidor ficticio llamado sammy-server. En una situación real, la solicitud podría provenir, por ejemplo, de un servidor web de un entorno de ensayo o desarrollo que requiera un certificado TLS para pruebas o de un servidor de OpenVPN que solicite un certificado para que los usuarios puedan conectarse a una VPN. En el siguiente paso, procederemos a firmar la solicitud de firma de certificado usando la clave privada del servidor de CA.

      (Opcional): Firmar una CSR

      En el paso anterior, creó una solicitud de certificado y una clave de prueba para un servidor ficticio. La copió al directorio /tmp de su servidor de CA, simulando el proceso que seguiría si clientes o servidores reales le enviaran solicitudes de firma de certificados (CSR).

      Continuando con la situación ficticia, ahora, el servidor de CA debe importar el certificado de prueba y firmarlo. Una vez que la CA valida una solicitud de certificado y la vuelve a enviar a un servidor, los clientes que confían en la entidad de certificación también podrán confiar en el nuevo certificado emitido.

      Debido a que operaremos dentro de la PKI de la CA, donde está disponible la utilidad easy-rsa, utilizaremos esta utilidad easy-rsa en los pasos de firma para facilitar la tarea, en vez de usar openssl directamente como hicimos en el ejemplo anterior.

      El primer paso para firmar la CSR ficticia es importar la solicitud de certificado usando la secuencia de comandos easy-rsa:

      • cd ~/easy-rsa
      • ./easyrsa import-req /tmp/sammy-server.req sammy-server

      Output

      . . . The request has been successfully imported with a short name of: sammy-server You may now use this name to perform signing operations on this request.

      Ahora, puede firmar la solicitud ejecutando la secuencia de comandos easyrsa con la opción sign-req, seguida del tipo de solicitud y el nombre común incluido en la CSR. El tipo de solicitud puede ser client, server o ca. Debido a que estamos practicando con un certificado para un servidor ficticio, asegúrese de utilizar el tipo de solicitud server:

      • ./easyrsa sign-req server sammy-server

      En el resultado, se le solicitará verificar que la solicitud provenga de una fuente de confianza. Escriba yes y luego presione ENTER para confirmarlo:

      Output

      You are about to sign the following certificate. Please check over the details shown below for accuracy. Note that this request has not been cryptographically verified. Please be sure it came from a trusted source or that you have verified the request checksum with the sender. Request subject, to be signed as a server certificate for 3650 days: subject= commonName = sammy-server Type the word 'yes' to continue, or any other input to abort. Confirm request details: yes . . . Certificate created at: /home/sammy/easy-rsa/pki/issued/sammy-server.crt

      Si cifró su clave de la CA, se le solicitará ingresar la contraseña en este punto.

      Al completar esos pasos, firmó la CSR de sammy-server.req usando la clave privada del servidor de CA en /home/sammy/easy-rsa/pki/private/ca.key. El archivo sammy-server.crt resultante contiene la clave de cifrado pública del servidor de prueba, así como una nueva firma del servidor de CA. El objetivo de la firma es indicar a quienes confían en la CA que también pueden confiar en el certificado de sammy-server.

      Si esta solicitud fuera para un servidor real, como un servidor web o VPN, el último paso en el servidor de CA sería distribuir los nuevos archivos sammy-server.crt y ca.crt del servidor de CA al servidor remoto que realizó la solicitud de firma de certificado:

      • scp pki/issued/sammy-server.crt sammy@your_server_ip:/tmp
      • scp pki/ca.crt sammy@your_server_ip:/tmp

      En este punto, podría utilizar el certificado emitido con, por ejemplo, un servidor web, una VPN, una herramienta de administración de configuración o un sistema de base de datos, o para la autenticación de clientes.

      (Opcional): Revocar un certificado

      De tanto en tanto, es posible que deba revocar un certificado para evitar que un usuario o un servidor lo use, por ejemplo, si roban la computadora portátil de alguien, si se compromete un servidor web o si un empleado o contratista deja de trabajar con su organización.

      Estos son los pasos del proceso general para revocar un certificado:

      1. Rechace el certificado con el comando ./easyrsa revoke client-name.
      2. Genere una nueva CRL con el comando ./easyrsa gen-crl.
      3. Transfiera el archivo crl.pem actualizado al servidor o los servidores que se basan en su CA y, en esos sistemas, cópielo al directorio o los directorios necesarios de los programas que hagan referencia a él.
      4. Reinicie todos los servicios que utilicen su CA y el archivo CRL.

      Puede utilizar este proceso para revocar cualquier certificado que haya emitido anteriormente en cualquier momento. Analizaremos cada paso en detalle en las siguientes secciones, comenzando por el comando revoke.

      Revocar un certificado

      Para revocar un certificado, diríjase al directorio easy-rsa en su servidor de CA:

      Luego, ejecute la secuencia de comandos easyrsa con la opción revoke seguida del nombre del cliente que desee revocar: Siguiendo el ejemplo práctico anterior, el nombre común del certificado es sammy-server:

      • ./easyrsa revoke sammy-server

      Con esto, se solicitará que confirme el rechazo ingresando yes:

      Output

      Please confirm you wish to revoke the certificate with the following subject: subject= commonName = sammy-server Type the word 'yes' to continue, or any other input to abort. Continue with revocation: yes . . . Revoking Certificate 8348B3F146A765581946040D5C4D590A . . .

      Observe el valor resaltado en la línea Revoking Certificate. Este valor es el número de serie único del certificado que se revocará. Necesitará este valor si desea examinar la lista de revocación en el último paso de esta sección para verificar que el certificado se encuentre en ella.

      Una vez que se confirme la acción, la CA revocará el certificado. Sin embargo, los sistemas remotos que se basan en la CA no tienen forma de verificar si se revocó un certificado. Los usuarios y los servidores podrán seguir utilizando el certificado hasta que la lista de revocación de certificados (CRL) se distribuya a todos los sistemas que se basan en la CA.

      En el siguiente paso, generará una CRL o actualizará un archivo crl.pem existente.

      Generar una lista de revocación de certificados

      Ahora que revocó un certificado, es importante actualizar la lista de certificados revocados en su servidor de CA. Una vez que tenga una lista de revocación actualizada, podrá indicar los usuarios y sistemas que tienen certificados válidos en su CA.

      Para generar una CRL, ejecute el comando easy-rsa con la opción gen-crl mientras se encuentre en el directorio ~/easy-rsa:

      Si usó una frase de contraseña cuando creó su archivo ca.key, se le solicitará ingresarla. El comando gen-crl generará un archivo llamado crl.pem, que contiene la lista actualizada de los certificados revocados de esa CA.

      A continuación, deberá transferir el archivo crl.pem actualizado a todos los servidores y clientes que se basan en esta CA cada vez que ejecute el comando gen-crl. De lo contrario, los clientes y sistemas podrán seguir accediendo a los servicios y sistemas que utilizan su CA, dado que esos servicios necesitan conocer el estado de revocación del certificado.

      Transferir una lista de revocación de certificados

      Ahora que generó una CRL en su servidor de CA, deberá transferirla a los sistemas remotos que se basan en su CA. Para transferir este archivo a sus servidores, puede usar el comando scp.

      Nota: En este tutorial, se explica la forma de generar y distribuir una CRL manualmente. Si bien hay métodos más sólidos y automatizados para distribuir y verificar las listas de revocación, como OCSP-Stapling, la configuración de esos métodos está fuera del alcance de este artículo.

      Asegúrese de estar conectado a su servidor de CA como usuario no root y ejecute lo siguiente; sustituya your_server_ip por el IP de su servidor o su nombre de DNS:

      • scp ~/easy-rsa/pki/crl.pem sammy@your_server_ip:/tmp

      Ahora que el archivo se encuentra en el sistema remoto, el último paso es actualizar todos los servicios con la nueva copia de la lista de revocación.

      Actualizar servicios que admiten una CRL

      En este tutorial, no se enumeran los pasos necesarios para actualizar los servicios que utilizan el archivo crl.pem. En general, deberá copiar el archivo crl.pem a la ubicación que el servicio espera y, luego, reiniciarlo mediante systemctl.

      Una vez que actualice sus servicios con el nuevo archivo crl.pem, podrán rechazar las conexiones de clientes o servidores que usen un certificado revocado.

      Examinar y verificar el contenido de una CRL

      Si desea examinar un archivo CRL, por ejemplo, para confirmar una lista de certificados revocados, utilice el siguiente comando openssl desde el directorio easy-rsa de su servidor de CA:

      • cd ~/easy-rsa
      • openssl crl -in pki/crl.pem -noout -text

      También puede ejecutar este comando en cualquier servidor o sistema que tenga la herramienta openssl instalada con una copia del archivo crl.pem. Por ejemplo, si transfirió el archivo crl.pem a su segundo sistema y desea verificar que el certificado de sammy-server se haya revocado, puede usar un comando openssl, como el siguiente, y sustituir el número de serie resaltado aquí por el que observó anteriormente cuando revocó el certificado:

      • openssl crl -in /tmp/crl.pem -noout -text |grep -A 1 8348B3F146A765581946040D5C4D590A

      Output

      Serial Number: 8348B3F146A765581946040D5C4D590A Revocation Date: Apr 1 20:48:02 2020 GMT

      Note cómo se usa el comando grep para verificar el número de serie único que observó en el paso de revocación. Ahora, puede verificar el contenido de su lista de revocación de certificados en cualquier sistema que se base en ella para restringir el acceso a usuarios y servicios.

      Conclusión

      En este tutorial, creó una entidad de certificación privada usando el paquete Easy-RSA en un servidor independiente de CentOS 8. Aprendió sobre el funcionamiento del modelo de confianza entre partes que se basan en la CA. También creó y firmó una solicitud de firma de certificado (CSR) para un servidor de prueba y, luego, aprendió a revocar certificados. Por último, aprendió a generar y distribuir una lista de revocación de certificados (CRL) para cualquier sistema que se base en su CA a fin de garantizar que los usuarios o servidores que no deban tener acceso a los servicios no puedan tenerlo.

      Ahora, puede emitir certificados para usuarios y usarlos con servicios como OpenVPN. También puede usar su CA para configurar servidores web de desarrollo o ensayo con certificados para proteger sus entornos de no producción. El uso de una CA con certificados TLS durante el desarrollo puede ayudarlo a asegurarse de que su código y sus entornos se adapten en la mayor medida posible a su entorno de producción.

      Si desea saber más sobre cómo usar OpenSSL, nuestro tutorial Conceptos básicos de OpenSSL: Trabajar con certificados SSL, claves privadas y CSR contiene mucha información adicional para ayudarlo a familiarizarse con los fundamentos de OpenSSL.



      Source link