Exemplos de uso inteligente de modelos SSH





Os certificados SSH são uma ferramenta muito poderosa . Inicialmente, no centro de certificação, step-ca



implementamos apenas um conjunto mínimo de funções para autenticação usando certificados de usuário e host. Em seguida, adicionamos modelos de certificado X.509 e, em agosto do ano passado - e modelos SSH, na versão 0.15.2. Por fim, documentamos esse recurso e estamos prontos para falar sobre ele.



Os modelos para certificados SSH funcionam de maneira semelhante aos modelos X.509: são arquivos JSON escritos em Go text/template



. Eles são usados ​​para configurar os certificados SSH que ele emite step-ca



. Vamos dar uma olhada no que são esses modelos e como você pode usá-los.



Por padrão, um modelo de certificado SSH personalizado se parece com este:



{
	"type": {{ toJson .Type }},
	"keyId": {{ toJson .KeyID }},
	"principals": {{ toJson .Principals }},
	"extensions": {{ toJson .Extensions }},
	"criticalOptions": {{ toJson .CriticalOptions }}
}
      
      





E aqui está o certificado SSH emitido usando este padrão:



$ step ssh inspect id_ct-cert.pub
id_ct-cert.pub:
        Type: ecdsa-sha2-nistp256-cert-v01@openssh.com user certificate
        Public key: ECDSA-CERT SHA256:iczSh1XiBBE36yfJcDidgp6fqY3qWx1RtEwFfAN9jDs
        Signing CA: ECDSA SHA256:MKwRQ/SDKk/pCJbbCk5bfhZACjSjv7uZXLyc5n4Wx6k
        Key ID: "carl@smallstep.com"
        Serial: 2831574724231262409
        Valid: from 2020-11-17T16:48:11 to 2020-11-18T08:49:11
        Principals:
                carl
                carl@smallstep.com
        Critical Options: (none)
        Extensions:
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc
      
      





Ele permite que o usuário carl



(ou carl@smallstep.com



) se autentique em qualquer host SSH que confie em minha CA SSH. O certificado inclui algumas extensões básicas:



  • permit-x11-forwarding



    : Habilita o encaminhamento X11 (com ssh -X



    ) para executar programas X11 remotos no monitor local.

  • permit-agent-forwarding



    : Permite o redirecionamento do agente (usando ssh -A



    ) para encaminhar chaves do agente SSH local para o host remoto (para obter mais informações sobre o agente SSH, consulte aqui ).

  • permit-port-forwarding



    : Permite o encaminhamento de portas (tunelamento) da porta local para a remota ( ssh -L



    ) ou remota para a local ( ssh -R



    ).

  • permit-pty



    : Uma extensão muito importante. Se você deseja abrir uma sessão interativa no console, o host deve alocar um pty (pseudo-tty) para você. Caso contrário, nenhuma interatividade é fornecida. Por exemplo, para testar a autenticação SSH no GitHub, pode-se executar ssh -T git@github.com



    ( -T



    desativa a solicitação pty).

  • permit-user-rc



    : Execute um arquivo RC pessoal após conectar (localizado ~/.ssh/rc



    no host remoto).


Os certificados de usuário e host oferecem suporte a extensões e parâmetros críticos, mas o OpenSSH não define nenhuma extensão interna ou parâmetro crítico para certificados de host. Assim, tudo o que há de mais interessante acontece com os certificados de usuário, portanto, neste artigo, consideraremos apenas eles.



Exemplos de modelos de certificado



Vamos fazer algumas alterações no modelo padrão.



Agente de proibição e encaminhamento de porta

Se os usuários estiverem se conectando a hosts internos por meio do host bastião , seria bom desabilitar o encaminhamento de porta por motivos de segurança. Você não quer que os usuários redirecionem o tráfego do servidor de produção MySQL para seu host local. Da mesma forma, o redirecionamento do agente traz um risco de segurança . Este é um modelo que simplesmente remove essas duas extensões dos certificados SSH:



{
	"type": {{ toJson .Type }},
	"keyId": {{ toJson .KeyID }},
	"principals": {{ toJson .Principals }},
	"extensions": {
           "permit-x11-forwarding": "",
           "permit-pty": "",
           "permit-user-rc": ""
  },
	"criticalOptions": {{ toJson .CriticalOptions }}
}
      
      





Incorporando a diretiva force-command

ForceCommand



É uma diretiva de configuração SSHD do lado do servidor que executa um comando alternativo no host em vez de um terminal interativo. Mas, com o mesmo efeito, você pode incorporá-lo force-command



diretamente no certificado - na seção Critical Options:



. Pode ser útil para contas de serviço que precisam executar apenas um comando, por exemplo, iniciar uma tarefa em um sistema remoto.



Restringindo conexões por endereços

Para restringir o escopo de um certificado, uma lista de endereços IP permitidos (blocos CIDR) pode ser incorporada a ele.



Aqui está um modelo de certificado que usa ambos source-address



, e force-command



.



{
	"type": {{ toJson .Type }},
	"keyId": {{ toJson .KeyID }},
	"principals": {{ toJson .Principals }},
	"extensions": {{ toJson .Extensions }},
	"criticalOptions": {
		"force-command": "echo \"Hello World\"",
		"source-address": "10.20.30.0/24,1.1.1.1/32"
	}
}
      
      





