Estou implantando o Goldfish , uma interface para Vault , em produção em um servidor dedicado ao gerenciamento de segredos. Então a segurança é uma das principais preocupações aqui.
Estou tentando implantar o serviço com systemd em um sistema UnBuntu 16.04, dando-lhe o mínimo de permissões possíveis. Eu quero que ele seja executado como o usuário não-root goldfish
e para escutar na porta 443. Eu tentei várias opções.
Solução 1: usando um soquete systemd , como sugerido em várias postagens que encontrei, como este (o backend Goldfish é escrito em Go como no post). Isso parece ser o mais preciso e seguro, pois é gerenciado inteiramente pelo systemd e abre uma única porta para um único serviço. Os arquivos da minha unidade são assim:
-
/etc/systemd/system/goldfish.socket
:
[Unit]
Description=a Vault interface
[Socket]
ListenStream=443
NoDelay=true # Tried with false as well
-
/etc/systemd/system/goldfish.service
:
[Unit]
Description=a Vault interface
After=vault.service
Requires=goldfish.socket
ConditionFileNotEmpty=/etc/goldfish.hcl
[Service]
User=goldfish
Group=goldfish
ExecStart=/usr/local/bin/goldfish -config=/etc/goldfish.hcl
NonBlocking=true # Tried with false as well
[Install]
WantedBy=multi-user.target
Infelizmente, recebo um "listen tcp 0.0.0.0:443: bind: permission denied". Portanto, parece que ainda não obtém a permissão desejada, o que parece frustrar o propósito de criar um soquete para o serviço. O que estou perdendo aqui?
Solução 2: fornecendo o recurso CAP_NET_BIND_SERVICE ao serviço. Desta vez, não uso nenhum soquete systemd, mas a configuração AmbientCapabilities
no serviço (também tentei com CpabilityBoudingSet
e Capabilities
, o sendo esta última surpreendentemente não documentada em systemd.exec
). Adicionar o recurso CAP_NET_BIND_SERVICE ao serviço deve dar ao serviço o direito de ligar-se a qualquer porta privilegiada.
-
/etc/systemd/system/goldfish.service
:
[Service]
User=goldfish
Group=goldfish
ExecStart=/usr/local/bin/goldfish -config=/etc/goldfish.hcl
# Tried combinations of those:
AmbientCapabilities=CAP_NET_BIND_SERVICE
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
#Capabilities=CAP_NET_BIND_SERVICE+ep
Ainda sem sorte, sempre acabo com "listen tcp 0.0.0.0:443: bind: permission denied". O que estou perdendo sobre gerenciamento de recursos com o systemd?
Solução 3: dando o recurso CAP_NET_BIND_SERVICE para o executável. Desta vez eu dou o recurso CAP_NET_BIND_SERVICE diretamente ao executável goldfish, e nada no serviço systemd:
sudo setcap cap_net_bind_service=+ep /usr/local/bin/goldfish
Hurray, funciona! O serviço liga-se corretamente à porta 443 e eu posso usá-lo. No entanto, agora eu tenho um binário que pode ser executado por qualquer usuário e vincular a qualquer porta privilegiada, que eu realmente não gosto. Qual é o relacionamento entre os recursos executáveis e os recursos de serviço do systemd? Não deveria permitir alcançar o mesmo resultado que eu recebo aqui, mas apenas para um processo específico?
Solução 4: colocando o serviço atrás de um proxy. A solução que estou considerando agora é colocar o Goldfish atrás de um proxy nginx que será o único visível do lado de fora e escutando na porta 443 Isso parece ser um bom compromisso, pois mantém permissões restritas, mas adiciona uma nova peça à configuração, com o que acrescenta de complexidade e potencial de erro. Parece uma opção superior ou menor em termos de segurança e administração do sistema?
Portanto, tenho várias perguntas aqui, mas todas relacionadas a fazer um serviço systemd ser executado como um usuário não privilegiado enquanto ouve em uma porta privilegiada e as implicações de segurança que ele possui. Alguém já encontrou os mesmos problemas?
Obrigado pela sua ajuda!