Proteger con password un site estático
Tags: asciidoc, documentation, write, antora
Published: 2021-10-28 04:40:31

---
title: Proteger con password un site estático
published: true
date: 2021-09-27 00:00:00 UTC
tags: asciidoc,documentation,write,antora
canonical_url: https://jorge.aguilera.soy/blog/2021/antora-password.html
---

| | En este post voy a centrarme en un site generado con Antora pero puedes extenderlo a cualquier otro site tipo Gatsby, Hugo, etc o incluso a un simple html |

| | Puedes descargar un repo de ejemplo en [https://gitlab.com/puravida-asciidoctor/antora-skeleton](https://gitlab.com/puravida-asciidoctor/antora-skeleton)y/o acceder al ejemplo en [https://antora-password-protected.herokuapp.com/](https://antora-password-protected.herokuapp.com/) con el usuario test/test |

Una vez que tienes tu contenido generado en HTML, una de las preguntas que te surge es cómo puedo restringuir su acceso a sólo algunos usuarios.

En este post vamos a ver alguna de las alternativas que podrías usar dependiende de si los lectores serían internos (por ejemplo otros equipos en la intranet de la empresa) o externos y en este caso si cuentas con infraestructura propia o quieres usar un proveedor externo. Así mismo puedes plantearte si lo que quieres es proteger una simple página o todo un site

## Simple página HTML

Preparando este post encontré un script en node, staticrypt, que encripta una página html con una password que le proporcionas generando así un html con un interface para pedir la password y poder desencriptar la página

Digamos que tienes un Asciidoctor donde tienes documentado un API y quieres publicarlo pero que sólo lo puedan leer los que tengan la clave:

```
= My API

this is my api
blablablab
```

Generamos el html:

`$asciidoctor api.adoc`

y obtenemos `api.html`

Lo encriptamos con staticrypt

`$staticrypt api.html la_clave_para_desencriptar -o api.html`

y ya tenemos un fichero `api.html` protegido que se puede publicar en Gitlab Pages, Github, etc

Sin embargo esta solución no funciona cuando tu documentación contiene varios ficheros porque, aunque puedes encriptar todos los ficheros, el usuario tendrá que proporcionar la página en cada una. Así que necesitamos algo que mantenga la sesión

## Site alojado en S3

Como existe mucha documentación tanto de AWS como tutoriales sobre cómo crear un Bucket de S3 y proteger su contenido no voy a explicarlo aquí. Simplemente lo menciono por si no lo habías tenido en cuenta

## Site alojado en Bucket GGP

Lo mismo para un bucket de Google Cloud Platform, y en realidad por extensión a todos los compatibles con estos

## Site alojado por nuestros medios

Una de las formas de proteger un site web es usando un fichero `.htpasswd` que puede ser manejado por Apache o por Nginx. En este post vamos a usar este último pues es mucho más fácil y ligero que Apache

Para crear el fichero seguiremos cualquier tutorial de Internet pero básicamente es ejecutar un comando tipo `httpass` o usar una de las muchas páginas online que lo generan

Siguiendo cualquiera de las dos opciones, vamos a crear el usuario `test` con password `test`

httpasswd

```
test:$apr1$yofaxwjl$xw.u6dmKy2qYiayuEnWW1. (1)
```

| **1** | Obviamente puedes crear tantos usuarios como quieras, uno por cada linea
<dl>
<dt>WARNING</dt>
<dd>
<p>El fichero esperado es con un punto al inicio pero yo lo uso sin punto para que me aparezca cuando
listo el directorio y luego lo copio al contenedor con el nombre esperado</p>
</dd>
</dl>
 |

### Site interno con NGINX

Supongamos que en nuestra empresa contamos con una infraestructura y disponemos de al menos un servidor con espacio y con Docker instalado (obviamente Docker es opcional pero así podemos aislar aplicaciones unas de otras).

Supongamos que hemos creado nuestro site Antora pero no queremos que cualquier usuario pueda acceder a ello (yo que sé porqué) sino sólo aquellos que dispongan del usuario y password creados anteriormente.

En nuestro proyecto Antora, crearemos un directorio `nginx` y ubicaremos en él el fichero `htpasswd`

Así mismo crearemos en este directorio un fichero mínimo de configuración de Nginx

default.conf

```
server {
    listen 80;
    listen [::]:80;
    server_name localhost;
    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        auth_basic "Restricted Content";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
}
```

y en el root de nuestro proyecto crearemos un docker-compose similar a

docker-compose.yml

```
version: "3"

services:

  antora:
    image: "ggrossetie/antora-lunr:2.3.4"
    volumes:
      - .:/antora
    entrypoint: /bin/ash
    command: /antora/custom-antora.sh (1)

  nginx:
    image: "nginx"
    volumes:
     - ./nginx/.htpasswd:/etc/nginx/.htpasswd
     - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
     - ./public:/usr/share/nginx/html
    ports:
     - "9080:80"
```

| **1** | El contenido de este fichero escapa a este post pero basicamente construye un site antora |

Con este docker-compose podemos generar el site mediante `docker-compose run antora` lo cual nos genera la documentaacion en `public`

Una vez generada y revisada en local podemos compartirla vía nginx con `docker-compose up -d nginx`y nuestros usuarios internos podrán acceder a ella vía el puerto `9080`

### Site publico con Heroku

Usando la capa gratuita de Heroku podemos desplegar nuestro site junto con el servicio Nginx anterior de tal forma que podríamos publicarlo en Internet y protegido mediante usuario/password de la misma forma

| | Para este paso necesitas tener una cuenta gratuita en Heroku y el comando de consola instalado , así como haber hecho login con el mismo. |

La idea es muy similar y lo que vamos a aprovechar es la capacidad de poder subir una imagen a Heroku construida por nosotros y correr una instancia de la misma. En la capa gratuita, Heroku para los containers transcurrido un tiempo (creo que 30 minutos) y lo vuelve a levantar ante una petición. Como nuestro servicio es realmente ligero, este tiempo de espera es casi inmediato para el usuario

Uno de los requisitos de Heroku es que él nos indica en tiempo de arranque el puerto en el que va a escuchar el contenedor por lo que el fichero nginx anterior no nos sirve. Usaremos para ello este otro

change.default.conf

```
server {
    listen $PORT;
    listen [::]:$PORT;
    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        auth_basic "Restricted Content";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
}
```

Junto con este `Dockerfile`

Dockerfile

```
FROM nginx

COPY nginx/htpasswd /etc/nginx/.htpasswd
COPY nginx/change.default.conf /etc/nginx/conf.d/default.conf
COPY public /usr/share/nginx/html

CMD /bin/bash -c "envsubst '\$PORT' < /etc/nginx/conf.d/default.conf > /etc/nginx/conf.d/default.conf" && cat /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;' (1)
```

<1>Es una sóla linea muy larga, supongo que se puede partir en varias pero no lo he investigado

Básicamente vamos a construir una imagen de nginx cambiando en el arranque la configuracion del puerto antes de ejecutar el servicio

Con todo ello preparamos nuestra aplicación en Heroku

`heroku container:push web -a TU-APPLICATION`

Y si todo ha ido bien, la desplegamos

`heroku container:release web -a TU-APPLICATION`

y eso es todo. Ahora tu documentación estaría expuesta en Internet pero protegida por usuario/password

## Conclusión

Obviamente no es la forma más robusta y completa de desplegar una documentación, pero es sencilla, barata y si lo automatizas puedes incluso ir rotando los usuarios y/o sus claves de una forma sencilla