Skip to content

Local automated upgrade testing #3075

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 52 commits into from
May 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
1a917c8
Add grsec debian packages to testing
msheiny Feb 9, 2018
e1f0203
Allow Jinja-fication of DEBIAN files, use w/ grsec
msheiny Feb 9, 2018
f723a7f
Over-load role rsync options for debian building
msheiny Feb 9, 2018
8da833e
init molecule scen. for kick-starting specifc ver of SD
msheiny Feb 13, 2018
d6b5c3b
Install python-vagrant dependency for developers
msheiny Feb 16, 2018
60b342b
Add Initial phase 1 working scenario for upgrade testing
msheiny Feb 16, 2018
33537ed
Add docker apt repo on same net as SD vagrant
msheiny Feb 20, 2018
71b474c
Add jdauphant nginx role
msheiny Feb 21, 2018
67253ac
Ditch docker, utilize vagrant box for apt server
msheiny Feb 21, 2018
8477df6
Ensure direct ssh access is enabled
msheiny Feb 22, 2018
0d174db
Ensure previous version of git is being cloned first
msheiny Feb 22, 2018
a7773e3
Diverge from custom aws reboot logic
msheiny Feb 22, 2018
1c48596
Utilize private static IPs
msheiny Feb 23, 2018
b19d211
Utilize vagrant insecure key for both servers
msheiny Feb 23, 2018
4c2bb45
Move apt-test keys into ./files dir
msheiny Feb 23, 2018
af7c11d
Add apt-test pub key to staging boxes
msheiny Feb 23, 2018
22cd840
Add scenario for vagrant builder
msheiny Feb 26, 2018
a84e308
Remove un-used ami-builder scenario
msheiny Feb 26, 2018
54c1f79
Provide make shortcut for vagrant packager
msheiny Feb 27, 2018
fb553e0
Add logic to push boxes up to S3
msheiny Feb 27, 2018
aeef51e
MiTM our SD apt servers with fake local apt
msheiny Feb 27, 2018
9f396be
Repoint molecule config to use hosted boxes
msheiny Feb 27, 2018
d000097
Correct flake8 issues, convert mypy syntax to py2
msheiny Feb 28, 2018
f9e8d51
Bump vagrant box versions to retain log files
msheiny Mar 1, 2018
d61978a
Fail vagrant package script if preceeding logic bombs
msheiny Mar 1, 2018
306cc32
Strengthen logic to ensure existing instance stands up
msheiny Mar 1, 2018
d8c1057
Toggle to pull from apt-test.freedom.press
msheiny Mar 1, 2018
642194b
Resolve missing cron-apt log after reboot
msheiny Mar 1, 2018
e7de75d
Fix builder tests for grsec package
msheiny Mar 7, 2018
309feb4
Fix ansible task description typo :)
msheiny Mar 7, 2018
8b14958
Ensure that tor server is enabled upon start-up
msheiny Mar 14, 2018
58625d4
Rename make cmd to be more in-line with other cmds
msheiny Mar 30, 2018
0030841
Rename upgrade_test -> upgrade for science
msheiny Mar 30, 2018
563e1ae
Bump vagrant package logic to use 0.6 release
msheiny Apr 5, 2018
5d3ccbf
Make sure tor starts up on reboot
msheiny Apr 5, 2018
f2f7b70
Fork vagrant molecule module to add halt functionality
msheiny Apr 6, 2018
57523bb
Add option for vagrant over-ride
msheiny Apr 6, 2018
89543fe
Upload 0.6 vagrant box, peg upgrade module to it
msheiny Apr 6, 2018
bd07e8d
Explicitly disable NFS in upgrade scenario
msheiny Apr 6, 2018
3e63b64
Whoopss - Bump expiration for testing CA
msheiny Apr 7, 2018
eb43e00
Symlink vagrant molecule into upgrade scenario
msheiny Apr 7, 2018
f75c9cd
Make upgrade side-effect explicitly upgrade deps
msheiny Apr 9, 2018
180826c
Remove fork of molecule_vagrant ansible library
msheiny May 7, 2018
a013de4
Address pathing issue with latest molecule update
msheiny May 7, 2018
e9c95f4
Ensure pre 0.7 SD, SSH works localnet after reboot
msheiny May 7, 2018
5bd3170
Add additional ignore items to docker build
msheiny May 7, 2018
a3fdcab
Move flake8 configuration to separate file
msheiny May 7, 2018
e2e3650
Exclude flake8 NITs
msheiny May 7, 2018
094dd0f
Optional - apt as a reverse-proxy to apt-test
msheiny May 8, 2018
2d05027
Work-around for testinfra 1.12.0 socket bug
msheiny May 9, 2018
1baabc3
Fixes for vagrant_packager + updated molecule
msheiny May 9, 2018
4800743
Fix timeout on SD 0.6 vagrant_packager on reboot
msheiny May 9, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ securedrop/static/gen
securedrop/static/.webassets-cache
securedrop/tests/log/*
securedrop/tests/pages-layout/
**/.molecule
build/*.deb
**/*.box
admin/.tox
7 changes: 7 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[flake8]
exclude =
config.py,
.venv/,
journalist_gui/journalist_gui/updaterUI.py,
journalist_gui/journalist_gui/resources_rc.py,
.python3
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,7 @@ raw-test-output/

