Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
deargle committed Nov 8, 2019
0 parents commit 3ab7c65
Show file tree
Hide file tree
Showing 54 changed files with 2,176 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Berksfile
@@ -0,0 +1,3 @@
source 'https://supermarket.chef.io'

cookbook 'apt'
5 changes: 5 additions & 0 deletions Berksfile.lock
@@ -0,0 +1,5 @@
DEPENDENCIES
apt

GRAPH
apt (7.2.0)
98 changes: 98 additions & 0 deletions README.md
@@ -0,0 +1,98 @@
# Pentest lab on GCP using Terraform, Chef, Ansible, and Vagrant

_Because why not use all the things?_

This repo is a general stash of my setup for how I provisioned and managed a vpn private network, including a
to-be-assessed ultra-vulnerable server, for each of twenty teams in my information security management class, Fall 2019.

I wanted to be able to borrow from and contribute back to [metasploitable3's ub1404 project](https://github.com/rapid7/metasploitable3), so I used chef for provisioning
the vulnerable server. I used vagrant to play the chef recipe provisioning on top of a `ubuntu-1404-lts` gcp box. When the midterm
server was mostly complete, I manually created a gcp image of it. I could have used [packer to create the image via chef-solo](https://www.packer.io/docs/provisioners/chef-solo.html).

I used terraform to create a workspace for each team. Each workspace has:

* an isolated vpc
* firewall rules allowing only ssh from the outside world, but allowing all traffic on the private network
* an openvpn server provisioned via a customized easy-openvpn script
* a copy of a vulnerable server based on the most recent image from my image family for the vuln server.

I used a few bash scripts for automating the process of managing all 20 workspaces -- for `terraform apply`ing, etc. Naturally, I had to do
some hot fixes to the vulnerable servers in the middle of the assignment timeframe. While I could have updated the base vuln server image and
had terraform tear down and recreate each of the vuln servers for each workspace, this led to too much downtime for the students, and was too
tedious for me. So, I initially looked to using a Chef Server for managing each vuln server. But I gave up on this when I hit some gotchas with
trying to automate the `knife` provisioning of each vuln server with the Chef Server. I switched to ansible instead, dynamically creating
the ansible inventory file from a script iterating over `terraform output` which spit out each workspace's vuln server ip. The ansible
playbook uploads a zip of the within-project chef recipes, runs them on the server, and then deletes the zip. I'm sure there's a cleaner
way to do that, but hey, it's fast and easy, and it works.

I'm removing most of my chef recipes from this public repo -- except for the basic functionality ones -- just to make it harder for nosy students to complete the midterm task. On the other hand,
heh, they're business school students, they probably can't read ruby anyhow.



## GCP

I created a gcp project specifically for this midterm assignment.
I also `ssh-keygen` created a private-public keypair specifically for provisioning for this project,
and I added this public key to the gcp project metadata, with username `_provisioner`. In the files in this
repo, I also added this private-public keypair as user `tyler`'s. That's what the reference to `tyler-midterm-vuln` is
in some of the config files. It's used to connect as the `_provisioner`.

I also created a gcp service account for this project (can't remember what permissions I gave it), and I downloaded it as json
and called it `midterm-vuln-gcp-private-key.json`.


## Vagrant and Chef

Run these:

vagrant plugin install vagrant-vbguest
vagrant plugin install vagrant-google

The chef-solo runlist is read from a file `chef_runlist`, because the ansible playbook also needs it.

Do your initial vuln midterm server creation using `vagrant up`, `vagrant provision`, etc. When you're satisfied, create a gcp image
from your instance. For compatibility with this repo's terraform config (`main.tf`), call your image family `midterm-vuln`.

I managed external chef cookbook dependencies using `berks`, which is provided by the `ChefDK`. Running `berks vendor` puts the berks cookbooks in a separate directory (IIRC).



## Terraform

I named my teams like this: `team-<team_number`. A convenience script in `scripts/create_all.sh` helps with the creation of all workspaces.

Terraform round-robin creates the workspaces in one of five regions. This is because I hit gcp quota limits for public ips -- max 8 per region by default, and surprise, they didn't
want to allow me to jump up to 40 ips for one region without me going through sales first. That's this part:

locals {
vpn_config_dir = "vpn_configs"
gcp_regions = ["us-central1","us-east1","us-east4","us-west1","us-west2"]
team_number_split = split("-",terraform.workspace)
team_number = length(local.team_number_split) > 1 ? local.team_number_split[1] : 1
google_region = local.gcp_regions[(local.team_number - 1) % length(local.gcp_regions)]
}


My vuln midterm server "company" was called `humbleify` (`resource "google_compute_instance" "midterm-vuln"`). The humbleify server was given an ip address of `192.168.10.107`.

The vpn server was provisioned via (`resource "google_compute_instance" "openvpn"`). It is based on gcp image debian-9. It is provisioned (`resource "null_resource" "openvpn_bootstrap"`) via `openvpn-install.sh`,
which is a fork of `https://raw.githubusercontent.com/angristan/openvpn-install/master/openvpn-install.sh`. This vpn server has some crucial key differences from one used solely as a tunnel for an
individual computer's traffic:

* It allows clients on the vpn network to see and talk to one another
* It allows multiple clients to simultaneously use the same config file.

After the vpn server is bootstrapped, the `client.conf` config file is `scp`'ed down to `vpn_configs/`, and then uploaded to the vuln midterm server (`resource "null_resource" "openvpn_upload_midtermvuln_vpn_config").
I had already installed the openvpn package on the midterm servers in my base image.


## Ansible hot-patching

I dynamically managed the inventory by running `scripts/get_all_ips.sh`, which relies on `output "midterm_vuln_ip"` and `output "team-name"` being provided by the terraform workspaces.

I created a `team-999` workspace that I used for testing my chef recipe live provision hot-fixes. `scripts/ansible-playbook-999.sh` runs the ansible playbook for just `team-999`.
After the success of the hot-patch was confirmed, I ran `scripts/ansible-playbook.sh`.


48 changes: 48 additions & 0 deletions Vagrantfile
@@ -0,0 +1,48 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :


# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
# Vagrant::DEFAULT_SERVER_URL.replace('https://vagrantcloud.com')
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.

# Every Vagrant development environment requires a box. You can search for
# boxes at https://vagrantcloud.com/search.

config.vm.define "gcp" do |gcp|
gcp.vm.box = 'google/gce'
gcp.vm.box_version = "0.1.0"

gcp.vm.provider :google do |google, override|
google.google_project_id = "midterm-vuln"
google.name = 'midterm-vuln'
google.google_json_key_location = "midterm-vuln-gcp-private-key.json"

# google.external_ip = true
google.image_family = 'ubuntu-1404-lts'
# vagrant@terraform-255421.iam.gserviceaccount.com
override.ssh.username = "_provisioner"
override.ssh.private_key_path = "tyler-midterm-vuln"
end
end


# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# config.vm.synced_folder '.', '/vagrant', disabled: true

config.vm.provision "chef_solo" do |chef|
chef.arguments = '--chef-license accept'
chef.cookbooks_path = ['cookbooks','berks-cookbooks']
run_list = File.read('chef_runlist')
end

end
2 changes: 2 additions & 0 deletions ansible.cfg
@@ -0,0 +1,2 @@
[defaults]
host_key_checking = False

0 comments on commit 3ab7c65

Please sign in to comment.