21 Oct 2016
We don’t use root directly in ansible in most cases. Instead, we prefer a common user to execute some tasks in sudo mode. By doing so, we can keep the security.
Let’s make an example, we try to manage tomcat init script by using ansible become
# on ansible control node useradd opsuser su - opsuser # on controled node useradd opsuser
实际上控制端不需要有opsuser这个用户而使用root也可以,但是为了模仿线上环境,我们同样创建一个opsuser用户
--- - hosts: test-host remote_user: opsuser become: true become_user: root become_method: sudo tasks: - name: start tomcat1 service: name=tomcat1 state=started ---
but we met an error when run it directly(run below command by opsuser user)
ansible-playbook -i hosts main.yml PLAY [my_web] *************************************************************** TASK [setup] ******************************************************************* fatal: [192.168.100.22]: FAILED! => {"changed": false, "failed": true, "module_stderr": "", "module_stdout": "sudo: a password is required\r\n", "msg": "MODULE FAILURE"} NO MORE HOSTS LEFT ************************************************************* to retry, use: --limit @/home/opsuser/ansible-test/main.retry PLAY RECAP ********************************************************************* 192.168.100.22 : ok=0 changed=0 unreachable=0 failed=1
we try it one more time in debug mode to check detail
ansible-playbook -i hosts main.yml -vvvv No config file found; using defaults Loaded callback default of type stdout, v2.0 PLAYBOOK: main.yml ************************************************************* 1 plays in main.yml PLAY [my_web] *************************************************************** TASK [setup] ******************************************************************* <192.168.100.22> ESTABLISH SSH CONNECTION FOR USER: opsuser <192.168.100.22> SSH: EXEC ssh -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=opsuser -o ConnectTimeout=10 -o ControlPath=/home/opsuser/.ansible/cp/ansible-ssh-%h-%p-%r 192.168.100.22 '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1477056354.81-98638790861511 `" && echo ansible-tmp-1477056354.81-98638790861511="` echo $HOME/.ansible/tmp/ansible-tmp-1477056354.81-98638790861511 `" ) && sleep 0'"'"'' <192.168.100.22> PUT /tmp/tmpeK7ikg TO /home/opsuser/.ansible/tmp/ansible-tmp-1477056354.81-98638790861511/setup <192.168.100.22> SSH: EXEC sftp -b - -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=opsuser -o ConnectTimeout=10 -o ControlPath=/home/opsuser/.ansible/cp/ansible-ssh-%h-%p-%r '[103.236.220.177]' <192.168.100.22> ESTABLISH SSH CONNECTION FOR USER: opsuser <192.168.100.22> SSH: EXEC ssh -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=opsuser -o ConnectTimeout=10 -o ControlPath=/home/opsuser/.ansible/cp/ansible-ssh-%h-%p-%r 103.236.220.177 '/bin/sh -c '"'"'chmod u+x /home/opsuser/.ansible/tmp/ansible-tmp-1477056354.81-98638790861511/ /home/opsuser/.ansible/tmp/ansible-tmp-1477056354.81-98638790861511/setup && sleep 0'"'"'' <192.168.100.22> ESTABLISH SSH CONNECTION FOR USER: opsuser <192.168.100.22> SSH: EXEC ssh -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=opsuser -o ConnectTimeout=10 -o ControlPath=/home/opsuser/.ansible/cp/ansible-ssh-%h-%p-%r -tt 192.168.100.22 '/bin/sh -c '"'"'sudo -H -S -n -u root /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-kzyiyadwuhlluevxdczpkcspfgwzyuhz; LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /home/opsuser/.ansible/tmp/ansible-tmp-1477056354.81-98638790861511/setup; rm -rf "/home/opsuser/.ansible/tmp/ansible-tmp-1477056354.81-98638790861511/" > /dev/null 2>&1'"'"'"'"'"'"'"'"' && sleep 0'"'"'' fatal: [192.168.100.22]: FAILED! => {"changed": false, "failed": true, "invocation": {"module_name": "setup"}, "module_stderr": "OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug2: mux_client_hello_exchange: master version 4\r\ndebug3: mux_client_request_forwards: requesting forwardings: 0 local, 0 remote\r\ndebug3: mux_client_request_session: entering\r\ndebug3: mux_client_request_alive: entering\r\ndebug3: mux_client_request_alive: done pid = 16619\r\ndebug3: mux_client_request_session: session request sent\r\ndebug1: mux_client_request_session: master session id: 2\r\ndebug1: mux_client_request_session: master session id: 2\r\ndebug3: mux_client_read_packet: read header failed: Broken pipe\r\ndebug2: Received exit status from master 1\r\nShared connection to 192.168.100.22 closed.\r\n", "module_stdout": "sudo: a password is required\r\n", "msg": "MODULE FAILURE"} NO MORE HOSTS LEFT ************************************************************* to retry, use: --limit @/home/opsuser/ansible-test/main.retry PLAY RECAP ********************************************************************* 192.168.100.22 : ok=0 changed=0 unreachable=0 failed=1 # we can see it that ansible have tried to run "service, sh, python" command # so we can fix it by grant permission of these command to opsuser
configure sudoer on test-host to solve it
# on test-host node visudo *************************** # add the content below to grant service command permission to opsuser # and we don't want to input password when running ansible tasks, so we set "NOPASSWD" opsuser ALL=(root) NOPASSWD: /sbin/service,/bin/sh,/usr/bin/python *************************** # try run ansible again ansible-playbook -i hosts main.yml PLAY [my_web] *************************************************************** TASK [setup] ******************************************************************* ok: [192.168.100.22] TASK [restart tomcat] ********************************************************** changed: [192.168.100.22] PLAY RECAP ********************************************************************* 192.168.100.22 : ok=2 changed=1 unreachable=0 failed=0 # check tomcat status on test-host ps aux |grep java |grep tomcat1 root 9650 0.2 0.6 6386456 102912 ? Sl 20:59 0:04 /usr/local/jdk/bin/java -Djava.util.logging.config.file=/home/tomcat1/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -XX:PermSize=128m -XX:MaxPermSize=512m -Djava.endorsed.dirs=/home/tomcat1/endorsed -classpath /home/tomcat1/bin/bootstrap.jar -Dcatalina.base=/home/tomcat1 -Dcatalina.home=/home/tomcat1 -Djava.io.tmpdir=/home/tomcat1/temp org.apache.catalina.startup.Bootstrap start