# Ignore visual studio code folder
.vscode

#Ignore vagrant staging files
*.box
*.img
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ docs: ## Build project documentation in live reload for editing

.PHONY: flake8
flake8: ## Validates PEP8 compliance for Python source files.
flake8 --exclude='config.py,.venv/,journalist_gui/journalist_gui/updaterUI.py,journalist_gui/journalist_gui/resources_rc.py'
flake8

.PHONY: app-lint
app-lint: ## Tests pylint lint rule compliance.
Expand Down Expand Up @@ -143,6 +143,10 @@ self-signed-https-certs: ## Generates self-signed certs for TESTING the HTTPS co
@echo "Generating self-signed HTTPS certs for testing..."
@./devops/generate-self-signed-https-certs.sh

.PHONY: vagrant-package
vagrant-package: ## Package up a vagrant box of the last stable SD release
@devops/scripts/vagrant_package.sh

# Explaination of the below shell command should it ever break.
# 1. Set the field separator to ": ##" and any make targets that might appear between : and ##
# 2. Use sed-like syntax to remove the make targets
Expand Down
7 changes: 7 additions & 0 deletions devops/scripts/vagrant_package.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

molecule test -s vagrant_packager && \
# Unfortunately since we need to prompt the user for sudo creds..
# I had to break the actual vagrant package logic outside of molecule
molecule/vagrant_packager/package.py && \
molecule destroy -s vagrant_packager
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha, I ran into a similar problem over in freedomofpress/ansible-role-grsecurity-build#31, with vars_prompt failing to run in non-interactive mode. I wouldn't hesitate to put logic this simple directly in the Makefile, but no objections here.

5 changes: 5 additions & 0 deletions install_files/ansible-base/group_vars/all/securedrop
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,8 @@ enable_ssh_over_tor: true
# force a reboot. Needed because of the de-coupled nature of
# the many roles of the current prod playbook
securedrop_cond_reboot_file: /tmp/sd-reboot-now

# If you bump this, also remember to bump in molecule/builder/tests/vars.yml
securedrop_pkg_grsec:
ver: "4.4.115"
depends: "linux-image-3.14.79-grsec,linux-image-4.4.115-grsec"
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,13 @@
# Destination directory on Ansible controller where built deb packages
# will be stored after fetching from build host.
securedrop_local_build: "../../build"

securedrop_generic_build_path: "/tmp/build/"

securedrop_app_rsync_opts:
- "--chmod=u=rwX,g=rX,o=rX"
- "--chown=root:root"
- "--exclude=*.git"
- "--exclude=*aths"
- "--exclude=*.deb"
- "--exclude=*.j2"
Original file line number Diff line number Diff line change
@@ -1,15 +1,46 @@
---
- name: Reduce weird path re-usage
set_fact:
package_path: "{{ role_path }}/../../../{{ package_name }}/"
build_path: "{{ securedrop_generic_build_path }}/{{ package_name }}"

