diff --git a/inventory/host_vars/bodhi-backend01.phx2.fedoraproject.org b/inventory/host_vars/bodhi-backend01.phx2.fedoraproject.org index 6c2bfb364c..9e7b357faa 100644 --- a/inventory/host_vars/bodhi-backend01.phx2.fedoraproject.org +++ b/inventory/host_vars/bodhi-backend01.phx2.fedoraproject.org @@ -17,6 +17,11 @@ bodhi_masher_enabled: True bodhi_updates_handler_enabled: False bodhi_signed_handler_enabled: False +# GDPR SAR variables +sar_script: /usr/local/bin/bodhi_sar.py +sar_script_user: apache +sar_output_file: bodhi.json + # These are consumed by a task in roles/fedmsg/base/main.yml fedmsg_certs: # This first cert is used by the push-tool. releng members run it and it fires diff --git a/inventory/inventory b/inventory/inventory index fd5e40eb67..f2f1be5679 100644 --- a/inventory/inventory +++ b/inventory/inventory @@ -39,6 +39,9 @@ retrace01.qa.fedoraproject.org [retrace-stg] retrace02.qa.fedoraproject.org +[sar] +bodhi-backend01.phx2.fedoraproject.org + [certgetter] certgetter01.phx2.fedoraproject.org diff --git a/playbooks/manual/gdpr/sar.yml b/playbooks/manual/gdpr/sar.yml new file mode 100644 index 0000000000..242cb465ee --- /dev/null +++ b/playbooks/manual/gdpr/sar.yml @@ -0,0 +1,87 @@ +# This playbook retrieves data that Fedora knows about a username and/or e-mail address. +# +# Admins: +# +# To use this playbook, you should define the following vars: sar_fas_user, sar_email, and +# sar_tar_output_path. The first two identify the person you wish to make an archive for, and the +# last defines where the playbook will write the tarball on the local machine when its done. For +# example: +# +# $ sudo ansible-playbook playbooks/manual/gdpr/sar.yml -e sar_fas_user=bowlofeggs \ +# -e sar_email=bowlof@eggs.biz -e sar_tar_output_path=/home/bowlofeggs/bowlofeggs.tar.gz +# +# +# Developers: +# +# Your task is to create a script and ansible variables so that your application is compatible +# with this playbook. +# +# Script +# ------ +# +# You need to create a script and have your project's Ansible role install that script somewhere +# (most likely on a host from your project - for example Bodhi's is going on bodhi-backend02.) +# It's not a bad idea to put your script into your upstream project - there are plans for upstream +# Bodhi to ship bodhi-sar. This script should accept two environment variables as input: +# SAR_USERNAME and SAR_EMAIL. Not all applications will use both, so do what makes sense for your +# app. The first will be a FAS username and the second will be an e-mail address. Your script +# should gather the required information related to those identifiers and print it in a machine +# readable format to stdout. Bodhi, for example, prints information to stdout in JSON. +# +# Some scripts may need secrets embedded in them - if you must do this be careful to install the +# script with 0700 permissions, ensuring that only sar_script_user can run them. Bodhi worked +# around this concern by having the script run as apache and read Bodhi's server config file. +# +# Variables +# --------- +# +# In addition to configuring a script, you need to define some Ansible variables for the host that +# will run your script: +# +# sar_script: The full path to the script (for example, /usr/bin/bodhi-sar). +# sar_script_user: The user the script should be run as (for example, Bodhi runs as apache). +# sar_output_file: The name of the file to write into the output tarball (for example, bodhi.json). +# +# You also need to add your host to the [sar] group in inventory/inventory. + +- name: Gather SAR data + hosts: sar + tasks: + - command: "{{ sar_script }}" + environment: + SAR_USERNAME: "{{ sar_fas_user }}" + SAR_EMAIL: "{{ sar_email }}" + register: sar_data + become: yes + become_user: "{{ sar_script_user }}" + # Let's make this a more conveniently expressed variable. + - set_fact: + sar_data: "{{ sar_data['stdout'] }}" + +- name: Create the archive + hosts: localhost + tasks: + - name: "Create the archive" + block: + # Create a safe place to store the files. + - command: "mktemp -d" + register: sar_tmp_dir + # Let's make this a more conveniently expressed variable. + - set_fact: + sar_tmp_dir: "{{ sar_tmp_dir['stdout'] }}" + # Write files from each service into our protected folder. + - copy: + content: "{{ hostvars[item]['sar_data'] }}" + dest: "{{ sar_tmp_dir }}/{{ hostvars[item]['sar_output_file'] }}" + loop: "{{ groups['sar'] }}" + # Generate a tarball of the files from each service. + - shell: "tar --transform \"s:^:{{ sar_fas_user }}_{{ sar_email }}/:\" -czf {{ sar_tmp_dir }}/{{ sar_fas_user }}_{{ sar_email }}.tar.gz *" + args: + chdir: "{{ sar_tmp_dir }}" + # Make sure the tarball is private. + - command: "chmod 0700 {{ sar_tmp_dir }}/{{ sar_fas_user }}_{{ sar_email }}.tar.gz" + # Move the tarball into the desired pick up location. + - command: "mv {{ sar_tmp_dir }}/{{ sar_fas_user }}_{{ sar_email }}.tar.gz {{ sar_tar_output_path }}" + always: + # Let's clean up our temporary directory. + - command: "rm -r {{ sar_tmp_dir }}" diff --git a/roles/bodhi2/backend/files/bodhi_sar.py b/roles/bodhi2/backend/files/bodhi_sar.py new file mode 100644 index 0000000000..84f9d85828 --- /dev/null +++ b/roles/bodhi2/backend/files/bodhi_sar.py @@ -0,0 +1,63 @@ +#!/usr/bin/python2 +# Copyright (c) 2018 Red Hat, Inc. +# +# This file is part of Bodhi. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +"""This script will print out SAR data for a FAS account given as the SAR_USERNAME env var.""" + +import json +import os + +import sqlalchemy + +from bodhi.server import config, initialize_db, models + + +initialize_db(config.config) + + +sar_data = {} + + +if os.environ['SAR_USERNAME']: + user = None + + try: + user = models.User.query.filter_by(name=os.environ['SAR_USERNAME']).one() + except sqlalchemy.orm.exc.NoResultFound: + # User not found so nothing to do. + pass + + if user is not None: + sar_data[user.name] = {} + sar_data[user.name]['comments'] = [ + {'karma': c.karma, 'karma_critpath': c.karma_critpath, 'text': c.text, + 'anonymous': c.anonymous, 'timestamp': c.timestamp.strftime('%Y-%m-%d %H:%M:%S'), + 'update_alias': c.update.alias, 'username': c.user.name} + for c in user.comments] + sar_data[user.name]['updates'] = [ + {'autokarma': u.autokarma, 'stable_karma': u.stable_karma, + 'unstable_karma': u.unstable_karma, 'requirements': u.requirements, + 'require_bugs': u.require_bugs, 'require_testcases': u.require_testcases, + 'notes': u.notes, 'type': str(u.type), 'severity': str(u.severity), + 'suggest': str(u.suggest), 'close_bugs': u.close_bugs, 'alias': u.alias, + 'builds': [b.nvr for b in u.builds], 'release_name': u.release.name, + 'bugs': [b.bug_id for b in u.bugs], 'user': u.user.name, + 'date_submitted': u.date_submitted.strftime('%Y-%m-%d %H:%M:%S')} + for u in user.updates] + + +print(json.dumps(sar_data)) diff --git a/roles/bodhi2/backend/tasks/main.yml b/roles/bodhi2/backend/tasks/main.yml index 4d7332b360..24a150e347 100644 --- a/roles/bodhi2/backend/tasks/main.yml +++ b/roles/bodhi2/backend/tasks/main.yml @@ -240,6 +240,17 @@ - bodhi - koji-sync +- name: Install bodhi_sar.py + copy: + src: bodhi_sar.py + dest: /usr/local/bin/bodhi_sar.py + mode: 0700 + owner: apache + group: apache + when: inventory_hostname.startswith('bodhi-backend01') + tags: + - bodhi + # # cron job that syncs updates to master mirror #