O ssh-under-cron para de funcionar no OS X 10.7 Lion

12

Acabei de atualizar do Snow Leopard para o Lion e meus trabalhos do cron que usam ssh pararam de funcionar. Parece que o ssh-agent não está mais funcionando conforme o esperado.

Aqui está uma versão reduzida do meu script chamado from-cron que funcionou muito bem no Snow Leopard:

#!/bin/bash
whoami # just to verify I'm running as myself, not root
ssh-agent # just to see what it outputs    
eval `ssh-agent`
ssh -vvv REMOTESERVER ls

Quando executado no prompt de comando, esse script funciona conforme o esperado.

Quando executado a partir do cron, ele não funciona. A saída do ssh-agent parece normal:

SSH_AUTH_SOCK=/tmp/ssh-QRxPUMRxbu/agent.17147; export SSH_AUTH_SOCK;
SSH_AGENT_PID=17148; export SSH_AGENT_PID;
echo Agent pid 17148;
Agent pid 17150

Mas a ssh -vvvsaída mostra que falha exatamente quando a chave privada deve ser lida:

debug1: Server accepts key: pkalg ssh-dss blen 818
debug2: input_userauth_pk_ok: fp ...
debug3: sign_and_send_pubkey: DSA ...
debug1: PEM_read_PrivateKey failed
debug1: read PEM private key done: type <unknown>
debug1: read_passphrase: can't open /dev/tty: Device not configured
debug2: no passphrase given, try next key

Em outras palavras, ele espera que eu digite a senha para ~/.ssh/id_dsa, a qual, obviamente, não funciona nos trabalhos do cron.

Tudo isso funcionou no Snow Leopard.

Observe que eu tenho a configuração do Keychain Access para que ssh, ssh-agente ssh-addpossa ler minha frase secreta para o meu .ssh/id_dsaarquivo - como resultado, eu posso fazer o SSH a partir de um prompt do terminal sem precisar digitar minha senha.

É esse problema que eu preciso executar ssh-addem algum momento do meu processo de login? Executá-lo a partir de um prompt padrão do bash não ajuda no trabalho do cron (embora, estranhamente, ele me solicite minha frase secreta ... o que eu consideraria desnecessário devido à configuração do Keychain Access).

NOTA 1 - antes de me redirecionar - estou ciente de que existe uma pergunta semelhante aqui ( Mac OS X Lion e sshpass ), mas trata-se especificamente de um programa sshpassque não uso (embora acredite que essa pergunta também seja respondida por essa) )

NOTA 2 - Percebo que as chaves SSH sem frase secreta resolveriam meu problema; no entanto, prefiro não seguir esse caminho.

John Hart
fonte
2
cron se foi. Veja a tag launchd aqui para todos os tipos de ajuda (faça a mudança - ela lida com portas, ambiente e muito mais do que o cron já fez) - espero que alguém tenha uma solução, mas o cron mojo aqui está envelhecendo por certo .
bmike
3
O cron ainda roda no Lion ... mas você está certo, eu devo fazer a mudança. Um arquivo XML com mais de 10 linhas para executar o trabalho de uma única LINHA do crontab é bastante complicado. Talvez em 10 anos eles mudem os arquivos plist para JSON, e haverá muita alegria, e 10 anos depois eles voltarão ao crontab, e os barbudos do BSD rirão. Acho que vou ser um greybeard BSD pelo então ...
John Hart
1
Apenas mudou para launchd, funciona um encanto. O script chamado não precisa interagir com o ssh-agent - você pode simplesmente pular diretamente para o comando ssh após o hashbang. Se o seu comentário fosse uma resposta, eu iria aceitá-lo =)
John Hart
O JSON certamente brilha sobre o XML em muitos casos, mas todas as sugestões que vieram antes provavelmente forçaram o problema. Estou agradado por termos uma substituição unificada, eficiente e estruturada baseada em dados. cron e com certeza nos serviu bem por muito tempo!
bmike
Eu tenho pesquisado alto e baixo por recursos adicionais da Web, mas sempre acabo retornando a esta postagem. Certamente alguém tem mais a contribuir para a discussão? Tentei usar um plist simples para executar meu shell script, mas o mailx não envia minhas notificações. Eu ainda gosto do cron e o uso no Ubuntu o tempo todo. Não quero voltar para a versão 10.6, mas esse problema está me matando. Eu não gosto de ser forçado a usar o launchctl e ter que aprender o que me parece uma estrutura muito expansiva para basicamente automatizar scripts de shell. Alguém tem novas idéias?

Respostas:

10

Para quem acaba nesta página, percebi que deveria postar a resposta:

Usar o launchd em vez do cron realmente corrige o problema de autorização. Os trabalhos de inicialização do usuário (que são executados apenas quando você está conectado) usam corretamente as informações do agente SSH que foram desbloqueadas através do seu chaveiro como parte do login (como parte do gerenciamento de chaves padrão do OS X, nenhum outro software é necessário).