- name: Ensure build directory in-place
file:
state: directory
path: "{{ securedrop_generic_build_path }}"

- name: Copy app code to build directory.
synchronize:
# All Debian package control files for FPF-maintained packages reside in
# `install_files/<package_name>` in the SecureDrop git repository.
src: "{{ role_path }}/../../../{{ package_name }}/"
dest: "/tmp/build/{{ package_name }}/"
src: "{{ package_path }}"
dest: "{{ build_path }}/"
recursive: yes
delete: yes
use_ssh_args: "{{ 'yes' if amazon_builder else omit }}"
rsync_opts: "{{ securedrop_app_rsync_opts }}"

- name: Find any jinja templates
find:
paths: "{{ package_path }}"
patterns: "*.j2"
recurse: yes
delegate_to: localhost
become: no
register: jinja_files_found

- name: Create any necessary parent directories for jinja files
file:
path: "{{ build_path }}/{{ item.path | dirname |regex_replace('^\\/.*'+package_name, '') }}"
state: directory
with_items: "{{ jinja_files_found.files }}"

- name: Template out any jinja files found and copy over
template:
src: "{{ item.path }}"
dest: "{{ build_path }}/{{ item.path | regex_replace('^\\/.*'+package_name, '') | regex_replace ('\\.j2$','') }}"
with_items: "{{ jinja_files_found.files }}"

- name: run bash script to build generic packages
script: "build_generic_package.sh {{ package_name }}"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def main():
ossec_version = module.params['ossec_version']
try:
ossec_config = OSSECURLs(ossec_version=ossec_version)
except:
except: # noqa: E722
msg = ("Failed to find checksum information for OSSEC v{}."
"Ensure you have the proper release specified, "
"and check the download page to confirm: "
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
Package: securedrop-grsec
Source: securedrop-grsec
Version: 4.4.115
Version: {{ securedrop_pkg_grsec.ver }}
Architecture: amd64
Maintainer: SecureDrop Team <[email protected]>
Depends: linux-image-3.14.79-grsec,linux-image-4.4.115-grsec
Depends: {{ securedrop_pkg_grsec.depends }}
Section: admin
Priority: optional
Homepage: https://securedrop.org
Expand Down
4 changes: 2 additions & 2 deletions molecule/ansible-config/molecule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ provisioner:
callback_whitelist: "profile_tasks, timer"
inventory:
links:
group_vars: ../../../install_files/ansible-base/group_vars
host_vars: ../../../install_files/ansible-base/host_vars
group_vars: ../../install_files/ansible-base/group_vars
host_vars: ../../install_files/ansible-base/host_vars
env:
ANSIBLE_ROLES_PATH: ../../install_files/ansible-base/roles
scenario:
Expand Down
4 changes: 2 additions & 2 deletions molecule/aws/molecule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ provisioner:
callback_whitelist: "profile_tasks, timer"
inventory:
links:
group_vars: ../../../install_files/ansible-base/group_vars
host_vars: ../../../install_files/ansible-base/host_vars
group_vars: ../../install_files/ansible-base/group_vars
host_vars: ../../install_files/ansible-base/host_vars
env:
ANSIBLE_ROLES_PATH: ../../install_files/ansible-base/roles
scenario:
Expand Down
3 changes: 1 addition & 2 deletions molecule/builder/molecule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ provisioner:
name: ansible
inventory:
links:
# Path is relative to .molecule folder
group_vars: ../../../install_files/ansible-base/group_vars
group_vars: ../../install_files/ansible-base/group_vars
env:
ANSIBLE_ROLES_PATH: ../../install_files/ansible-base/roles
ANSIBLE_ACTION_PLUGINS: ../../install_files/ansible-base/action_plugins
Expand Down
16 changes: 16 additions & 0 deletions molecule/builder/tests/test_securedrop_deb_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def get_deb_packages():
ossec_version=securedrop_test_vars.ossec_version,
keyring_version=securedrop_test_vars.keyring_version,
config_version=securedrop_test_vars.config_version,
grsec_version=securedrop_test_vars.grsec_version
)

