Tech/OSS/Ansible

From lathama
< Tech‎ | OSS
Jump to navigation Jump to search

Bootstrapping Ansible

If the host you are trying to administer does not have Python then Ansible will not be useful. Just add Python via this bootstrap in your playbook site.yml. Remember to gather facts next after this so your playbook can rock and roll. --- - name: Ansible Bootstrapping Debian

 hosts: debian
 gather_facts: no
 tasks:
   - name: Ensure Python on Debian
     raw: which python || (apt -qq update && apt -qq install python)

Portable Ansible with Vault Security

So you want to develop a complex playbook and share it with a team. The team may or may not currently use Ansible. To ease usage for all try a portable setup starting with Documentation in a project directory. One issue is getting a root or sudo password for inventory items which we will cover with a per host example.

mkdir -p project/playbook/roles/base/tasks && cd project/playbook && touch README hosts.yml site.yml roles/base/tasks/main.yml
README
Portable Ansible and Playbook Howto

1. Create an Ansible Vault password file:
    1. $ echo "thepassword" > ~/.vault
2. In the project directory where this README is we will get Ansible 2.4 Stable branch
    1. $ git clone -b stable-2.4 --single-branch https://github.com/ansible/ansible.git ansible
    2. $ cd ansible
    3. $ source ./hacking/env-setup
3. We can run the playbook with the Ansible Vault
    1. $ ./bin/ansible-playbook --vault-id ~/.vault -e @../playbook/secret.yml -i ../playbook/hosts.yml ../playbook/site.yml
4. Enjoy
hosts.yml
all:
  children:
    group_a:
      hosts:
        host1.example.com
      vars:
        ansible_user: production
        ansible_become_pass: "{{ example_root_pass}}"
  vars:
    become: yes
    become_method: su
    become_user: root
</code>

;site.yml

<code lang="YAML">
---
- hosts: group_a
  roles:
    - base
secret.yml (./bin/ansible-vault edit --vault-id ~/.vault ../playbook/secret.yml)
---
example_root_pass: one2three4five6seven8nine10
app1password: qwertyuiop
shortkey: TF1DaAFxfeJ9zcVdE
roles/base/tasks/main.yml
---

- name: do stuffs
  apt:
    name: vlan
    state: latest

- name: install key
  copy:
    name: /root/.privatekey
    contents: {{ shortkey }}

Security tasks in Ansible to ban services

I was playing around and just wrote the following playbook task to keep people off of production hardware.

group_vars/all
banned_services:
  - screen
  - tmux
security.yml task
- name: Kill banned services
  shell: "pkill -f {{ item }}"
  with_items: "{{ banned_services }}"
  ignore_errors: yes
  changed_when: False
  failed_when: False

Which will run pkill against a list of names which is both dangerous and effective at the same time. This will look like:

TASK [common : Kill banned services] **********************************
ok: [192.168.15.12] => (item=screen)
ok: [192.168.15.13] => (item=screen)
ok: [192.168.15.11] => (item=screen)
ok: [192.168.15.12] => (item=tmux)
ok: [192.168.15.11] => (item=tmux)
ok: [192.168.15.13] => (item=tmux)

Which should be all green and evil at the same time.

Ansible task for libvirt setup

Playing with some libvirt stuffs and setup a quick task to get my HVM nodes working the way I want. Will update with some fine tuning over time.

---

- name: HVM Packages to install 
  apt: 
    name: "{{ item }}"
    state: latest
  with_items:
    - qemu-kvm
    - libvirt-clients 
    - libvirt-daemon-system

- name: Add user to group
  user:
    name: hvm
    groups: libvirt-qemu,libvirt
    append: yes

Docker on Debian

  # System might not be ready yet so check
  - name: Wait for SSH to come up
    wait_for_connection:
      delay: 5

  # Basic packages
  - name: Basic Packages to install 
    apt: 
      name: ["apt-transport-https", "unzip"]
      update_cache: yes

  # Upgrade all packages
  - name: Upgrade all packages to the latest version
    command: "apt-get -qq upgrade"
    changed_when: False

  # Use Docker repo as upstream, install their key
  - name: Docker Repo Signing key
    apt_key:
      url: https://download.docker.com/linux/debian/gpg
      state: present

  # Setup repo for upstream Docker
  - name: Docker Repo Setup
    apt_repository:
      repo: "deb https://download.docker.com/linux/debian/ stretch stable"
      state: present

  # With docker.com as upstream install packages.
  # Docker Compose installs Python tooling
  - name: install docker
    apt:
      name: ["docker-ce", "docker-compose"]
      update_cache: yes

