Você usa / trabalha com Linux há anos diariamente, e usa SSH para tudo. Provavelmente vai ser difícil apresentar algo que você não conheça, certo?
Então vamos tirar isso à prova fazendo um estudo de caso do recurso OSLogin do Google Cloud. No final, me conte se aprendeu algo diferente ou não!
OS Login
De acordo com a documentação, OS Login é um recurso para melhor gerir o acesso via SSH às suas máquinas virtuais Linux no GCP. Ele faz mais que gerenciar chaves:
- é um mecanismo completamente integrado ao GCP IAM, o que garante controle de acesso e permissões granulares usando políticas globais da conta e não do Linux;
- implementa componentes que permitem ao Linux reconhecer identidades externas, que podem estar em um servidor LDAP ou no seu Active Directory.
Eu vejo muitas comparações com o AWS Systems Manager - Session Manager, mas é um recurso muito mais parecido com outro recurso da AWS chamado Instance Connect.
Como acessar VMs
Em uma instância com este recurso ativado (é possível ativá-lo na maioria das instâncias Linux no processo de criação), basta executar um único comando que você consegue o acesso:
$ gcloud compute ssh instancia-publica
...
Last login: Thu Dec 14 02:20:56 2023 from 35.235.244.32
cloud_user_p_0fffe37e_linuxacade@instancia-publica:~$
Se sua máquina não tiver um endereço IP público para acesso direto, o Gcloud é esperto o suficiente para saber que precisa de um passo a mais para viabilizar:
$ gcloud compute ssh instance-2
External IP address was not found; defaulting to using IAP tunneling.
...
Usuários com a role compute.osLogin ou compute.osAdminLogin naquela ainstância poderão acessar a máquina. Pode ser necessário mais permissões caso a máquina use uma ServiceAccount.
Como funciona o OS Login - cliente SSH
Ao tentar usar OS Login a primeira vez, você deverá receber a seguinte mensagem:
$ gcloud compute ssh instance-1
WARNING: The private SSH key file for gcloud does not exist.
WARNING: The public SSH key file for gcloud does not exist.
WARNING: You do not have an SSH key for gcloud.
WARNING: SSH keygen will be executed to generate a key.
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/marcelo/.ssh/google_compute_engine
Your public key has been saved in /home/marcelo/.ssh/google_compute_engine.pub
The key fingerprint is:
SHA256:W0xABfw0HgNyBgsPX6av+co9ZM/JWaa893fcIhM3zL8 marcelo@devsres.com
The key's randomart image is:
+---[RSA 3072]----+
| o o+X+. |
| = O..= |
| = +.+ |
| . oo |
| S o o |
| ooo + = |
| oo.= * o +.|
| . o. O + . *|
| o.o..o +.Eo|
+----[SHA256]-----+
...
Ainda que você tenha chaves - mesmo com os nomes padrão id_rsa, id_ecdsa, id_ed25519 -, ele irá gerar uma nova para você:
$ ls -la ~/.ssh/google*
-rw------- 1 marcelo marcelo 2602 Dec 13 23:38 /home/marcelo/.ssh/google_compute_engine
-rw-r--r-- 1 marcelo marcelo 571 Dec 13 23:38 /home/marcelo/.ssh/google_compute_engine.pub
-rw-r--r-- 1 marcelo marcelo 218 Dec 13 23:44 /home/marcelo/.ssh/google_compute_known_hosts
(Observe que eles optam por não poluir o seu arquivo known_hosts com as máquinas do GCP, o comando gcloud adiciona os hosts conhecidos em um arquivo próprio, o .ssh/google_compute_known_hosts)
A chave gerada é uma RSA de 3072 bits:
# O comando executado deve ter sido:
# ssh-keygen -t rsa -b 3072 ~/.ssh/google_compute_engineq
$ ssh-keygen -l -f ~/.ssh/google_compute_engine.pub
3072 SHA256:W0xABfw0HgNyBgsPX6av+co9ZM/JWaa893fcIhM3zL8 marcelo@dominator (RSA)
Após gerar a chave, o gcloud "sobe" a chave pública para o GCP sem você ver:
$ gcloud compute os-login ssh-keys list
FINGERPRINT EXPIRY
eee442d8830969ce8109c1c62a8d1aed1c188c11e87c7beebdb8610269724138
É possível ver informações sobre a chave executando o comando:
$ gcloud compute os-login ssh-keys describe --key eee442d8830969ce8109c1c62a8d1aed1c188c11e87c7beebdb8610269724138
fingerprint: eee442d8830969ce8109c1c62a8d1aed1c188c11e87c7beebdb8610269724138
key: ssh-rsa ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCsPAqzEGyyz5ltlhJd1wxSyde2WOkDz4baJkDyB90dXstaVLkrw64LfYTIu0W2gpJOLkzOsUNjhTJl/3Feda+GvTIpNpom7EboCYbNd9ExTWnw2W1d6Y/Inn1vydOHoi1qt7X97QOfg7avDkYHoXhHMxumRetUWxte1FBKZ8se3KAPUH/GCBEB28EO6OOqs89c9MmjxWq9d1l0iMioGzGRkM2DvowhmVe5NwrYZMeSXBd7x0bGkDTpdaT5RFJf1nvBy8a68SQbTGO6d9KsqsGmTyUrUPhylkG+yzG+DW4p+KRsC8M6bXX0J3DCiHA9evLT6MyuTpOJDpxJAb+UAdXNwNn6T154HJZ1s1w4u5ruenAepaXBqI8EzGKBy0VUBObupQZuEMNj7XkKTlF3hgjwDvnMQr0AbDsz7da/uMhcVjoUCGZPRmeYRtCpUaEG453W9ZgNlQYALy18D4NEaJ85XiQQUQWDbBoEUcdl6R0JCIJK6pe4HxTyJT05I/QYNus=
marcelo@devsres.com
name: users/cloud_user_p_0fffe37e@linuxacademygclabs.com/sshPublicKeys/eee442d8830969ce8109c1c62a8d1aed1c188c11e87c7beebdb8610269724138
É possível reusar suas chaves sem dificuldade:
$ gcloud compute os-login ssh-keys add --key-file ~/.ssh/id_rsa.pub --ttl 30
...
$ gcloud compute os-login ssh-keys list
FINGERPRINT EXPIRY
ca30c038ede7cc7ed7bee957d7778988b540f8204beabe2cdccf00ae78031a30 2023-12-14T03:19:19Z
eee442d8830969ce8109c1c62a8d1aed1c188c11e87c7beebdb8610269724138
...
Executar o "gcloud compute ssh" especificando uma chave privada sem subir a chave pública faz o auto upload da chave com TTL 0 (ou seja, não expira).
Como funciona o OS Login no servidor
No Linux: NSS
Agora sim, a parte interessante!
Primeiramente, vamos observar com que usuário você autentica no servidor remoto:
$ gcloud compute ssh instancia-publica --project=playground-s-11-b0bd65c9 --zone=us-central1-a
...
cloud_user_p_0fffe37e_linuxacade@instance-1:~$ whoami
cloud_user_p_0fffe37e_linuxacade
O usuário está associado ao meu usuário do Google Cloud - que é meio grande e não coube: cloud_user_p_0fffe37e@linuxacademygclabs.com.
Aqui a primeira diferença deste recurso para o SSM Session Manager e o Instance Connect: esse usuário não foi criado localmente na máquina:
[instancia-publica] $ grep cloud_user /etc/passwd | echo nao achei nada
nao achei nada
Isso acontece porque o OS Login integra com uma velha conhecida no mundo Linux, a libnss, por meio de um módulo específico (na verdade, dois):
[instancia-publica] $ head -n 13 /etc/nsswitch.conf
# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc-reference' and `info' packages installed, try:
# `info libc "Name Service Switch"' for information about this file.
passwd: files cache_oslogin oslogin
group: files cache_oslogin oslogin
shadow: files
gshadow: files
hosts: files dns
networks: files
O arquivo nsswitch.conf é onde, tradicionalmente, mapeamos essa integração. A resolução de nomes, por exemplo, ocorre na ordem files -> dns (ou seja, /etc/host, depois linux client resolver). Para entradas no /etc/passwd ou /etc/group, a libnss orienta buscar, após destes arquivos, primeiramente no provider cache_oslogin, e posteriormente no próprio oslogin.
Essas libs são instaladas pelo pacote:
[instancia-publica] $ dpkg -L google-compute-engine-oslogin | fgrep libnss
/lib/x86_64-linux-gnu/libnss_cache_oslogin-20231004.00.so
/lib/x86_64-linux-gnu/libnss_oslogin-20231004.00.so
/lib/x86_64-linux-gnu/libnss_cache_oslogin.so.2
/lib/x86_64-linux-gnu/libnss_oslogin.so.2
Também há units do systemd ativas com estes programas:
[instancia-publica] $ systemctl list-units 'google*'
UNIT LOAD ACTIVE SUB DESCRIPTION
google-guest-agent.service loaded active running Google Compute Engine Guest Agent
google-osconfig-agent.service loaded active running Google OSConfig Agent
google-shutdown-scripts.service loaded active exited Google Compute Engine Shutdown Scripts
google-oslogin-cache.timer loaded active waiting NSS cache refresh timer
Dependendo do provider, é possível ver as entradas usando o comando abaixo:
[instancia-publica] $ getent passwd | tail -n5
systemd-timesync:x:999:999:systemd Time Synchronization:/:/usr/sbin/nologin
systemd-coredump:x:998:998:systemd Core Dumper:/:/usr/sbin/nologin
cloud_user_p_0fffe37e_linuxacade:*:1862762045:1862762045::/home/cloud_user_p_0fffe37e_linuxacade:/bin/bash
sa_112203697991872690750:*:3661484281:3661484281::/home/sa_112203697991872690750:/bin/bash
sa_109344113766727672345:*:3686152525:3686152525::/home/sa_109344113766727672345:/bin/bash
Nem sempre o comando getent traz todas as entradas. Isso não quer dizer que o sistema operacional não seja capaz de enxergá-lo, apenas indica que a biblioteca usada não necessariamente suporta enumeração.
Se seu usuário não fosse visível para o SO, você não conseguiria nem logar!
Se ele não surgir na saída do comando acima, é possível fazer uma query direta sobre ele especificando o nome:
[instancia-publica] $ id
uid=1862762045(cloud_user_p_0fffe37e_linuxacade) gid=1862762045(cloud_user_p_0fffe37e_linuxacade) groups=1862762045(cloud_user_p_0fffe37e_linuxacade),44(video)
[instancia-publica] $ getent passwd cloud_user_p_0fffe37e_linuxacade
cloud_user_p_0fffe37e_linuxacade:*:1862762045:1862762045::/home/cloud_user_p_0fffe37e_linuxacade:/bin/bash
Nem todo mundo conhece estas funcionalidades do mundo Linux! Elas vêm desde lá atrás com o NIS/Yellow Pages, e geralmente só quem administra servidores integrados com LDAP ou Active Directory conhece esses recursos!
Agora, uma outra consideração: as conexões realmente ocorrem via ssh a partir do endereço da sua máquina!
[instancia-publica] $ ss -nt '( sport = :22 )'
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
ESTAB 0 140 10.128.0.2:22 XXX.42.69.YYY:59660
No caso, o IP XXX.42.69.YYY representa o meu endereço IP.
Se você executar o comando a partir de um tunel IAP, o endereço vai ser outro:
[instancia-publica] $ ss -nt '( sport = :22 )'
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
ESTAB 0 0 10.128.0.2:22 35.235.240.4:46519
Ou seja, é necessário garantir que haja conectividade a partir dos recursos de Identity Aware Proxy (IAP) do Google Cloud para que isso funcione (i.e., abrir regras para o range 35.235.240.0/20, como descrito na documentação).
Como os acessos ocorrem realmente via SSH (diferentemente do AWS SSM Session Manager), é necessário configurar um outro componente para viabilizar o login no Linux: o PAM!
No Linux: PAM
O diretório /etc/pam.d conta com a configuração de como vários programas do Linux realizam seu processo de autenticação e estabelecimento de sessões!
[instancia-publica] $ ls /etc/pam.d
chfn chsh common-auth common-session cron newusers passwd runuser-l su sudo
chpasswd common-account common-password common-session-noninteractive login other runuser sshd su-l
O PAM oculta diversas camadas de complexidade por trás de sua aparente simplicidade, e é imprescindível que um administrador Linux entenda do que se trata e saiba ler o que dizem as configurações.
Esta é a configuração PAM do comando sudo:
[instancia-publica] $ egrep -v '^$|^#' /etc/pam.d/sudo
@include common-auth
@include common-account
@include common-session-noninteractive
Esta, a do su:
[instancia-publica] $ egrep -v '^$|^#' /etc/pam.d/su
auth sufficient pam_rootok.so
session required pam_env.so readenv=1
session required pam_env.so readenv=1 envfile=/etc/default/locale
session optional pam_mail.so nopen
session required pam_limits.so
@include common-auth
@include common-account
@include common-session
E esta a do ssh (se a diretiva UsePAM estiver configurada!):
[instancia-publica] $ sudo fgrep -i 'UsePAM' /etc/ssh/sshd_config
UsePAM yes
[instancia-publica] $ egrep -v '^$|^#' /etc/pam.d/sshd
auth [default=ignore] pam_group.so
@include common-auth
account required pam_nologin.so
@include common-account
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
session required pam_loginuid.so
session optional pam_keyinit.so force revoke
@include common-session
session optional pam_motd.so motd=/run/motd.dynamic
session optional pam_motd.so noupdate
session optional pam_mail.so standard noenv # [1]
session required pam_limits.so
session required pam_env.so # [1]
session required pam_env.so user_readenv=1 envfile=/etc/default/locale
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
@include common-password
session [success=ok default=ignore] pam_mkhomedir.so
Achou complicado? Note que em todos há includes de outros arquivos, o que 'empilha' as diretivas com as descritas nesses arquivos! Isso existe para evitar que você precise reconfigurar cada programa separadamente com as mesmas diretivas!
O Google OS Login pode modificar o PAM e usar dois módulos, o pam_oslogin_login.so para determinar se o usuário pode autenticar, e o pam_oslogin_admin.so que determina se o usuário vai poder usar o comando sudo.
Em vez de criar as entradas em /etc/sudoers.d, o OS Login deixa um arquivo com um include para outro diretório:
[instancia-publica] $ cat /etc/sudoers.d/google-oslogin
#includedir /var/google-sudoers.d
[instancia-publica] $ cat /var/google-sudoers.d/*
cloud_user_p_0fffe37e_linuxacade ALL=(ALL) NOPASSWD: ALL
No SSH
A parte mais interessante, entretanto, vem nas modificações do SSH. O programa faz as seguintes modificações no arquivo /etc/sshd:
[instancia-publica] $ head -n7 /etc/ssh/sshd_config
#### Google OS Login control. Do not edit this section. ####
TrustedUserCAKeys /etc/ssh/oslogin_trustedca.pub
AuthorizedPrincipalsCommand /usr/bin/google_authorized_principals %u %k
AuthorizedPrincipalsCommandUser root
AuthorizedKeysCommand /usr/bin/google_authorized_keys
AuthorizedKeysCommandUser root
#### End Google OS Login control section. ####
As três primeiras diretivas estão relacionadas ao uso de certificados SSH, o que, a princípio, não é a funcionalidade usada para as conexões do usuário - mas que vale a leitura a respeito se você nunca ouviu falar!
A diretiva mais importante para o uso desta funcionalidade é AuthorizedKeysCommand: ela permite que o SSH invoque um comando adicional para recuperar quais chaves estão associadas ao usuário tentando logar.
As chaves estão salvas no GCP (como mostramos na sessão do cliente!); logo, basta que a instância seja capaz de acessar a API do GCP e listar as chaves públicas cadastradas para o usuário!
[instancia-publica] $ /usr/bin/google_authorized_keys cloud_user_p_0fffe37e_linuxacade
ssh-rsa ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCsPAqzEGyyz5ltlhJd1wxSyde2WOkDz4baJkDyB90dXstaVLkrw64LfYTIu0W2gpJOLkzOsUNjhTJl/3Feda+GvTIpNpom7EboCYbNd9ExTWnw2W1d6Y/Inn1vydOHoi1qt7X97QOfg7avDkYHoXhHMxumRetUWxte1FBKZ8se3KAPUH/GCBEB28EO6OOqs89c9MmjxWq9d1l0iMioGzGRkM2DvowhmVe5NwrYZMeSXBd7x0bGkDTpdaT5RFJf1nvBy8a68SQbTGO6d9KsqsGmTyUrUPhylkG+yzG+DW4p+KRsC8M6bXX0J3DCiHA9evLT6MyuTpOJDpxJAb+UAdXNwNn6T154HJZ1s1w4u5ruenAepaXBqI8EzGKBy0VUBObupQZuEMNj7XkKTlF3hgjwDvnMQr0AbDsz7da/uMhcVjoUCGZPRmeYRtCpUaEG453W9ZgNlQYALy18D4NEaJ85XiQQUQWDbBoEUcdl6R0JCIJK6pe4HxTyJT05I/QYNus= marcelo@devsres.com
Caso mais uma chave seja adicionada do lado do cliente:
$ gcloud compute os-login ssh-keys add --key-file ~/.ssh/id_ecdsa.pub --ttl 30
...
$ gcloud compute os-login ssh-keys list
FINGERPRINT EXPIRY
68dc496cf5293b7fa094a05b0f0acc92d2382e7bb983a70bacae1ea06cbfaeed 2023-12-14T05:27:22Z
eee442d8830969ce8109c1c62a8d1aed1c188c11e87c7beebdb8610269724138
A saída do outro comando irá mostrar todas as chaves disponíveis!
[instancia-publica] $ /usr/bin/google_authorized_keys cloud_user_p_0fffe37e_linuxacade
fiXhlbf7uTxcmcYKSrFRakfPRyVtpUVaBLoTJHh70OvITNBXyCiUxwBGM6kKwqSWGX6uD3Bk8nal6cG4eZFHGFy8mfCK3Cx7wNShvXfXEVOqALXJI5W8NPl3eIOMQhx+S1mrK+45K4qTqfaUuq9W8MdrzUEfB4y/DbsgcY4p6GAqTBURuMU0Ym3d+H7DAo4rJCTpy1d/qTvCTkN14Y3slIshmzORmuo2caPpPMsX7iJtpLZkmMJ872gTKU3P5sx7efEv1D89i1WMHFpWAqhIRsKNsJCB53r0Dtt6dK2iKeonWgZYMYfKd+3Px8eDgYyOetNVFhaGXv9w/bDDj60pchENCEDTB59CdAU71tiI/U7738DITq1ZZVzCSWpu0= cloud_user_p_0fffe37e@cs-380498931324-default
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCsPAqzEGyyz5ltlhJd1wxSyde2WOkDz4baJkDyB90dXstaVLkrw64LfYTIu0W2gpJOLkzOsUNjhTJl/3Feda+GvTIpNpom7EboCYbNd9ExTWnw2W1d6Y/Inn1vydOHoi1qt7X97QOfg7avDkYHoXhHMxumRetUWxte1FBKZ8se3KAPUH/GCBEB28EO6OOqs89c9MmjxWq9d1l0iMioGzGRkM2DvowhmVe5NwrYZMeSXBd7x0bGkDTpdaT5RFJf1nvBy8a68SQbTGO6d9KsqsGmTyUrUPhylkG+yzG+DW4p+KRsC8M6bXX0J3DCiHA9evLT6MyuTpOJDpxJAb+UAdXNwNn6T154HJZ1s1w4u5ruenAepaXBqI8EzGKBy0VUBObupQZuEMNj7XkKTlF3hgjwDvnMQr0AbDsz7da/uMhcVjoUCGZPRmeYRtCpUaEG453W9ZgNlQYALy18D4NEaJ85XiQQUQWDbBoEUcdl6R0JCIJK6pe4HxTyJT05I/QYNus= marcelo@devsres.com
É ou não é um recurso interessante?
Isso porque eu ainda não mostrei a funcionalidade de usar SSH com MFA também disponível!
Top comments (0)