Este é um exemplo normal, mas aqui a lista de IP é rigidamente fixada e não muda. E geralmente queremos usar listas de endereços diferentes para usuários diferentes. Vamos tentar…



Insira valores diferentes para usuários diferentes

Obviamente, os usuários não podem ter o direito de editar o intervalo de endereços. Portanto, os valores dinâmicos devem vir de uma fonte confiável.



Para fazer isso, step-ca



por meio do provedor OpenID Connect (OIDC), você pode configurar o provedor OAuth para adicionar declarações personalizadas ao token que contém os blocos de endereço CIRD que desejamos adicionar ao certificado deste usuário.



O provedor OIDC é a maneira perfeita de emitir certificados SSH para step-ca. No artigo DIY Single Sign-On para SSH , abordei como configurar uma CA SSH para emitir certificados SSH de curto prazo usando tokens de ID de um provedor OAuth confiável. Se um step-ca



configurado como um cliente OAuth confiável, ele lerá o campo email



do token de ID e recuperará a lista de principais de certificados SSH de lá (por exemplo, carl@smallstep.com



certificados para carl



e serão gerados pelo campo carl@smallstep.com



).



Mas o OIDC permite a leitura de ID e outros campos de tokens por meio de modelos . É aqui que começa a verdadeira magia. Assim, adicionamos um campo separado ao diretório do usuário no lado do provedor de identidade source_address



- e o refletimos em nosso token de ID. Em seguida, por meio do modelo SSH, você pode inserir o valor do token no certificado. Aqui está o modelo:



{
	"type": {{ toJson .Type }},
	"keyId": {{ toJson .KeyID }},
	"principals": {{ toJson .Principals }},
	"extensions": {{ toJson .Extensions }},
{{ if .Token.source_address }}
	"criticalOptions": {
		"source-address": "{{ .Token.source_address }}"
	}
{{ else }}
	"criticalOptions": {{ toJson .CriticalOptions }}
{{ end }}
}
      
      





Autenticação GitHub por certificado

Vejamos outro exemplo de declaração personalizada. Usando GitHub Enterprise Cloud ou GitHub Enterprise Server, você pode configurar o GitHub para usar certificados SSH. Especificamente, o GitHub confiará na sua autoridade de certificação SSH . Mas para que tudo funcione, você precisa criar um certificado SSH separado para cada usuário com uma extensão login@github.com



que especifica o nome de usuário no GitHub. Com esta extensão, o certificado autentica o usuário no GitHub Enterprise. E é ótimo: o mesmo certificado permite que você se conecte ao seu servidor via SSH e envie o código ao GitHub.



Aqui está um modelo de certificado com suporte para extensão GitHub personalizada:



{
	"type": {{ toJson .Type }},
	"keyId": {{ toJson .KeyID }},
	"principals": {{ toJson .Principals }},
	"criticalOptions": {{ toJson .CriticalOptions }},
{{ if .Token.ghu }}
	"extensions": {
	  "login@github.com": {{ toJson .Token.ghu }}
	}
{{ else }}
	"extensions": {{ toJson .Extensions }}
{{ end }}
}
      
      





Para usar o modelo, você precisa adicionar um requisito individual ghu



(“Nome de usuário do GitHub”) aos tokens de identificação OIDC . Vamos dar uma olhada em como criar essa declaração personalizada usando seu provedor OAuth.



Registrando um aplicativo com um provedor de identidade

Nem todos os provedores de identidade oferecem suporte a requisitos individuais, mas se o fizerem, o processo é bastante semelhante. Veja como é feito com Okta:



  1. Adicione o aplicativo OAuth para Okta e confiar nele com o provedor de OIDC em step-ca



    como descrito na DIY SSO para SSH artigo .





  2. Adicione um novo campo ao seu diretório de usuário Okta (por exemplo GitHub Username



    )

  3. Adicione um requisito individual ao token OIDC , por exemplo, com um nome curtoghu





  4. Agora preenchemos o campo para o usuário de teste e verificamos o requisito. Okta tem uma ferramenta de teste de token de ID. Ou pode ser usado step



    para validar todo o fluxo OAuth:



    OIDC_ENDPOINT="https://[your organization].okta.com/oauth2/default/.well-known/openid-configuration"
    CLIENT_ID="[your OAuth client ID]"
    CLIENT_SECRET="[your OAuth client secret]"
    step oauth --oidc --provider $OIDC_ENDPOINT \
        --client-id $CLIENT_ID --client-secret $CLIENT_SECRET \
        --listen=":10000" --bare |
    step crypto jwt inspect --insecure
          
          





  5. Finalmente, step-ca



    para usar este padrão. A configuração do provedor deve fazer referência ao arquivo de modelo:



    {
      "provisioners": [
        {
          "type": "OIDC",
          "name": "Okta",
          "clientID": "[your OAuth client ID]",
          "clientSecret": "[your OAuth client secret]",
          "configurationEndpoint": "https://[your organization].okta.com/oauth2/default/.well-known/openid-configuration",
          "listenAddress": ":10000",
          "options": {
            "ssh": {
                "templateFile": "templates/certs/ssh/github.tpl"
            }
          }
        },
          ...
      ]
    }
          
          





Qual é o próximo



Adicionamos uma seção sobre modelos SSH à documentação que fornece mais detalhes sobre todos os parâmetros e variáveis.



Se você tiver alguma dúvida, não hesite em perguntar .



All Articles