One Liners

Example from a local ansible source tree without using any install to run adhoc commands

Assume key works

$ ansible all -i 192.168.15.11, -a "uname -a"
192.168.15.11 | SUCCESS | rc=0 >>
Linux nodeone 3.16.0-4-amd64 #1 SMP Debian 3.16.39-1 (2016-12-30) x86_64 GNU/Linux

Set key

$ ansible all -i 192.168.15.11, -a "uname -a" --private-key=~/.ssh/id_rsa
192.168.15.11 | SUCCESS | rc=0 >>
Linux nodeone 3.16.0-4-amd64 #1 SMP Debian 3.16.39-1 (2016-12-30) x86_64 GNU/Linux

whoami

$ ansible all -i 192.168.15.11, -a "whoami" --private-key=~/.ssh/id_rsa
192.168.15.11 | SUCCESS | rc=0 >>
lathama

become root via su

$ ansible all -i 192.168.15.11, --private-key=~/.ssh/id_rsa -b --become-method=su -K -a "whoami"
SU password: 
192.168.15.11 | SUCCESS | rc=0 >>
root

Setting up EC2 on Amazon Web Services AWS example


- name: Spin up EC2
  hosts: localhost
  connection: local
  gather_facts: false
  vars:
     ec2_size: t2.micro
     ec2_image: ami-0ef798b78daa90ad3 # Debian Stable
     ec2_count: 1
     ec2_group: demo
     aws_region: us-west-2

  tasks:
  # AWS specific config for SSH keys
  - name: SSH key pair
    ec2_key:
      name: ski_keys
      aws_access_key: "{{ aws_access_key }}"
      aws_secret_key: "{{ aws_secret_key }}"
      region: "{{ aws_region }}"
      key_material: "{{ ssh_key }}"

  # AWS specific config for firewall rules - lack of IPv6 by default
  - name: Security Group
    ec2_group:
      name: "{{ ec2_group }}"
      description: "{{ ec2_group }}"
      aws_access_key: "{{ aws_access_key }}"
      aws_secret_key: "{{ aws_secret_key }}"
      region: "{{ aws_region }}"
      state: present
      purge_rules: true
      purge_rules_egress: true
      rules:
        - proto: tcp
          ports: 80
          cidr_ip: 0.0.0.0/0
          rule_desc: HTTP
        - proto: tcp
          from_port: 22
          to_port: 22
          cidr_ip: 0.0.0.0/0
          rule_desc: SSH
      rules_egress:
        - proto: all
          cidr_ip: 0.0.0.0/0
          rule_desc: Allow All

  # Inspect existing inventory for tag
  - name: Check Instances
    ec2_instance_facts:
      aws_access_key: "{{ aws_access_key }}"
      aws_secret_key: "{{ aws_secret_key }}"
      region: '{{ aws_region }}'
      filters:
        "tag:Name": demo
    register: ec2_facts

  # If it exists and is stopped, start it
  - name: If it exists and is stopped, start it
    ec2:
      instance_ids: '{{ ec2_facts.instances[0].instance_id }}'
      aws_access_key: "{{ aws_access_key }}"
      aws_secret_key: "{{ aws_secret_key }}"
      region: '{{ aws_region }}'
      state: running
      wait: True
    register: ec2_instances
    when: ec2_facts.instances[0].instance_id is defined

  # AWS specific node startup - need wrapper for various states
  - name: Setup Instance
    ec2:
      id: demo
      instance_tags:
        Name: skigame
      key_name: ski_keys
      aws_access_key: "{{ aws_access_key }}"
      aws_secret_key: "{{ aws_secret_key }}"
      region: "{{ aws_region }}"
      instance_type: "{{ ec2_size }}"
      image: "{{ ec2_image }}"
      group: "{{ ec2_group }}"
      count: "{{ ec2_count }}"
      wait: yes
    register: ec2_instances
    no_log: True

  # Register created hosts in dynamic inventory
  - name: Add hosts
    add_host:
      hostname: "{{ item.public_ip }}"
      groupname: aws
      ansible_user: admin
    with_items: "{{ ec2_instances.instances }}"
    changed_when: False