Para minimizar minhas interações com o launchd, criei um único trabalho launchd que chama um script bash. Dessa forma, eu posso simplesmente editar o script sem lidar com o launchd.

Aqui está o arquivo launchd:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.mycron.hourly</string>

  <key>ProgramArguments</key>
  <array>
    <string>/Users/john/bin/cron.hourly</string>
  </array>

  <key>Nice</key>
  <integer>1</integer>

  <key>StartInterval</key>
  <integer>3600</integer> <!-- start every X seconds -->

  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

Salvei o arquivo ~/Library/LaunchAgents/com.mycron.hourly.pliste carreguei-o com:

launchctl load ~/Library/LaunchAgents/com.mycron.hourly.plist

Uma vez carregado, ele será executado imediatamente e novamente a cada 60 minutos.

Se você seguir o mesmo procedimento, altere a string `ProgramArguments 'pelo caminho certo para o seu script.

John Hart
fonte
2
De fato, o cron está obsoleto pelo menos no Lion. Parabéns por encontrar a resposta - pode ser difícil entrar no launchctl inicialmente.
Zwerdlds 23/07/12
7

Adicionar o seguinte código ao script shell bash corrigirá o problema:

declare -x SSH_AUTH_SOCK=$( find /tmp/launch-*/Listeners -user your_user -type s | head -1 )

Substitua your_userpor seu próprio nome de usuário.

Este código define o valor correto para SSH_AUTH_SOCKque informa sshou scpsobre como se comunicar com ssh-agentquando o shell script é iniciado fora do cron.

Werner Antweiler
fonte
Isso resolveu o problema que eu estava tendo, onde o scp não funcionava via launchd em um shell script, apesar de funcionar bem na linha de comando regular (iTerm ou Terminal). Excelente dica.
TJ Luoma #
Apenas para constar, no El Captain 10.11.2:zsh: no matches found: /tmp/launch-*/Listeners
Ivan Balashov
1

Eu esperaria que a segurança aprimorada, como a sandbox e as alterações para mudar ainda mais as coisas para 64 bits, esteja causando sofrimento inesperado.

Não é uma resposta, por si só, mas o launchd está recebendo todo o amor da apple nos dias de hoje.

Não está corrigindo o problema do cron, mas é mais estável e mais pessoas podem ajudá-lo.

bmike
fonte
Resposta muito boa . Obrigado por publicá-lo.
Bmike
1

Para qualquer um que encontre isso agora, tentando fazer isso funcionar em El Capitan, e ainda relutante em transformar seu trabalho cron de uma linha em um script launchd, a resposta de Werner Antweiler ainda funciona, mas o caminho mudou. O abaixo funcionou para mim:

declare -x SSH_AUTH_SOCK=$(find /var/folders/*/*/*/*/agent.* -user your_user -type s | head -1)

NOTA : lembre-se de substituir seu_usuário por seu nome de usuário!

Não me deixaria enviar isso como um comentário sobre a resposta dele, pois não tenho reputação, mas não queria deixá-la sem atualizar isso, pois definitivamente me ajudou a finalmente configurá-lo.

Edit: 30 de março de 2016

Depois de testar isso por um tempo, preciso acrescentar que isso só funciona quando o agente tiver sido usado pelo menos uma vez durante o login. Iniciar uma conexão ssh ou executar manualmente o ssh-agent é suficiente para fazê-lo. Um script de inicialização também pode ser usado se você desejar que seja executado automaticamente. Criei um startup.sh que apenas executa o ssh-agent e, em seguida, usei o Editor de scripts para salvar um .app com o seguinte e adicionei o aplicativo resultante aos meus itens de login:

do shell script "/path/to/startup.sh"
Petie
fonte
Estou resolvendo isso agora, e esse não é o melhor caminho. O launchd aparentemente é o caminho a seguir, mas para o cron, você deseja configurar sua chave ssh (com senha) em seu chaveiro. Depois de fazer isso, basta fazer login no Mac para configurar tudo. O caminho do soquete que você postou é onde eles são mantidos se você executar o ssh-agent manualmente (e digitar sua senha manualmente). No El Cap, depois que o chaveiro é carregado, encontre o soquete via ls /private/tmp/com.apple.launchd.*/Listeners. Você não precisa fazer nada, exceto fazer login no mac.
joe
O launchd é definitivamente a maneira "oficial" de fazer isso, mas para aqueles que desejam continuar usando o cron, isso serve como uma solução alternativa viável. Nos meus testes, o simples login não era suficiente para fazer com que uma chave salva de chave funcionasse via cron. O caminho que você listou definitivamente existe. Se isso for gerado assim que você efetuar login e ainda funcionar no cron, provavelmente será suficiente para ignorar o método de script de inicialização que listei. Certamente vale a pena testar pelo menos - obrigado!
Petie 14/05
Coloquei isso no lugar de um processo de backup, e ele está sendo executado de forma limpa - em todas as reinicializações - há mais de uma semana.
joe