如何ssh作为myuser,但在/ home / deployuser中以deployuser身份运行所有Capistrano命令

问题描述 投票:3回答:1

背景/问题

由于安全配置,我绝对不能改变,我必须在我的所有盒子ssh一个联邦用户,myuser

我需要部署的盒子上的所有东西都归deployuser所有,我绝对不能改变它。

myuser可以假设用户deployuser并拥有所有sudo权限。

最终,我希望我的Capistrano部署功能就好像我从一开始就以deployuser的形式进行操作,因此每个命令都以deployuser/home/deployuser运行。

我可以使用我想要的任何版本的Capistrano,但是现在我正在尝试使用Capistrano 3。

测试设置

我创建了一个简单的Capistrano任务来测试我是否可以对我知道由deployuser拥有的文件执行操作。

desc "Check that we can access everything"
task :check_permissions do
  on roles(:all) do |host|
    execute("whoami")
    execute("cp /tmp/file-owned-by-deploy-user /tmp/test-file")
  end
end

编辑:上面的测试实际上并没有像人们预期的那样工作。我相信这是因为当你手动声明像execute('command')这样的东西时,它会覆盖任何说“以X用户身份做这件事”的配置。更好的测试是运行你的cap environment deploy任务,看看失败了什么。

我试过的

sshkit-backends-netssh_global as per their docs

我尝试的第一件事是sshkit-backends-netssh_global,在他们的文档中说他们正好处理这个用例。

我将其添加到我的Capfile中,然后尝试将其添加到deploy.rb,然后甚至高于我的任务定义以防万一:

require 'sshkit/backends/netssh_global'

SSHKit::Backend::NetsshGlobal.configure do |config|
  config.owner        = 'deployuser'
  config.directory    = '/home/deployuser'
end

这无论如何都有效果。没有新的错误消息,只有相同的权限被拒绝,而whoami返回myuser。

Setting :sshkit_backend in Capistrano 3

其次,我试图设置卡兹斯特拉诺的:ssh_backend,我在this issue for sshkit-backends-netssh_global看到:

require 'sshkit/backends/netssh_global'

set :sshkit_backend, -> {
  SSHKit::Backend::NetsshGlobal.tap do |backend|
    backend.configure do |config|
      config.owner        = 'deployuser'
      config.directory    = '/home/deployuser'
    end
  end
}

这表明sshkit-backends-netssh_global不再与最新版本的Capistrano兼容。它使用了一种弃用的方法checkout。太讨厌了:

NoMethodError: undefined method `checkout' for #<SSHKit::Backend::ConnectionPool:0x007fae8340e3c0>

我尝试降级到较低版本的Capistrano,虽然这修复了弃用问题,但它并没有神奇地使这些配置设置生效。虽然我没有深入挖掘。

Using as 'deployuser' from SSHKit to test

我觉得我在这里疯了,因为当我尝试按照SSHKit documentation将我的任务包装为'用户'时,whoamideployuser运行,而cp命令仍然返回Permission Denied。

所以也许我的测试脚本没有做我认为它正在做的事情。仍然可以将此命令复制/粘贴到服务器上,并通过附加sudo -u deployuser来运行。

在我上面的编辑中,我说这是因为我认为做一个execute('command')有点不同,并没有考虑你的配置 - 它只是执行的东西。我认为。所以这可能仍适用于其他类型的任务(当然不是内部的Capistrano任务)。

desc "Check that we can access everything"
task :check_permissions do
  on roles(:all) do
    as 'deployuser' do
      # this returns deployuser
      execute("whoami")

      # this throws permission denied
      execute("cp /tmp/file-owned-by-deploy-user /tmp/test-file")
    end
  end
end

Using SSHKit.config.command_map

我尝试的另一种策略,与上面的例子相同,是:

SSHKit.config.command_map = Hash.new do |hash, command|
  hash[command] = "sudo -u deployuser #{command}"
end

whoami返回deployuser,但cp命令仍然返回Permission Denied。同样,这可能是因为execute实际上并不是我需要在这里测试的。

相关但未解决的Stackoverflow问题

一些相关问题

有没有人得到这个工作?有任何想法吗?

编辑:有点工作的东西(ish)

我一整天都在努力,这就是我到目前为止所做的......而且这很糟糕,但我得到了一个基本的部署工作。

首先,虽然你大部分都希望将sudo -u deployuser附加到命令,但对于所有命令都不是这样。我最初在这里有几个人,但我把它归结为chmod不能作为我的deployuser运行

SSHKit.config.command_map = Hash.new do |hash, command|
  skipped_commands = [:chmod]

  if skipped_commands.include?(command)
    hash[command] = command
  else
    hash[command] = "sudo -u deployuser #{command}"
  end
end

好吧那么我意识到这对所有Capistrano案件都不适用,因为这些>>被插入Capistrano方面的几个rake任务中。

所以我为这两个任务写了一个猴子补丁:

namespace:deploy do

  # MONKEY PATCH OH NO
  # =======================

  # you actually have to clear the old rake task 
  # for yours to overwrite Capistrano's
  Rake::Task['deploy:set_current_revision'].clear
  desc "IT'S MINE"
  task :set_current_revision  do
    on release_roles(:all) do
      within release_path do
        execute :echo, "\"$(sudo -u deployuser git rev-parse HEAD)\" | sudo -u deployuser tee REVISION"
      end
    end
  end

  Rake::Task['deploy:log_revision'].clear
  desc "Log details of the depl
  task :log_revision do
    on release_roles(:all) do
      within releases_path do
        execute :echo, %Q{"#{revision_log_message}" | sudo -u deployuser tee #{revision_log}}
      end
    end
  end
end

正在进行调查(我仍然需要实施部署的其余部分),但是在这些变化之后,现在正在完成一个简单的cap test_environment deploy

另外,这是我未来发现的人的捆绑包:

Gems included by the bundle:
  * activesupport (4.2.10)
  * airbrussh (1.3.0)
  * aws-partitions (1.56.0)
  * aws-sdk-core (3.14.0)
  * aws-sdk-ec2 (1.25.0)
  * aws-sigv4 (1.0.2)
  * bundler (1.16.0)
  * capistrano (3.10.1)
  * capistrano-bundler (1.3.0)
  * capistrano-rails (1.3.1)
  * coderay (1.1.2)
  * concurrent-ruby (1.0.5)
  * dogapi (1.28.0)
  * faraday (0.14.0)
  * i18n (0.9.3)
  * jmespath (1.3.1)
  * json (1.8.6)
  * method_source (0.9.0)
  * minitest (5.11.1)
  * multi_json (1.13.1)
  * multipart-post (2.0.0)
  * net-scp (1.2.1)
  * net-ssh (4.2.0)
  * pry (0.11.3)
  * rake (12.3.0)
  * slackbot (0.0.2)
  * sshkit (1.15.1)
  * sshkit-backends-netssh_global (0.1.1)
  * thread_safe (0.3.6)
  * tzinfo (1.2.4)

再次编辑!

昨天原始插件posted this patch的作者在Capistrano 3.10中为我工作,没有任何猴子补丁。

ruby-on-rails ssh capistrano capistrano3
1个回答
0
投票

我不是capistrano用户,但是您可以使用OpenSSH功能来实现此目的。假设:

  1. Capistrano正在连接到远程系统上的OpenSSH ssh服务器。
  2. 正在使用ssh密钥对ssh会话进行身份验证
  3. 你可以改变远程ssh配置(特别是myuser authorized_keys文件)

如果假设为真,则每个远程系统上的myuser都有一个.ssh / authorized_keys文件,其中包含capistrano用于进行身份验证的公钥。您可以向该行添加一个指令,该指令强制ssh服务器在使用该密钥时运行硬编码命令,而不是远程客户端请求的命令。这允许您为请求的命令插入自己的处理程序。

处理程序可以是一个简单的shell脚本。这是未经测试但你应该明白:

#!/bin/sh
sudo -u deployuser $SSH_ORIGINAL_COMMAND

将其存储在远程系统上的文件中,使其可执行,并将其设置为在authorized_keys文件中运行的命令。当ssh服务器代表远程客户端调用此命令时,它会将SSH_ORIGINAL_COMMAND环境变量设置为远程客户端请求的命令字符串。

authorized_keys文件描述为here。基本上,文件的每一行都指定了一个可用于进行身份验证的密钥。一行看起来像这样:

ssh-rsa AAAAB3NzaC1yc2EAA...

你可以在行前加一个command=指令:

command=/home/myuser/run-as-deployuser ssh-rsa AAAAB3NzaC1yc2EAA...

当此密钥用于身份验证时,ssh服务器将调用请求的命令,而不是调用客户端请求的任何命令。正如我之前所说,SSH_ORIGINAL_COMMAND环境变量将被设置为客户端请求的命令。

© www.soinside.com 2019 - 2024. All rights reserved.