Deploying Mantis Bug Tracker on Google Cloud Platform

Utilising CentOS 7, Caddy, Cloud SQL and the gcloud CLI

rsclarke
rsclarke
Oct 11, 2017 · 11 min read

Overview

Use Case

Currently as an independent security researcher I need a solution to catalogue and track vulnerabilities discovered. At a previous employer this has been achieved through custom in-house software. Alternatively, those in the security industry are likely to be familiar with Project Zero’s issue tracker, where bug tracking software Monorail is utilised.

Side note: I only discovered Monorail was open-source whilst writing this article and would fit given it is a Google App Engine project.

Of course there are many other open-source bug tracking software solutions available. I found Mantis Bug Tracker offered the right balance between user interface, configuration and provides an API for automation. Admittedly I have not used it in anger, however I was keen to get it setup and also learn more about Google Cloud Platform.

Without going off topic into vulnerability disclosure, bugs listed on the tracker will be the result of those found either through automation, therefore requiring triage, or manual investigation. I don’t foresee the information being made public through this means and have opted to use small (f1-micro) instances on Google Cloud Platform given the light load and costing.

Using the pricing calculator, 1 month with sustained usage discount is expected to cost approximately $16 (USD, at the time of writing). Of course this may vary depending on the region you deploy the application in and instance sizes you require.

Buzzword Summary

This article walks through the deployment of Mantis Bug Tracker (MantisBT) on Google Cloud Platform (GCP). MantisBT will be installed on Google Compute Engine, in this scenario a CentOS 7 virtual machine, using Caddy as the web server and to proxy requests with FastCGI to PHP-FPM in order to serve the application. Google Cloud SQL will be used as the database backend for MantisBT.

The article is in two parts; part 1 focuses on creating the compute and SQL instances, whilst part 2 walks through the application install process.

Part 1: Instance Setup

Google Cloud SDK

All of the services and instances used on Google Cloud may be instantiated through the web console. However, I have been interested in becoming more familiar with the command line utility to quickly deploy and redeploy services. Google already provides a quickstart for installing and initialising the Cloud SDK. I encourage you to follow this if you have not already done so.

You can create a new project or use the currently configured one listed under the command;

gcloud config list

To create and switch, substitute for a unique name in the following commands;

gcloud projects create PROJECT_ID
gcloud config set core/project PROJECT_ID

Further setup of the compute instance and Cloud SQL will occur within this project. You may find that you will be asked to enable APIs if not already done so for the given project as you proceed.

Compute Instance

The compute instance will act as the web server running the MantisBT application served using Caddy.

Depending on whether you are using a new project or an existing one, the default rules to allow HTTP(S) traffic through the firewall may not be present. You can view the current firewall rule list with the following command.

gcloud compute firewall-rules list

If there is no rule to allow and in the output, execute the following two commands to add these rules.

gcloud compute firewall-rules create default-allow-http \ 
--allow=tcp:80 --target-tags http-server
gcloud compute firewall-rules create default-allow-https \
--allow=tcp:443 --target-tags https-server

If you wish to assign a static IP address for your instance of MantisBT, create one with the following command, substituting for hostname.

gcloud compute addresses create ADDRESS_NAME

The address can be seen in the output of;

gcloud compute addresses list

Create an A record with your DNS provider pointing a domain to this IP address. This is required if you wish to automatically obtain a certificate with Let’s Encrypt using Caddy later on. This will provide secure access to your MantisBT application.

Now create the compute instance with the following command, substitute to give the created virtual machine a name, for example . Equally, change to that used earlier. Note the tags used reflect the given to the firewall rules created. The use of scopes allows the VM to connect and use the Cloud SQL database. Further options to create the instance can be seen in the reference documentation.

gcloud compute instances create INSTANCE_NAME               \
--image-family centos-7 --image-project centos-cloud \
--machine-type=f1-micro --tags=http-server,https-server \
--address=ADDRESS_NAME \
--scopes=default,cloud-platform,sql-admin

Once the command returns with the status you can test SSH access with;

gcloud compute ssh INSTANCE_NAME

This will create a key pair for Google Compute Engine if there isn’t already one at and update the project’s metadata to allow this key to be used.

Type within the SSH session to return to your local prompt and we will continue with the setup of Google Cloud SQL.

Google Cloud SQL

Currently there are two database engines offered for Cloud SQL, MySQL and PostgreSQL, the latter still in beta. PostgreSQL on Cloud SQL currently does not support high availability and replication. This is not particularly required in my use case for now, however it is worth considering depending on your deployment. Google’s documentation provides instructions on configuring an instance for high availability. I will be continuing with PostgreSQL.

Use the following command, substituting to give the Cloud SQL instance a name, and to the location of the compute instance, this can be checked with .

gcloud sql instances create SQL_INSTANCE_NAME --tier=db-f1-micro  \
--database-version=POSTGRES_9_6 --storage-type=HDD \
--storage-size=10 --storage-auto-increase \
--activation-policy=ALWAYS --backup --backup-start-time=00:00 \
--maintenance-release-channel=production \
--maintenance-window-day=FRI --maintenance-window-hour=12 \
--gce-zone=GCE_ZONE --region=REGION

This creates a shared-core instance with 0.6GB RAM and 10GB storage on a hard disk drive which will increase (but not decrease) when necessary. A daily backup at midnight, with a maintenance window on Friday at midday.

Lastly, set the default user account password using the following command, substituting with the name used in the create command above.

gcloud sql users set-password postgres no-host \
--instance=SQL_INSTANCE_NAME --prompt-for-password

Section Recap

In this section you have created the foundation infrastructure and platform for installing and running MantisBT. This has included;

  • Installing and initialising the Cloud SDK as well as configuring a project
  • Creating firewall rules
  • Reserving a static IP address
  • Creating a compute instance, assigning the aforementioned rules and IP address
  • Connecting to the instance using SSH
  • Creating a managed Cloud SQL instance with backup and maintenance schedules.

With this in place, the remainder of the article will focus on installing MantisBT and Caddy, as well as Cloud SQL Proxy to securely connect to the database backend.

Part 2: Application Install Process

Connect to the Instance

The following commands for installing and configuring the software all take place on your compute instance created earlier. You can securely connect to the instance with;

gcloud compute ssh INSTANCE_NAME

Cloud SQL Proxy

The Cloud SQL instance isn’t publicly available when created. Clients and their associated IP addresses wishing to communicate must be added to a whitelist. Furthermore, it is highly recommended that you connect to the database using the Secure Socket Layer (SSL) protocol. This ensures data transmitted between the client and the Cloud SQL database is secure.

The necessity to whitelist IP addresses, configure and manage server/client certificates for secure communication is taken care of when using Cloud SQL Proxy. More insight to how the Cloud SQL Proxy works can be seen in the reference documentation, About the Cloud SQL Proxy. In summary it automatically encrypts traffic and handles access to the database.

You may find that you need to enable the Cloud SQL API for the proxy to work. It can be enabled through the API Library. Additionally, when the compute instance was created we added the and scopes. This means the default service account can manage the Cloud SQL instance. Alternatively you can create a specific service account and pass the credentials file when starting the Cloud SQL Proxy.

Firstly download Cloud SQL Proxy;

curl https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 \
-o cloud_sql_proxy

Make the application executable, and move to .

chmod +x cloud_sql_proxy
sudo mv cloud_sql_proxy /usr/local/bin

In order to start the process at boot we will create a systemd service unit configuration file based on this comment and stackoverflow answer. Replace with the instance connection name as given on the Cloud SQL dashboard. This is in the form .

[Unit]
Description=Google Cloud Compute Engine SQL Proxy
After=networking.service
Before=google-shutdown-scripts.service
[Service]
Type=simple
WorkingDirectory=/run/cloudsql
ExecStart=/usr/local/bin/cloud_sql_proxy -dir=/run/cloudsql -instances=CONNECTION_NAME=tcp:127.0.0.1:5432
Restart=always
StandardOutput=journal
User=root
[Install]
WantedBy=multi-user.target

