Segurança de contêineres em um cluster kubernetes
Tags: kubernetes, security, docker, linux
Published: 2022-11-02 18:10:46

## **Introdução**

Recentemente vivemos um período de aceleração contínua no mundo da tecnologia da informação, principalmente na maneira como entregamos serviços e produtos. Com essa aceleração tivemos um "BOOM" no crescimento da procura por SRE's, ocasionando assim uma escassez na mão de obra qualificada para tal função, resultando assim, na prática de contratação de pessoas visando o treinamento delas dentro da empresa para que ela "se forme" um SRE.

Porém, devido a essa aceleração muitos profissionais acabam pulando etapas importantes de aprendizado, como por exemplo, as boas práticas de desenvolvimento/orquestração de serviços, gerando assim um risco para as companhias de tecnologia. 

Neste artigo irei abordar um pouco sobre segurança voltada a orquestração de contêineres utilizando o kubernetes.

## **Docker**

O Docker, é o componente do software de código aberto que automatiza a implementação de aplicativos em Contêineres baseados na arquitetura do LINUX. O seu principal objetivo é segmentar uma aplicação em microsserviços para que assim seja possível garantir uma melhor observabilidade, disponibilidade e escalabilidade do serviço.

## **Kubernetes**

Kubernetes é um sistema de orquestração de contêineres open-source que automatiza a implantação, o dimensionamento e a gestão de aplicações em contêineres. Possibilitando dentre vários ganhos um ganho enorme na disponibilidade das aplicações/serviços uma vez que, ele possui componentes de auto-scaling que permitem o upgrade do microsserviço.


## **Segurança**

Hoje vivemos uma época de fácil acesso a informação, seja ela para o uso benéfico ou maléfico. Facilmente podemos encontrar vídeo aulas na internet ensinando pessoas que tem um conhecimento básico a realizar diversos tipos de ataques.

No contexto dos contêineres, um dos principais problemas conhecidos é a execução do mesmo com privilégios de super-usuário (root), que poderia ser corrigida com boas práticas de segurança.

No próximo tópico irei mostrar algumas boas práticas que podem ser implementadas em suas configurações para garantir uma "camada extra" de segurança para seus contêineres.

## **Dockerfile**

O Dockerfile é um arquivo que é interpretado pelo Docker para buildar a imagem do contêiner com as configurações que você informar. Abaixo temos um exemplo de Dockerfile comum que, por sua vez, não tem nenhum tipo de implementação de segurança.

```
FROM my.repo/my-images/myimage
LABEL maintainer="dev.to" author="dev.to"

ADD *.jar /my-app.jar

ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

EXPOSE 80 443

ENTRYPOINT java -Dnewrelic.config.labels="$NEW_RELIC_LABELS" $JAVA_OPTS -jar /my-app.jar
```

Devido ao fato de não ter um usuário configurado no Dockerfile o Docker por default irá executar o build como super-usuário, fazendo assim com que ao final do build o contêiner mantenha o usuário root como usuário padrão.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u16e88o646yv7wqiqv2k.png)

O problema poderia ser corrigido utilizando um simples `USER myappuser` por exemplo. Mas existem casos onde o build pode quebrar por falta de privilégios de super-usuário para executar alguns comandos, nesse caso podemos adicionar a criação do usuário ao final do build para que, antes de finalizar o Docker faça o switch para `myappuser`. Como complemento também recomenda-se utilizar portas altas para expor o serviço e configurar um grupo para o usuário.

```
FROM my.repo/my-images/myimage
LABEL maintainer="dev.to" author="dev.to"

ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

RUN apt-get update -y && apt-get install vim mlocate -y

RUN groupadd -r myuserapp -g 65536 && useradd --no-log-init -u 65536 -r -g myuserapp myuserapp -m -d /myuserapp
USER myuserapp
WORKDIR /myuserapp
COPY main.jar .

ENTRYPOINT java -jar /myuserapp/main.jar

ADD --chown=65536:65536 *.jar /myuserapp/main.jar
```

Note que o parâmetro `USER` só é utilizado após a execução dos comandos que necessitam de privilégios para serem utilizados (`apt-get`).

**Kubernetes**

Agora é a vez de realizar algumas configurações de segurança no orquestrador do seu contêiner (kubernetes), no exemplo abaixo irei utilizar um deployment.

```
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: my-namespace
  labels:
   app: my-test
   component: api
  name: my-test
spec:
  replicas: 1
  selector:
    matchLabels:
      component: api
  template:
    metadata:
      labels:
        app: my-test
        component: api
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 65536
        runAsGroup: 65536
      containers:
        - image: my-repo/my-images/my-test
          name: my-test
          resources:
            limits:
              memory: "1000Mi"
              cpu: "1000m"
          securityContext:
            allowPrivilegeEscalation: false
---
```

Note os parâmetros que estão configurados no "securityContext". Eles dizem respeito a parâmetros de segurança que podem ser considerados, seja para os pods, ou somente para imagem.

No exemplo acima, o primeiro bloco do securityContext diz respeito aos contêineres do pod, todos contêineres que forem utilizados no pod terão os valores **runAsNonRoot**, **runAsUser** e **runAsGroup** configurados.

```
runAsNonRoot: true # Garante que o usuário do contêiner não tem privilégios de super-usuário (caso seja detectado, o k8s não irá subir o pod)

runAsUser: 65536 # Garante que o usuário do contêiner será o usuário com ID 65536 (que foi configurado no Dockerfile).

runAsGroup: 65536 # Garante que o grupo do usuário do contêiner será o grupo com GID 65536 (que foi configurado no Dockerfile).

```

Ao fim do deployment, temos outra configuração de securityContext, essa diz respeito exclusivamente a imagem que está localizado em my-repo/my-images/my-test, onde fora configurado o parâmetro **allowPrivilegeEscalation: false**.

```
allowPrivilegeEscalation: false # Garante que não será possível fazer priv-escaling na imagem, ou seja, caso um atacante consiga acesso ao contêiner ele não conseguirá fazer o scaling para o usuário root.
```

## **Conclusão**

É necessário darmos sempre atenção a conhecer novas stacks utilizando das melhores práticas de segurança disponíveis e conhecidas, para evitar possíveis problemas com ataques cibernéticos. No artigo acima podemos expor pontos de boas práticas de segurança que, se forem associados as configurações do Dockerfile e Deployment, garantem um nível extra de segurança nos serviços orquestrados.