VPNサーバー(SoftEhter)をAnsibleでConoha-VPNサーバーへ構築

Conoha API を使いVPN構築を簡略化 の備忘録

VPN サーバー(SoftEhter)を Ansible で Conoha-VPN サーバーへ構築

GitHub

inventory_file での host の指定を動的にしたい

ローカルの Docker 上でのテスト, Act(GitHub actions のローカル版)を利用してのテスト、本番デプロイにおいて inventory_file での host の指定を動的にしたい。

## vars-file for docker
mount_dir: '/softether'
project_name: 'Ansible-SoftEther-For-Conoha'
docker_server:
hosts:
  - host_ip: "127.0.0.1"
ssh_port: 2223
image_tag: "softether_server"
container_tag: "softether001"
container_ip: ""
dockerfile: "centos7"
inventory_name: "docker_server"
docker_client:
hosts:
  - host_ip: "127.0.0.1"
ssh_port: 2222
image_tag: "softether_client"
container_tag: "softether_client"
container_ip: ""
dockerfile: "ubuntu20.04"
inventory_name: "docker_client"
# Create inventory
hosts_text = ""
for i in range(len(docker_server["hosts"])):
    cname = str(docker_server["hosts"][i]["container_tag"])
    ip = str(docker_server["hosts"][i]["container_ip"])
    port = str(docker_server["hosts"][i]["ssh_port"])
    hosts_text += str(cname + " ansible_host=" + ip) + "n"
os.makedirs(pwd + "/hosts", exist_ok=True)
with open(
        pwd + "/hosts/" + docker_server["inventory_name"] + "_root", "w"
) as f:
    f.write(SOFTETHER_INVENTORY_FILE)
SOFTETHER_INVENTORY_FILE = (
    textwrap.dedent(
        """
[softether]
{hosts}
[softether:vars]
ansible_user={ansible_user}
ansible_port={ansible_ssh_port}
ansible_ssh_private_key_file={mount_dir}/roles/ansible_user/{key}\
"""
    )
        .format(
        hosts=hosts_text,
        ansible_user=self.vars_ansible_user["ansible_users"]["master"]["name"],
        ansible_ssh_port=self.vars_sshd["sshd_port"],
        mount_dir=self.vars_docker["mount_dir"],
        key=self.vars_ansible_user["ansible_users"]["master"]["secret_key"],
    )
        .strip()
)
os.makedirs(pwd + "/hosts", exist_ok=True)
with open(
        pwd + "/hosts/" + docker_server["inventory_name"] + "_user", "w"
) as f:
    f.write(SOFTETHER_INVENTORY_FILE)

nofity 設定反映するため Service を restart させる

Case in Firewalled

# roles/firewalled/handlers/main.yml
- name: Restart
  firewalld
become: yes
systemd:
state: restarted
name: firewalld
enabled: yes
- name: Open
  port
  by
  firewalld
become: yes
firewalld:
port: "{{ item.port }}"
permanent: "{{ item.permanent }}"
state: "{{ item.state }}"
with_items: "{{ firewalld_ports }}"
when: firewalld_ports is defined
notify: Restart
  firewalld  # <-  最終的にリスタートさせる

Use dict for vars and loop

#  dict で書くことにより
ansible_users:
master:
name: 'ansible'
groups: 'wheel'
append: 'yes'
state: 'present'
remove: 'no'
password: "{{ secret.ansible_user_password }}"
key: "files/ansible_rsa.pub"
secret_key: "files/ansible_rsa"
login_shell: '/bin/bash'
create_home: 'yes'
sudo: 'present'
comment: 'ansible user'
expires: '-1'
#  指定しやすくなる
.format(
    hosts=hosts_text,
    ansible_user=self.vars_ansible_user["ansible_users"]["master"]["name"],
    ansible_ssh_port=self.vars_sshd["sshd_port"],
    mount_dir=self.vars_docker["mount_dir"],
    key=self.vars_ansible_user["ansible_users"]["master"]["secret_key"],
)
.strip()
# playbook では with_dict を使い item.value.xxxになる
- name: user - control
become: true
user:
name: "{{ item.value.name }}"
groups: "{{ item.value.groups }}"
state: "{{ item.value.state }}"
remove: "{{ item.value.remove }}"
create_home: "{{ item.value.create_home }}"
password: "{{ item.value.password | password_hash('sha512') }}"
shell: "{{ item.value.login_shell }}"
comment: "{{ item.value.comment }}"
expires: "{{ item.value.expires }}"
with_dict: "{{ ansible_users }}"

ansible-lint shell command

# Default command
ansible-lint site.yml
# docker execから ansible-lint
subprocess.run(
    "docker exec -it "
    + docker_client["hosts"][0]["container_tag"]
    + " bash -c 'cd "
    + str(self.vars_docker["mount_dir"])
    + " && ansible-lint site.yml'",
    shell=True,
    check=True,
)

flake8

# Default command
flake8 [DIR_NAME FILE_NAME]
# docker execから flake8
subprocess.run(
    "docker exec -it "
    + docker_client["hosts"][0]["container_tag"]
    + " bash -c 'cd "
    + str(self.vars_docker["mount_dir"])
    + " && flake8 tests tests.py deploy deploy.py'",
    shell=True,
    check=True,
)

block

# default command
black [DIR_NAME FILE_NAME]
# docker execから flake8
subprocess.run(
    "docker exec -it "
    + docker_client["hosts"][0]["container_tag"]
    + " bash -c 'cd "
    + str(self.vars_docker["mount_dir"])
    + " && block tests tests.py deploy deploy.py'",
    shell=True,
    check=True,
)

testinfra for ansible

        subprocess.run(
    "docker exec -it "
    + docker_client["hosts"][0]["container_tag"]
    + ' bash -c "cd '
    + str(self.vars_docker["mount_dir"])
    + " && py.test -v tests/testinfra.py"
    + " --connection=ssh"
    + " --hosts='ansible://softether'"
    + " --ansible-inventory='hosts/"
    + docker_server["inventory_name"]
    + "_user'"",
shell = True,
        check = True,
)
# Service check
def test_sshd_running_and_enabled(host):
    """ Check service sshd  """
    service = host.service("sshd")
    assert service.is_running
    assert service.is_enabled


# Port check
def test_open_port(host):
    """ Check ports  """
    all_variables = host.ansible.get_variables()
    localhost = host.addr("localhost")
    # sshd
    assert localhost.port(all_variables["sshd_port"]).is_reachable
    if all_variables["sshd_port"] != 22:
        assert not localhost.port(22).is_reachable
    # vpnserver
    assert localhost.port(443).is_reachable
    assert localhost.port(5555).is_reachable
    assert localhost.port(1194).is_reachable


# user check
def test_ansible_user(host):
    """ Check exists ansible user  """
    all_variables = host.ansible.get_variables()
    for i in all_variables["ansible_users"].values():
        user = host.user(i["name"])
        assert user.exists
        assert user.name == i["name"]
        assert user.shell == i["login_shell"]
        assert user.home == "/home/" + i["name"]

Docker for Ansible test

Enable ssh systemd

CentOS7

FROM centos:centos7
VOLUME [ "/sys/fs/cgroup" ]
RUN yum -y update; yum clean all
RUN yum -y install openssh-server passwd; yum clean all
RUN yum install -y which
RUN yum install -y https://repo.ius.io/ius-release-el7.rpm
RUN yum install -y sudo
RUN yum install -y wget
RUN yum install -y curl
RUN yum install -y sshpass
RUN echo 'root:password' | chpasswd
RUN mkdir /root/.ssh
RUN touch /root/.ssh/config
RUN echo $'Host *\n\
 \tStrictHostKeyChecking no\n\
 \n\
ServerAliveInterval 60 \n\
ServerAliveCountMax 10 \n '  >> /root/.ssh/config

RUN chmod 700 /root/.ssh/
RUN chmod 600 /root/.ssh/*

RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ''
ENTRYPOINT ["/sbin/init"]

Ubuntu20.04

FROM ubuntu:20.04
RUN apt-get update && \
    apt-get install -y software-properties-common \
                       tzdata

RUN apt-add-repository -y ppa:git-core/ppa && \
    apt-get update && \
    apt-get install -y git \
                       curl \
                       openssh-server \
                       vim \
                       sudo \
                       sshpass \
                       python3-pip
RUN mkdir /root/.ssh
RUN echo '\n\
Host *\n\
    StrictHostKeyChecking no\n\
' >> /root/.ssh/config

RUN chmod 700 /root/.ssh
RUN chmod 600 /root/.ssh/*

RUN echo 'root:root' | chpasswd
EXPOSE 22
CMD [ "/sbin/init" ]

おっさんWEBエンジニア奮闘記©2007 WEBDIMENSION