Skip to content

Instantly share code, notes, and snippets.

@artburkart
Last active August 13, 2018 21:33
Show Gist options
  • Save artburkart/8b8894ef8973fab34773a1a311f9f19a to your computer and use it in GitHub Desktop.
Save artburkart/8b8894ef8973fab34773a1a311f9f19a to your computer and use it in GitHub Desktop.
Ansible scripts to install & run CodeDeploy not as unprivileged user on Ubuntu
---
- name: Update apt cache
apt: update_cache=yes
- name: Install Ruby
apt: pkg=ruby2.0 state=present
- block:
- name: Get CodeDeploy version
set_fact:
current_codedeploy_version: "{{ lookup('file', '/opt/codedeploy-agent/.version') }}"
become: yes
rescue:
- name: Set CodeDeploy version to something bogus
set_fact:
current_codedeploy_version: "agent_version: OFFICIAL_something_bogus"
- block:
- name: Try to stop codedeploy-agent (since it should be re-installed)
service: name=codedeploy-agent state=stopped
ignore_errors: yes
- name: Download CodeDeploy package
get_url:
url: "{{ codedeploy_bucket }}/{{ codedeploy_pkg_name }}"
dest: /tmp/{{ codedeploy_pkg_name }}
mode: 0755
- name: Unarchive CodeDeploy package
command: dpkg -x /tmp/{{ codedeploy_pkg_name }} /tmp/codedeploy
# NOTE(arthurb): I know I could've used the codedeploy_pkg_name variable,
# but http://www.independent.co.uk/life-style/gadgets-and-tech/news/man-accidentally-deletes-his-entire-company-with-one-line-of-bad-code-a6984256.html
# ...of course, it was a hoax
- name: Delete CodeDeploy package
file:
state: absent
path: /tmp/codedeploy-agent_{{ codedeploy_version }}_all.deb
# NOTE(arthurb): If you wanted to make this script user-agnostic,
# then you'd need to replace each occurrence of `www-data` with
# something that looks like "{{ custom_username }}"
- name: Replace text to start CodeDeploy as www-data
replace:
dest: /tmp/codedeploy/etc/init.d/codedeploy-agent
regexp: '(^\s*)(nohup \$BIN.*2>&1)'
replace: '\1sudo -H -u www-data bash -c "\2"'
- name: Change default deployment directory
replace:
dest: /tmp/codedeploy/etc/codedeploy-agent/conf/codedeployagent.yml
regexp: ":root_dir: '/opt/codedeploy-agent/deployment-root'"
replace: ":root_dir: '{{ codedeploy_deployment_dir }}'"
- name: Make codedeploy-agent code executable
file:
owner: root
group: root
mode: 0755
path: /tmp/codedeploy/opt/codedeploy-agent/bin/codedeploy-agent
- name: Make codedeploy-agent logging directory
file:
owner: www-data
group: www-data
state: directory
path: "{{ item }}"
with_items:
- /var/log/aws/codedeploy-agent
- /tmp/codedeploy/opt/codedeploy-agent/lib
- /tmp/codedeploy/opt/codedeploy-agent/vendor
- /tmp/codedeploy/opt/codedeploy-agent/state
- name: Sync CodeDeploy directory to /
synchronize:
src: /tmp/codedeploy/
dest: /
owner: yes
group: yes
delegate_to: "{{ inventory_hostname }}"
- name: Remove old update-rc.d entries for codedeploy-agent
command: update-rc.d -f codedeploy-agent remove
- name: Set update rcd
command: update-rc.d codedeploy-agent defaults 71 20
- name: Start codedeploy-agent
service: name=codedeploy-agent state=restarted
when: ("{{ current_codedeploy_version }}" != "{{ codedeploy_version_check }}")
become: true
become_user: root
---
codedeploy_version: 1.0-1.950
codedeploy_bucket: https://aws-codedeploy-us-east-1.s3.amazonaws.com/releases
codedeploy_pkg_name: codedeploy-agent_{{ codedeploy_version }}_all.deb
codedeploy_version_check: "agent_version: OFFICIAL_{{ codedeploy_version }}_deb"
codedeploy_deployment_dir: /tmp/codedeploy-deployments
@artburkart
Copy link
Author

I've tested this script with the following CodeDeploy agent versions:

2016-06-21 16:40:46    1889802 codedeploy-agent_1.0-1.950_all.deb
2016-05-31 15:55:49    1933766 codedeploy-agent_1.0-1.966_all.deb

In 950, the following Ansible block was necessary:

  - name: Replace text to start CodeDeploy as www-data
    replace:
      dest: /tmp/codedeploy/etc/init.d/codedeploy-agent
      regexp: '(^\s*)(nohup \$BIN.*2>&1)'
      replace: '\1sudo -H -u www-data bash -c "\2"'

But in version 966, they added a line to enable running not as root:

start() {
        echo -n $"Starting $prog:"
        cd $AGENT_ROOT
        if [ $USER ]; then
          nohup sudo -i -u $USER $BIN start >/dev/null </dev/null 2>&1 # Try to start the server
        else
          nohup $BIN start >/dev/null </dev/null 2>&1  # Try to start the server
        fi
        exit $?
}

Unfortunately, it's a little presumptive in that it executes the script with sudo -i which means:

     -i, --login
                 Run the shell specified by the target user's password database entry as a login shell.

In my case, I was using www-data with nologin, so their update doesn't work for my use case. As such, I didn't update the replace portion of the Ansible script. Instead, the init script looks similar to the 950 version:

start() {
        echo -n $"Starting $prog:"
        cd $AGENT_ROOT
        if [ $USER ]; then
          nohup sudo -i -u $USER $BIN start >/dev/null </dev/null 2>&1 # Try to start the server
        else
          sudo -H -u www-data bash -c "nohup $BIN start >/dev/null </dev/null 2>&1"  # Try to start the server
        fi
        exit $?
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment