SUSE安装SaltStack后的pam认证问题

来源:互联网 发布:和网络有关的英文单词 编辑:程序博客网 时间:2024/06/01 07:26

            最近项目需要在几个集群的机器上部署SaltStack,操作系统有SUSE11 SP3和SP4两个版本的。之前同事在centos的虚拟机上测试一路顺风顺水,没想到上SUSE遇到一堆坑。

 

            坑1:在SaltStack的官网上可以找到两个SUSE用的源,从Document- Installation - SUSE下找到的源是opensuse的(http://download.opensuse.org/repositories/systemsmanagement:/saltstack/SLE_11_SP4/systemsmanagement:saltstack.repo),版本为2016.3.3;而从Downloads- SUSE - SLES11下找到的源是saltstack的(http://repo.saltstack.com/opensuse/SLE_11_SP4/systemsmanagement:saltstack.repo),版本为2015.8.12。版本不一致让人疑惑,但坑不在这里,真正的坑是,不管用哪个源装都会少一些依赖,比如python-requests等几个rpm包,要找到匹配的版本还是花了一番功夫的,我找到的4个包如下,地址就不放了。这还不算大坑。

python-requests-2.4.1-30.1.x86_64.rpm

python-ordereddict-1.1-0.7.31.x86_64.rpm

ca-certificates-1-9.1.noarch.rpm

libffi43-4.3.4_20091019-0.37.28.x86_64.rpm

 

            除了salt,salt-master,salt-minion外,我还装了salt-api,因为需要一个restful的API供外部调用。装完以后,还需要配置外部认证供salt-api使用(https://docs.saltstack.com/en/latest/topics/eauth/index.html),再新建一个操作系统帐号供api使用(我建的帐号为saltapi),无难度。全部配完,起salt-master和salt-api服务,显示OK,但是调用的时候来坑了。

 

            坑2:首先尝试用curl方式调用

curl -si localhost:8088/login -H"Accept:application/json" -H"Content-type:application/json" -d'{"username":"saltapi","password":"mypassword","eauth":"pam"}'

返回了一个401错误:

HTTP/1.1 401 UnauthorizedContent-Length: 1614Access-Control-Expose-Headers: GET, POSTVary: Accept-EncodingServer: CherryPy/3.6.0Allow: GET, HEAD, POSTAccess-Control-Allow-Credentials: trueDate: Sat, 15 Oct 2016 11:14:43 GMTAccess-Control-Allow-Origin: *Content-Type: text/html;charset=utf-8Set-Cookie: session_id=9f4c49f186ad3026386a43372d7b2e538d216397; expires=Sat, 15 Oct 2016 21:14:43 GMT; Path=/<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head>    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>    <title>401 Unauthorized</title>    <style type="text/css">    #powered_by {        margin-top: 20px;        border-top: 2px solid black;        font-style: italic;    }    #traceback {        color: red;    }    </style></head>    <body>        <h2>401 Unauthorized</h2>        <p>Could not authenticate using provided credentials</p>        <pre id="traceback">Traceback (most recent call last):  File "/usr/lib64/python2.6/site-packages/cherrypy/_cprequest.py", line 670, in respond    response.body = self.handler()  File "/usr/lib64/python2.6/site-packages/cherrypy/lib/encoding.py", line 217, in __call__    self.body = self.oldhandler(*args, **kwargs)  File "/usr/lib64/python2.6/site-packages/salt/netapi/rest_cherrypy/app.py", line 534, in hypermedia_handler    ret = cherrypy.serving.request._hypermedia_inner_handler(*args, **kwargs)  File "/usr/lib64/python2.6/site-packages/cherrypy/_cpdispatch.py", line 61, in __call__    return self.callable(*self.args, **self.kwargs)  File "/usr/lib64/python2.6/site-packages/salt/netapi/rest_cherrypy/app.py", line 1529, in POST    'Could not authenticate using provided credentials')HTTPError: (401, 'Could not authenticate using provided credentials')</pre>    <div id="powered_by">      <span>        Powered by <a href="http://www.cherrypy.org">CherryPy 3.6.0</a>      </span>    </div>    </body></html>


            心里觉得奇怪,该不会是salt-api没装好吧,毕竟有不少野地里淘来的rpm啊。于是决定用salt命令在master的本机调用:

salt -a pam "*" test.ping

            执行后会提示输入用户名和密码,输入saltapi帐号信息,依然是401错误。这下雷了。研究了一下salt的代码,pam认证都要过以下文件,编辑一下以便调试:

vi /usr/lib64/python2.6/site-packages/salt/auth/pam.py

            在179行加入:

print "retval after AUTHENTICATE:%s" % retval

            然后将salt-master服务停掉,在命令行前台起一个debug模式的salt-master,来看到底什么情况:

service salt-master stop

salt-master -l debug

            接下去就更雷了。在2015.8.12版本的机器上,执行到这里打印“retval after AUTHENTICATE: 10”,而在2016.3.3版本的机器上打印“retvalafter AUTHENTICATE: 7”。关于这个返回值的解释,可以看这个页面(http://pubs.opengroup.org/onlinepubs/8329799/chap5.htm)。其中,7代表PAM_PERM_DENIED,10代表PAM_NEW_AUTHTOK_REQD。我一开始在一台2015.8.12版本的虚拟机上调试,始终返回10,怀疑是PAM的token无法生成,翻遍了网上所有saltstack的文章都没有解决方案。由于当时已经到晚上11点了,困得要死,决定先作个弊,跑过去再说。于是再修改pam.py文件,将auth方法改为如下:

def auth(username, password, **kwargs):    ‘’’    Authenticate via pam    ‘’’    # return authenticate(username, password)    if username==’saltapi’ and password==’mypassword’:        return True    else:        return False

            作弊成功,果然跑通,拿到了通信的token。

 

            第二天起来以后,觉得不甘心,继续找原因,并且发现了2016.3.3版本下retval值为7,开始怀疑是权限问题。起初在/etc/pam.d/下找问题,无果。偶然之下cat /etc/shadow 了一下,发现一个奇怪的帐号:

salt:*:17089:0:99999:7:::

            于是恍然大悟,虽然servicesalt-master ***是用root帐号跑的,但进程未必是root起的,ps一下查看果然,salt-master都是salt帐号起的。而linux的/etc/shadow默认是只有root帐号能读的,于是:

setfacl -m u:salt:r /etc/shadow

            把昨天改的pam.py改回去,起salt-master服务,调用api拿token,成功!再深究一下,发现在/etc/salt/master下有以下一段:

# The user under which the salt master willrun. Salt will update all

# permissions to allow the specified userto run the master. The exception is

# the job cache, which must be deleted ifthis user is changed. If the

# modified files cause conflicts, setverify_env to False.

user: salt

syndic_user: salt

 

            结论是在SUSE环境下由于某些我不清楚的原因,saltstack安装时只是建了salt帐号,并没能正确修改权限,导致不能读取/etc/shadow,引发了奇怪的401错误。而在centos上是正确修改了的,所以没碰到问题。至于修改是在rpm的postscripts里,还是在salt-master起来后的代码里,没进一步深究,有空再更新。


1 0