deb_packages = [d.format(**substitutions) for d
Expand Down Expand Up @@ -289,3 +290,18 @@ def test_grsec_metapackage(host, deb):
# Post-install kernel hook for managing PaX flags must exist.
assert re.search("^.*\./etc/kernel/postinst.d/paxctl-grub$",
c.stdout, re.M)


@pytest.mark.parametrize("deb", deb_packages)
def test_jinja_files_not_present(host, deb):
"""
Make sure that jinja (.j2) files were not copied over
as-is into the debian packages.
"""

deb_package = host.file(deb.format(
securedrop_test_vars.securedrop_version))

c = host.run("dpkg-deb --contents {}".format(deb_package.path))
# There shouldn't be any files with a .j2 ending
assert not re.search("^.*\.j2$", c.stdout, re.M)
2 changes: 2 additions & 0 deletions molecule/builder/tests/vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ securedrop_version: "0.7.0~rc1"
ossec_version: "2.8.2"
keyring_version: "0.1.1"
config_version: "0.1.1"
grsec_version: "4.4.115"

# These values will be interpolated with values populated above
# via helper functions in the tests.
Expand All @@ -26,6 +27,7 @@ build_deb_packages:
- /tmp/build/ossec-agent-{ossec_version}-amd64.deb
- /tmp/build/securedrop-keyring-{keyring_version}+{securedrop_version}-amd64.deb
- /tmp/build/securedrop-config-{config_version}+{securedrop_version}-amd64.deb
- /tmp/build/securedrop-grsec-{grsec_version}-amd64.deb

lintian_tags:
# - non-standard-file-perm
Expand Down
24 changes: 24 additions & 0 deletions molecule/upgrade/ansible-override-vars.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
install_local_packages: false
primary_network_iface: eth0
ssh_users: vagrant
securedrop_app_install_from_repo: true
allow_direct_access: true
ssh_listening_address: 0.0.0.0

monitor_ip: "{{ hostvars['mon-staging']['ansible_'+primary_network_iface].ipv4.address }}"
monitor_hostname: "{{ hostvars['mon-staging'].ansible_hostname }}"
app_ip: "{{ hostvars['app-staging']['ansible_'+primary_network_iface].ipv4.address }}"
app_hostname: "{{ hostvars['app-staging'].ansible_hostname }}"

etc_hosts:
app-staging:
- reg: ^127.0.0.1
line: 127.0.0.1 app-staging localhost
- reg: securedrop-monitor-server-alias$
line: "{{ monitor_ip }} mon-staging securedrop-monitor-server-alias"
mon-staging:
- reg: ^127.0.0.1\s+mon
line: 127.0.0.1 mon-staging localhost
- reg: app-staging$
line: "{{ app_ip }} app-staging"
74 changes: 74 additions & 0 deletions molecule/upgrade/apt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---

- name: Configure apt-server
hosts: aptservers
become: yes
tasks:
- name: Establish QA strategy
set_fact:
QA_APTTEST: "{{ lookup('env','QA_APTTEST')|bool }}"

- import_tasks: local_apt_mirror.yml
- import_tasks: local_apt_with_debs.yml
when: not QA_APTTEST

vars:
molecule_dir: "{{ lookup('env', 'MOLECULE_SCENARIO_DIRECTORY') }}"
dpkg_dir: /var/repos/debs
rep_dist: trusty
rep_component: main
rep_arch: i386 amd64
release_file: "/var/repos/base/dists/{{ rep_dist }}/Release"
nginx_sites:
default:
- listen 80
- root "/var/repos/base"
- location / { autoindex on; }
- location /gpg { alias /var/repos/base/; }
encrypted:
- listen 443 ssl
- server_name apt.freedom.press
- ssl_certificate /etc/ssl/certs/apt_freedom_press.pem
- ssl_certificate_key /etc/ssl/private/apt_freedom_press.priv
- root "/var/repos/base"
- location / { {{ "proxy_pass https://apt-test.freedom.press;" if QA_APTTEST else "autoindex on;" }} }

- name: Configure apt-server
hosts: securedrop
gather_facts: false
become: yes
tasks:
- block:
- name: Redirect to local QA Apt server
set_fact:
apt_key_bits:
- url: "http://{{ hostvars['apt']['ansible_eth0'].ipv4.address }}/gpg/apt-test.pub"
id: 6D65484B
- url: "http://{{ hostvars['apt']['ansible_eth0'].ipv4.address }}/gpg/apt-test-fpf.pub"
id: 4A3BE4A92211B03C
apt_test_etc_line: "{{ hostvars['apt']['ansible_eth0'].ipv4.address }} apt.freedom.press"

- name: Install testing apt key to keyring
apt_key:
id: "{{ item.id|default(omit) }}"
url: "{{ item.url|default(omit) }}"
data: "{{ item.data|default(omit) }}"
state: present
with_items: "{{ apt_key_bits }}"

- name: Redirect apt.freedom.press to local apt server
lineinfile:
path: /etc/hosts
regexp: apt.freedom.press$
line: "{{ apt_test_etc_line }}"

- name: Add apt-test CA to CA trusted store
copy:
src: cacert.pub
dest: /usr/local/share/ca-certificates/fpf_test_ca.crt
notify: update ca
tags: apt

handlers:
- name: update ca
command: update-ca-certificates
59 changes: 59 additions & 0 deletions molecule/upgrade/create.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
- import_playbook: sd_clone.yml

- name: Create
hosts: localhost
connection: local
vars:
molecule_file: "{{ lookup('env', 'MOLECULE_FILE') }}"
molecule_instance_config: "{{ lookup('env', 'MOLECULE_INSTANCE_CONFIG') }}"
molecule_yml: "{{ lookup('file', molecule_file) | molecule_from_yaml }}"
tasks:

- name: Create molecule instance(s)
molecule_vagrant:
instance_name: "{{ item.name }}"
instance_interfaces: "{{ item.interfaces | default(omit) }}"
instance_raw_config_args: "{{ item.instance_raw_config_args | default(omit) }}"

platform_box: "{{ item.box }}"
platform_box_version: "{{ item.box_version | default(omit) }}"
platform_box_url: "{{ 'file://'+playbook_dir+'/' if item.box_url|default(false) else '' }}{{ item.box_url | default(omit) }}"

provider_name: "{{ molecule_yml.driver.provider.name }}"
provider_memory: "{{ item.memory | default(omit) }}"
provider_cpus: "{{ item.cpus | default(omit) }}"
provider_override_args: "{{ item.provider_override_args | default(omit) }}"
provider_raw_config_args: "{{ item.raw_config_args | default(omit) }}"
force_stop: yes

state: up
register: server
with_items: "{{ molecule_yml.platforms }}"

# Mandatory configuration for Molecule to function.

- name: Populate instance config dict
set_fact:
instance_conf_dict: {
'instance': "{{ item.Host }}",
'address': "{{ item.HostName }}",
'user': "{{ item.User }}",
'port': "{{ item.Port }}",
'identity_file': "{{ item.IdentityFile }}", }
with_items: "{{ server.results }}"
register: instance_config_dict
when: server.changed | bool

- name: Convert instance config dict to a list
set_fact:
instance_conf: "{{ instance_config_dict.results | map(attribute='ansible_facts.instance_conf_dict') | list }}"
when: server.changed | bool

- name: Dump instance config
copy:
# NOTE(retr0h): Workaround for Ansible 2.2.
# https://github.com/ansible/ansible/issues/20885
content: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}"
dest: "{{ molecule_instance_config }}"
when: server.changed | bool
Loading