Skip to content

Getting Started

Lee Baird edited this page Jun 19, 2023 · 21 revisions

Warning: Since the computer / server that runs Terry will dynamically generate SSH keys / certificates / etc, that device MUST BE SECURE. If you are not comfortable with that, stop what you are doing, clap your hands 4 times, and sing Happy Birthday in a southern accent. No just kidding, but you have been warned.

Step by Step

Before following this guide, make sure that you have pip3 installed.

  1. Install Python dependencies.
python3 -m pip install -r requirements.txt
  1. Copy config_example.yml to config.yml. Terry will look for the config at that location. You can store the config elsewhere and use the -c / --config flag to point Terry to that location.
cp config_example.yml config.yml
  1. Edit config.yml to your liking. At a minimum, edit the main_email and default_users map (of which the parent name is arbitrary). Here is an example of what that should look like.
# ===================== Miscellaneous Configurations =====================
ansible_configuration:
  global:
    main_email: joe.smith@acme.org
  # Default users for all systems
  default_users:
    terry:
      user: terry
      public_ip: 8.8.8.8 # Public IP of the user (this will be the only IP allowed in on port 22, SSH)
      public_key: # Either public key value or path to the public key file

Pro Tip: You can use a CIDR instead of an IP address for the public_ip. You can also add multiple users with corresponding IPs/CIDRs and SSH keys. For example, add a user for each operator on your red team.

  1. Copy ./configurations/container_mappings_example.yml to ./configurations/container_mappings.yml. Update it by following the Adding a Container documentation (only if you plan to build your resources with containers using the -cT flag, which I highly recommend). This step must be performed even if you do not plan on using containers. Additionally you will need to copy ./configurations/terraform_mappings_example.yml to ./configurations/terraform_mappings.yml.
cp configurations/container_mappings_example.yml configurations/container_mappings.yml
cp configurations/terraform_mappings_example.yml configurations/terraform_mappings.yml
  1. Install Terraform on your local system or download the binary. If you choose to download the binary, make sure you add the path to config.yml.
https://www.terraform.io/downloads
Ubuntu/Debian > LINUX BINARY DOWNLOAD > Amd64
unzip <package>
mv terraform /usr/local/bin/
rm <package>
  1. Install Nebula on your local system or download the binary. If you choose to download the binary, make sure you add the path to config.yml. If you do not plan on using Nebula for your builds, you can ignore this step.
  2. Install Git on your local system or download the binary. If you choose to download the binary, make sure you add the path to config.yml. If you do not plan on using remote_configurations for your builds, you can ignore this step.

Once all of this is complete, you are ready to get started. Check out the Usage Page to learn how Terry can help you!

Remote Configurations

Should you want to programmatically ingest configuration files in from a Git repository (should work with GitHub, GitLab, and other big Git-based VCS), you can add to the configuration by adding a list to ansible_configuration.remote in your Terry config file.

- name: team
  repo_url: github.com/<YOUR_GH_ORG>/<YOUR_GH_REPO>.git
  username: <YOUR_USERNAME>
  personal_access_token: <YOUR_PERSONAL_ACCESS_TOKEN>

In the case above, the contents of that repository will be ingested by Terry, parsed, and then added to the Ansible inventory file under the team key. For example, say we want to dynamically ingest all of your team's usernames, IP addresses, CIDRs, SSH keys from a GitHub repository so that all members on my team can access and edit their configuration should they cycle their SSH key or their ISP change their IP address.

In this use case, we created a private GitHub repository that contains JSON files in the root of the repository with each user's configuration.

https://github.com/ExampleOrg/ExampleRepo.git
  |--- team-member1.json
  |--- team-member2.json
  |--- team-member3.json
  |--- ...

If you have a remote configuration listed in your Terry config, Terry will clone this repository to the system he is running on to the /tmp/<RANDOM_GUID> directory, loop over the files in the root of the repository, and ingest all json OR yaml files. Then each json or yaml file will be ingested as a dictionary where each key is the root name of the file in the repo. Therefore, if you had the structure above and wanted to dynamically ingest user configurations, your json format should look like the following:

{
    "user": "<username>", // string
    "public_ip": "<1.1.1.1>", // string
    "public_key": "<public ssh key here>" // string
}

Assuming you had that json structure and the file / folder structure of the repo above, when Terry ingests the configuration, the team dictionary should contain the following:

team-member1:
  public_ip: 1.1.1.1
  public_key: ''
  user: team-member1
team-member2:
  public_ip: 2.2.2.2
  public_key: ''
  user: team-member2
team-member3:
  public_ip: 3.3.3.3
  public_key: ''
  user: team-member3
<...CONTINUED...>

If you notice, that is the same format as the ansible_configuration.default_users inside of the Terry config file. This is intentional as nw that default_users dictionary will be overwritten by the new dictionary above. If you have any questions on this, please open an issue.