Adicionando Headers no Nginx com Ansible
Tags: devops, ansible, automation, nginx
Published: 2024-04-08 02:25:56

**Fala comunidade !!!**

A ideia desse post é passar uma forma de automatizar o incremento de Headers dentro do arquivo de configuração do Nginx.

[GitHub Repo  ⭐🚀](https://github.com/LeonanViana/add_headers_nginx)

Recentemente passei por um Projeto no qual precisava adicionar Headers no Nginx para que a Aplicação Web não quebrasse em certas páginas.

**Exemplo de Headers:**

_- Strict-Transport-Security_
_- Content-Security-Policy_
_- X-XSS-Protection_
_- X-Frame-Option_
_- X-Content-Type-Options_
_- Referrer-Policy_
_- Permissions-Policy_

Devido a quantidade de Hosts e também incrementos, resolvi criar uma automação com Ansible.

**_Etapa 1:_**
Criaremos um arquivo TXT para adicionar os headers e os cabeçalhos inseridos necessários para nossa Aplicação, um exemplo abaixo:

```
        
add_header Strict-Transport-Security 'max-age=63072000; includeSubDomains; preload';
add_header Content-Security-Policy "connect-src 'self' www.google-analytics.com adservice.google.com analytics.google.com translate.googleapis.com www.google.co.ao www.google.co.in www.google.com.ar ; font-src 'self' data: fonts.gstatic.com; img-src 'self' data: static.zdassets.com unsafe c.bing.com www.google-analytics.com www.googletagmanager.com www.facebook.com lh4.googleusercontent.com www.securityscore.com.br a.slack-edge.com lh5.googleusercontent.com www.google.com www.google.com.br www.google.ca adservice.google.com lh4.googleusercontent.com www.google-analytics.com www.google.co.ao www.google.co.in www.google.co.mz www.google.com.ar www.google.pt www.googletagmanager.com www.securityscore.com.br a.slack-edge.com analytics.google.com blob: i.ytimg.com lh5.googleusercontent.com stats.g.doubleclick.net unsafe www.google.com.au www.google.com.pe www.google.st; script-src-attr 'unsafe-inline'; script-src-elem 'self' 'unsafe-inline' cdn.mxpnl.com static.zdassets.com www.google-analytics.com www.googletagmanager.com blob: ; script-src 'unsafe-eval' wasm-eval; style-src-attr 'unsafe-inline'; style-src-elem 'self' 'unsafe-inline' fonts.googleapis.com; style-src 'self' fonts.googleapis.com 'unsafe-inline'; form-action www.facebook.com; child-src www.youtube.com; default-src 'self' 'unsafe-inline' adservice.google.com analytics.google.com connect.facebook.net data: fonts.googleapis.com fonts.gstatic.com googleads.g.doubleclick.net stats.g.doubleclick.net www.facebook.com www.google.com.br www.googletagmanager.com";
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy "strict-origin";
add_header Permissions-Policy "geolocation=(self),midi=(self),sync-xhr=(self),microphone=(self),camera=(self),magnetometer=(self),gyroscope=(self),fullscreen=(self),payment=(self)";

        
```
**_Etapa 2:_**
Criando a Playbook e os Jobs de execução.

Nossa Playbook é composta por alguns Jobs:

_- Backup do arquivo nginx.conf;_

_- Remoção das linhas com a diretiva add_header para entradas sem duplicidade;_

_- Remoção das linhas com a diretiva add_header para linhas comentadas;_

_- Remoção de linhas em brancos após remoção das linhas do add_header para manter o arquivo da formatação correta;_

_Incremento dos Headers a partir do arquivo .txt;_

_- Restart nginx para atualizar o servico com as alterações realizadas;_

```
- name: Adicionar Headers no Nginx
  hosts: localhost
  become: yes
  become_method: sudo

  vars:
    # ALTERAR PATHS CONFORME SUA NECESSIDADE
    PATH_ADD_HEADERS_TXT: /Users/leonanviana/Repos/LeonanViana/add_headers_nginx/playbooks/headers_nginx.txt # Alterar para o seu diretorio. 
    PATH_NGINX_CONF: /opt/homebrew/etc/nginx/nginx.conf # Alterar para o seu diretorio. 

  tasks:

    - name: Fazer backup do arquivo nginx default # Primeira opcao de BKP
      fetch:
        src: /opt/homebrew/etc/nginx/nginx.conf 
        dest: /var/tmp/
        flat: yes
      become: true

    - name: Fazer backup do arquivo nginx default com comando cp # Segunda opcao de BKP
      shell: cp "{{ PATH_NGINX_CONF }}" /var/tmp/default_nginx_bkp

    - name: Remover linhas com add_header
      lineinfile:
        path: "{{ PATH_NGINX_CONF }}" 
        state: absent
        regexp: '^(\s*add_header\s.*;)$'

    - name: Remover linhas com add_header comentadas com "#"
      lineinfile:
        path: "{{ PATH_NGINX_CONF }}" 
        state: absent
        regexp: '^(\s*#add_header\s.*;)$'         

    - name: Remover linhas em branco
      replace:
        path: "{{ PATH_NGINX_CONF }}" 
        regexp: '^\s*$'
        replace: ''      

    - name: Add Headers Nginx
      shell: awk '/gzip_vary on;/ {print; system("cat \"{{ PATH_ADD_HEADERS_TXT }}\""); next} 1' "{{ PATH_NGINX_CONF }}" > tmpfile && mv tmpfile "{{ PATH_NGINX_CONF }}"

    - name: Restart Nginx
      service:
        name: nginx
        state: restarted          
     
```

**OBS:** O JOB que adiciona os Headers no nginx.conf usa _AWK_ para buscar a string _"gzip_vary on;"_ como base _(Podendo ser substituída por outro parametro ja existente)_ no arquivo de configuração do Nginx. Se encontrada, imprime a linha atual e acrescenta o conteúdo de um arquivo de cabeçalhos Nginx definido pela variável _PATH_ADD_HEADERS_TXT_. Em seguida, redireciona a saída para um arquivo temporário e, se bem-sucedido, substitui o arquivo de configuração original do Nginx pelo temporário.

**_HANDS_ON 🚀:_**
Abaixo uma breve demonstração da execução da Playbook.

- Arquivo nginx.conf sem nenhuma diretiva de Headers;
![Nginx.conf sem Headers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0oeuczmi0fh8z4oshjjc.png)


- Execução da Playbook para adicionar Headers;
![Run Playbook](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ly1papitislyhv1tuudu.png)



- Visualização do Arquivo nginx.conf e as diretivas de Headers;
![Nginx.conf com Headers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tk0f13xcfkgsq4ucymsq.png)


🔚 **_CONCLUSÃO:_**
Com isso podemos ajustar nossas diretivas e adicionar headers conforme a necessidade em vários hosts de uma só vez;

Por último criei uma Playbook para a remoção das diretivas de Headers se necessário:
[Remove Headers](https://github.com/LeonanViana/add_headers_nginx/blob/main/playbooks/remove_headers_nginx.yml)