Skip to content
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

Uploads dom0 RPM package for securedrop-workstation template #251

Merged
merged 4 commits into from
May 15, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
@@ -0,0 +1,4 @@
# ignore everything
**
# whitelist just the pubkey, used for verifying sigs
!sd-workstation/apt-test-pubkey.asc
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,7 @@ builder/packages/securedrop-workstation-grsec/debian/debhelper-build-stamp
builder/packages/securedrop-workstation-grsec/debian/securedrop-workstation-grsec.substvars
builder/packages/securedrop-workstation-grsec/debian/securedrop-workstation-grsec
builder/packages/securedrop-workstation-grsec/debian/files

# rpm package build artifacts
*.rpm
rpm-repo/
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ flake8: ## Lints all Python files with flake8
template: ## Builds securedrop-workstation Qube template RPM
./builder/build-workstation-template

publish-rpm: ## Uploads signed RPMs to dom0 repository
./scripts/publish-rpm

prep-dom0: prep-salt # Copies dom0 config files for VM updates
sudo qubesctl top.enable sd-vm-updates
sudo qubesctl top.enable sd-dom0-files
Expand Down
12 changes: 12 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[dev-packages]

[packages]
awscli = "*"

[requires]
python_version = "3.5"
126 changes: 126 additions & 0 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,28 @@ rpm -Kv # will now say signatures are OK: "Digests signatures OK"
You can then proceed with distributing the package, via the "test" or "prod" repo,
as appropriate.

## Distributing packages

For the Debian packages, see https://github.com/freedomofpress/securedrop-debian-packaging/.
For the RPM packages, such as the `securedrop-workstation` TemplateVM package, first
build the package (e.g. `make template`), then sign the RPM, as outlined above.

To upload the package to S3, you'll need valid AWS credentials. Talk to a member of the ops team.
Once you have valid credentials configured, install the dependencies (`pipenv install`), then run:

```
./scripts/publish-rpm
```

The RPM will immediately be available in dom0. Provided you've run the Salt configurations,
find it via:

```
sudo qubes-dom0-update --action=search qubes-template-securedrop-workstation
```

You can then install it directly.

## Threat model