Save this file as and set the appropriate permissions;

sudo chmod 0644 /etc/systemd/system/cloud-sql-proxy.service

Create the working directory;

sudo mkdir /run/cloudsql

And finally, enable and start the proxy;

sudo systemctl daemon-reload
sudo systemctl enable cloud-sql-proxy
sudo systemctl start cloud-sql-proxy

You can check for log output using to see if the proxy is up and running or for any errors;

journalctl -u cloud-sql-proxy

MantisBT and PHP-FPM

We begin by installing PHP and additional modules required for MantisBT. If you proceeded with a MySQL database earlier, substitute for in the following command;

sudo yum install php php-pgsql php-mbstring php-fpm php-soap \ 
policycoreutils-python

CentOS defaults to using the user and group for running the Apache Web Server. In this instance we are using Caddy, and default configuration files relating to PHP-FPM use the user and group. We will create a new user and update the configuration file accordingly for the purposes of clarity as we are not using Apache.

sudo mkdir /srv/www
sudo groupadd -g 33 www-data
sudo useradd -g www-data --no-user-group --home-dir /srv/www \
--no-create-home --shell /usr/sbin/nologin --system \
--uid 33 www-data
sudo chown www-data:www-data /srv/www

Modify substituting the lines;

user = apache
group = apache

With as the user and group respectively;

user = www-data
group = www-data

Additionally update the ownership on the PHP session store;

sudo chown root:www-data /var/lib/php/session

Just like the Cloud SQL Proxy service, we can enable PHP-FPM to start at boot and begin executing;

sudo systemctl enable php-fpm
sudo systemctl start php-fpm

We have also created a home directory for the user in . In order to serve files the appropriate file context must be set, otherwise SELinux will block the process from serving the MantisBT application.

sudo semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"

Installation of MantisBT just requires downloading and extracting the source code.

cd /srv/wwwsudo -u www-data curl -O "https://kent.dl.sourceforge.net/project/mantisbt/mantis-stable/2.6.0/mantisbt-2.6.0.tar.gz"sudo -u www-data tar xf mantisbt-2.6.0.tar.gz
sudo -u www-data mv mantisbt-2.6.0 mantisbt
sudo -u www-data rm -rf .pki mantisbt-2.6.0.tar.gz

Caddy

Caddy offers an array of features for a modern web server of which simple configuration, secure defaults and automatic certificate setup and renewal with Let’s Encrypt stood out.

Given the low traffic my instance will be receiving, Caddy or rather any web server will be sufficient at serving requests. However, as with other decisions made throughout this article, you may wish to seek an alternative if this does not scale to your needs.

There are several ways of obtaining Caddy, either through the download or release pages. If you choose this method, please observe the license details when using the official Caddy binaries. Alternatively, you can build Caddy from source as follows;

sudo yum install golang git
go get github.com/mholt/caddy/caddy
sudo cp `go env GOPATH`/bin/caddy /usr/local/bin

We need to set some additional properties on the Caddy binary to allow for it to bind to ports 80 and 443 without being root and additionally for SELinux;

sudo setcap cap_net_bind_service=+ep /usr/local/bin/caddy
sudo semanage fcontext -a -t httpd_exec_t /usr/local/bin/caddy
sudo restorecon /usr/local/bin/caddy
sudo setsebool -P httpd_can_network_connect_db on

This gist provided helpful guidance on setting SELinux properties for Caddy.

Like other services installed, we will setup a systemd service unit following this example as a guide. To begin with, create the necessary directories;

sudo mkdir /etc/caddy
sudo chown -R root:www-data /etc/caddy
sudo mkdir /etc/ssl/caddy
sudo chown -R www-data:root /etc/ssl/caddy
sudo chmod 0770 /etc/ssl/caddy

Caddy will use the directory for the Let’s Encrypt certificate. With SELinux in enforcing mode, Caddy will be unable to write to this directory despite the user permissions. We must further set the file context just like the MantisBT install.

