我目前正在使用Chef在受管节点上部署Jenkins实例。我正在使用以下公共超市食谱:https://supermarket.chef.io/cookbooks/jenkins。
我在配方文件中使用以下代码来启用身份验证:
jenkins_script 'activate global security' do
command <<-EOH.gsub(/^ {4}/, '')
import jenkins.model.*
import hudson.security.*
def instance = Jenkins.getInstance()
def hudsonRealm = new HudsonPrivateSecurityRealm(false)
hudsonRealm.createAccount("Administrator","Password")
instance.setSecurityRealm(hudsonRealm)
instance.save()
def strategy = new GlobalMatrixAuthorizationStrategy()
strategy.add(Jenkins.ADMINISTER, "Administrator")
instance.setAuthorizationStrategy(strategy)
instance.save()
EOH
end
这非常适合在第一次在受管节点上运行配方时在实例上设置安全性。它在Jenkins服务器上创建具有管理员权限的管理员用户。除了在Jenkins实例上启用安全性之外,还使用此配方安装插件。
启用安全性后,安装尚未存在但已指定安装的插件失败:
ERROR: anonymous is missing the Overall/Read permission
我认为这是与新创建的管理员帐户相关的错误,而Chef尝试使用匿名用户而不是管理员用户安装插件。是否有任何应该在我的配方文件中设置以解决此权限问题?
此处的目标是,如果插件升级到不需要的版本或完全卸载,运行配方将重新安装/回滚任何插件更改。目前,如果我还在Jenkins实例上启用了安全性,这似乎是不可能的。
EDIT 还应该注意,目前每次我需要以这种方式修复插件时,我必须禁用安全性然后运行整个配方(插件安装+安全启用)。
感谢您的帮助!
答案 0 :(得分:0)
jenkins_plugin
资源似乎没有公开任何身份验证选项,因此您可能需要构建自己的资源。如果你深入研究代码,你会发现cookbook中的底层执行层确实支持auth(以及其他一些东西),所以在copy-fork中可能很容易(并向我们发送一个补丁)只是那个资源。
答案 1 :(得分:0)
我们之所以遇到这个问题,是因为我们之前曾定义过:jenkins_username
和:jenkins_password
,但是它们仅与remoting
协议一起使用,为了支持通过REST API访问而弃用了这些协议SSH或HTTPS以及更高版本中的默认值为DISABLED。
我们最终结合了@StephenKing食谱中的逻辑以及来自chef-cookbooks/jenkins和this GitHub issue comment on that repo的信息,以在通过实例上的Active Directory启用身份验证(我们使用SSH)后使插件安装正常工作。 / p>
我们基本上从https://github.com/TYPO3-cookbooks/jenkins-chefci/blob/e1b82e679074e96de5d6e668b0f10549c48b58d1/recipes/_jenkins_chef_user.rb中提取了该示例,并删除了如果不存在会自动生成密钥的部分(我们的实例仍然存在,并且大多需要确定性),然后用查找替换了File.read。在我们的加密数据包(或等效功能)中。
recipes / authentication.rb
require 'aws-sdk'
require 'net/ssh'
require 'openssl'
ssm = Aws::SSM::Client.new(region: 'us-west-2')
unless node.run_state[:jenkins_private_key]
key_contents = ssm.get_parameter(name: node['jenkins_wrapper']['secrets']['chefjenkins']['id_rsa']['path'], with_decryption: true).parameter.value
key_path = node['jenkins_wrapper']['secrets']['chefjenkins']['id_rsa']['path']
key = OpenSSL::PKey::RSA.new key_contents
# We use `log` here so we can assert the correct path was queried without exposing or hardcoding the secret in our tests
log 'Successfully read existing private key from ' + key_path
public_key = [key.ssh_type, [key.to_blob].pack('m0'), 'auto-generated key'].join(' ')
# Create the Chef Jenkins user with the public key
jenkins_user 'chefjenkins' do
id 'chefjenkins' # This also matches up with an Active Directory user
full_name 'Chef Client'
public_keys [public_key]
end
# Set the private key on the Jenkins executor
node.run_state[:jenkins_private_key] = key.to_pem
end
# This was our previous implementation that stopped working recently
# jenkins_password = ssm.get_parameter(name: node['jenkins_wrapper']['secrets']['chefjenkins']['path'], with_decryption: true).parameter.value
# node.run_state[:jenkins_username] = 'chefjenkins' # ~FC001
# node.run_state[:jenkins_password] = jenkins_password # ~FC001
recipes / enable_jenkins_sshd.rb
port = node['jenkins']['ssh']['port']
jenkins_script 'configure_sshd_access' do
command <<-EOH.gsub(/^ {4}/, '')
import jenkins.model.*
def instance = Jenkins.getInstance()
def sshd = instance.getDescriptor("org.jenkinsci.main.modules.sshd.SSHD")
def currentPort = sshd.getActualPort()
def expectedPort = #{port}
if (currentPort != expectedPort) {
sshd.setPort(expectedPort)
}
EOH
not_if "grep #{port} /var/lib/jenkins/org.jenkinsci.main.modules.sshd.SSHD.xml"
notifies :execute, 'jenkins_command[safe-restart]', :immediately
end
属性/default.rb
# Enable/disable SSHd.
# If the port is 0, Jenkins will serve SSHd on a random port
# If the port is > 0, Jenkins will serve SSHd on that port specifically
# If the port is is -1 turns off SSHd.
default['jenkins']['ssh']['port'] = 8222
# This happens to be our lookup path in AWS SSM, but
# this could be a local file on Jenkins or in databag or wherever
default['jenkins_wrapper']['secrets']['chefjenkins']['id_rsa']['path'] = 'jenkins_wrapper.users.chefjenkins.id_rsa'