This section outlines the threat model for the *SecureDrop Workstation*, and should complement [SecureDrop's threat model](https://docs.securedrop.org/en/stable/threat_model/threat_model.html). This document is always a work in progress, if you have any questions or comments, please open an issue on [GitHub](https://github.com/freedomofpress/securedrop-workstation) or send an email to [[email protected]](mailto:[email protected]).
Expand Down
12 changes: 12 additions & 0 deletions docker/CreateRepoRPM/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# fedora:29 2019-04-15
FROM fedora@sha256:8ee55e140e8751492ab2cfa4513c82093cd2716df9311ea6f442f1f1259cbb3e
LABEL maintainer="Freedom of the Press Foundation"
RUN dnf update -y && \
dnf install -y \
createrepo_c

COPY sd-workstation/apt-test-pubkey.asc /tmp/apt-test-pubkey.asc
RUN rpm --import /tmp/apt-test-pubkey.asc

RUN mkdir /repo
WORKDIR /repo
62 changes: 62 additions & 0 deletions dom0/sd-dom0-files.sls
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,68 @@
# over time. These scripts should be ported to an RPM package.
##

dom0-rpm-test-key:
file.managed:
# We write the pubkey to the repos config location, because the repos
# config location is automatically sent to dom0's UpdateVM. Otherwise,
# we must place the GPG key inside the fedora-29 TemplateVM, then
# restart sys-firewall.
- name: /etc/pki/rpm-gpg/RPM-GPG-KEY-securedrop-workstation-test
- source: "salt://sd/sd-workstation/apt-test-pubkey.asc"
- user: root
- group: root
- mode: 644

dom0-rpm-test-key-import:
cmd.run:
- name: sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-securedrop-workstation-test
- require:
- file: dom0-rpm-test-key

dom0-rpm-test-key-sys-firewall:
cmd.run:
# Pass in the pubkey directly to sys-firewall, so it's available on the
# UpdateVM for dom0 while we're configuring dom0 repos.
- name: >
qvm-run -p sys-firewall '
sudo tee /etc/pki/rpm-gpg/RPM-GPG-KEY-securedrop-workstation-test'
< /srv/salt/sd/sd-workstation/apt-test-pubkey.asc

dom0-rpm-test-key-sys-firewall-import:
cmd.run:
- name: >
qvm-run --no-gui sys-firewall '
sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-securedrop-workstation-test'
- require:
- cmd: dom0-rpm-test-key-sys-firewall

dom0-workstation-rpm-repo:
# We use file.managed rather than pkgrepo.managed, because Qubes dom0
# settings write new repos to /etc/yum.real.repos.d/, but only /etc/yum.repos.d/
# is copied to the UpdateVM for fetching dom0 packages.
file.managed:
- name: /etc/yum.repos.d/securedrop-workstation-dom0.repo
- user: root
- group: root
- mode: 644
- contents: |
[securedrop-workstation-dom0]
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-securedrop-workstation-test
enabled=1
baseurl=https://dev-bin.ops.securedrop.org/dom0-rpm-repo/
Copy link
Contributor

Choose a reason for hiding this comment

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

Hey @conorsch - you probably want an over-ride variable here, we dont want to target dev-bin.ops.securedrop.org in all scenarios, do we?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right now, we only need dev support, but you're right that we'll eventually want to flip this to dev—and preserve the ability for developers to override. Any thoughts on how to do that cleanly in Salt? We're not currently using any vars-based configuration, as we do heavily over in SecureDrop core (https://github.com/freedomofpress/securedrop/).

Copy link
Contributor

Choose a reason for hiding this comment

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

Yea @conorsch - look into pillars here. Variable interpolation uses the jinja syntax and you can inject complex jinja logic where-ever (one of the pros/cons in using salt v. ansible).

name=SecureDrop Workstation Qubes dom0 repo
- require:
- file: dom0-rpm-test-key

# Not installing automatically, since we have more testing to do
# dom0-install-securedrop-workstation-template:
# pkg.installed:
# - pkgs:
# - qubes-template-securedrop-workstation
# - require:
# - file: dom0-workstation-rpm-repo
# - cmd: dom0-rpm-test-key-sys-firewall

# Copy script to system location so admins can run ad-hoc
dom0-update-securedrop-script:
Expand Down
Empty file added rpm-repo/.empty
Empty file.
1 change: 1 addition & 0 deletions scripts/clone-to-dom0
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ function create-tarball() {
printf "Cloning code from %s:%s ...\n" "${dev_vm}" "${dev_dir}"
qvm-run --pass-io "$dev_vm" \
"tar -c --exclude-vcs \
--exclude='*.rpm' \
-C '$(dirname "$dev_dir")' \
'$(basename "$dev_dir")'" > /tmp/sd-proj.tar
}
Expand Down
65 changes: 65 additions & 0 deletions scripts/publish-rpm
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/bin/bash
# Creates a local RPM repo, then pushes its contents to S3, for serving.
set -e
set -u
set -o pipefail


REPO_ROOT="$(git rev-parse --show-toplevel)"
RPM_LOCAL_DIR="${REPO_ROOT}/rpm-repo"


function list_rpms() {
find "$RPM_LOCAL_DIR" | grep '\.rpm$'
}

function container_run() {
docker run --rm \
--network=none \
-v "$RPM_LOCAL_DIR:/repo" \
fpf.local/createrepo \
$@
}

# Check that we have local RPMs to build a repo for
if [[ -z "$(list_rpms)" ]]; then
echo "No RPM files found in $RPM_LOCAL_DIR"
echo "Build RPMs and place in that directory, then rerun the publish action."
exit 1
fi

# Ensure we have 'aws' installed, otherwise we cannot push to S3
if ! hash aws > /dev/null 2>&1 ; then
echo "'aws' CLI not found, install requirements"
exit 2
fi

# Build container for preparing repo
docker build -t fpf.local/createrepo -f docker/CreateRepoRPM/Dockerfile .

# TODO: In order to manage state over time, we'll need to *pull* from S3,
# populating the existing local dir with the current state of what's in S3.
# That's a bandwidth-intensive operation, so skipping for now.
# aws --profile sdpackager s3 sync "s3://dev-bin.ops.securedrop.org/dom0-rpm-repo/ ${RPM_LOCAL_DIR}/"

# Sanity check that we have RPMs locally to upload, and they're already
# signed.
echo "Validating RPM signatures..."
while read -r f; do
fname="$(basename "$f")"
sig_results="$(container_run rpm -Kv "$fname")"
if ! grep -qP '^\s+V4 RSA/SHA256 Signature, key ID \w+: OK$' <<< "$sig_results"; then
echo "Failed to validate signature on $fname"
echo "Is the RPM signed? rpm -Kv showed:"
echo "$sig_results"
exit 3
fi
done <<< "$(list_rpms)"

# Use local container for creating repo metadata
container_run createrepo_c .

# Push created repo dirtree to S3
aws --profile sdpackager s3 sync \
Copy link
Contributor

Choose a reason for hiding this comment

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

How do you feel about making explicit STS calls (assumerole) here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@msheiny I like that idea—can you recommend CLI additions? Also, @rmol, given that you just ran through the full test plan, can you comment on how troublesome it was to sort out the AWS access, with the script written as-is?

Copy link
Contributor

Choose a reason for hiding this comment

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

The hardcoded sdpackager profile meant I had to figure out how to construct my config/credentials files to suit the script, which did mean some more manual fumbling.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great feedback, let's aim to clean this up next time another team member runs through the process. Not opposed to adding a CLI flag to the existing script, but we may want to migrate to a more robust Python script in the near future.

--exclude ".empty" \
"${RPM_LOCAL_DIR}/" s3://dev-bin.ops.securedrop.org/dom0-rpm-repo/
2 changes: 1 addition & 1 deletion sd-workstation/apt-test-pubkey.asc
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ J7KQd1hEvVs00DxY6VlyK0FzXqByKYq6Arl2tzlCZ6RPEHKXV2xSP06jLEagzgYe
DylVo9Xahenj4n/Mtq7Am6tGgU9Vy9cGbWNBdUND/mFQEEZSh9RJabPeluH12sir
5/tfsDr4DGHSz7ws+5M6Zbk6oNJEwQZ4cR+81qCfXE5X5LW1KlAL8wDl7dfS
=fYUi
-----END PGP PUBLIC KEY BLOCK-----
-----END PGP PUBLIC KEY BLOCK-----
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Adding the trailing newline was required, otherwise dnf balked, saying the pubkey was invalid.