sudo semanage fcontext -a -t httpd_sys_rw_content_t /etc/ssl/caddy
sudo restorecon /etc/ssl/caddy

Next we will create what is called the , the configuration file for Caddy. Place the following contents in the file . Replace with the domain you configured an A record for earlier when creating the address for the instance. Alternatively you can use the IP address here, however you will not be issued a certificate nor connect securely to the MantisBT instance. Also replace with your email address to agree to the subscriber agreement.

DOMAIN_NAME
tls EMAIL_ADDRESS
root /srv/www/mantisbt
gzip
status 404 {
/composer
/config
/core
/doc
/lang
/library
/plugins
/scripts
/vendor
}
fastcgi / 127.0.0.1:9000 php
log stdout
errors stderr

And update permissions;

sudo chown www-data:www-data /etc/caddy/Caddyfile
sudo chmod 444 /etc/caddy/Caddyfile

Fetch the systemd unit file from the guide;

cd ~/
curl -O https://raw.githubusercontent.com/mholt/caddy/master/dist/init/linux-systemd/caddy.service

And set the service to be enabled as well as starting Caddy;

sudo mv caddy.service /etc/systemd/system/
sudo chown root:root /etc/systemd/system/caddy.service
sudo chmod 644 /etc/systemd/system/caddy.service
sudo systemctl daemon-reload
sudo systemctl enable caddy.service
sudo systemctl start caddy.service

Review the output for Caddy, you should see logging with regards to a certificate being issued successfully and written to disk.

journalctl -u caddy

By visiting your domain you should now see the page to setup and configure the database over a secure connection.

MantisBT Configuration

MantisBT Pre-Install Checklist

When visiting your domain you will be automatically redirected to the MantisBT installer. You should see the above checklist with “GOOD” for each of the corresponding items.

Further down are the installation options for you to fill in. Mainly, type of database (postgres), the database server (127.0.0.1, as we are using a local proxy), username (postgres) and the password setup earlier. Lastly a database name (mantisbt). You can see these options in the screenshot below.

MantisBT Installation Options

Click “Install/Upgrade Database”.

On the following page the installer attempts to write to but fails due to SELinux. This is OK, follow the instructions and copy the config it produced into the file;

sudo -u www-data vim /srv/www/mantisbt/config/config_inc.php

At the same time, there are many configuration options you may also wish to set. Using this as a personal instance, I have opted to disable signup for example by adding the following to the file.

$g_allow_signup = OFF;

You may have also noticed the instructions to remove the directory as well as change the administrator password. This is critical for security reasons. You can remove the directory with;

sudo -u www-data rm -rf /srv/www/mantisbt/admin

To change the administrator password, first login with the default credentials. The username is “administrator” and the password is “root”, both without quotes. You will be prompted to change the password then.

Section Recap

In this section you have installed and configured the necessary applications and services for the MantisBT deployment. This has included;

  • Setup Cloud SQL Proxy as a service
  • Installed PHP-FPM and reconfigured to use the user
  • Fetched the MantisBT source code
  • Deployed Caddy as a service
  • Set appropriate permissions, capabilities and file contexts for SELinux.
  • Created a simple Caddyfile
  • Installed and configured MantisBT through the web interface.

Closing Remarks

Congratulations, you now have an instance of MantisBT running on Google Cloud Platform. The Admin Guide provides more insight into further setup of MantisBT which you may find helpful.

I’m sure you will agree we have covered a significant amount of material. I hope this has been useful to you and have learned something along the way. I appreciate any feedback or responses so feel free to comment!

Google Cloud - Community

A collection of technical articles published or curated by…

rsclarke

Written by

rsclarke

Security researcher and digital exploration enthusiast. https://rsclarke.io

Google Cloud - Community

A collection of technical articles published or curated by Google Cloud Developer Advocates. The views expressed are those of the authors and don't necessarily reflect those of Google.

More From Medium

More from Google Cloud - Community

More from Google Cloud - Community

Define new paths with routing

More from Google Cloud - Community

More from Google Cloud - Community

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade