{"id":13448990,"url":"https://github.com/AnalogJ/drawbridge","last_synced_at":"2025-03-22T18:32:17.444Z","repository":{"id":47508478,"uuid":"128282529","full_name":"AnalogJ/drawbridge","owner":"AnalogJ","description":"manage SSH access to multiple applications/environments protected by bastion servers","archived":false,"fork":false,"pushed_at":"2024-07-26T10:29:31.000Z","size":8116,"stargazers_count":219,"open_issues_count":12,"forks_count":9,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-03-16T05:11:49.258Z","etag":null,"topics":["bastion","ssh","tunnel"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AnalogJ.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-06T01:12:33.000Z","updated_at":"2025-02-11T15:50:26.000Z","dependencies_parsed_at":"2024-10-28T14:21:23.285Z","dependency_job_id":"7414c107-b56b-4158-844b-ae7c6f06beff","html_url":"https://github.com/AnalogJ/drawbridge","commit_stats":{"total_commits":134,"total_committers":6,"mean_commits":"22.333333333333332","dds":0.6417910447761195,"last_synced_commit":"4e58fc35c76dc207f94da272d44586b79c6a7dbf"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnalogJ%2Fdrawbridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnalogJ%2Fdrawbridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnalogJ%2Fdrawbridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnalogJ%2Fdrawbridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AnalogJ","download_url":"https://codeload.github.com/AnalogJ/drawbridge/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245002950,"owners_count":20545521,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bastion","ssh","tunnel"],"created_at":"2024-07-31T06:00:27.391Z","updated_at":"2025-03-22T18:32:12.424Z","avatar_url":"https://github.com/AnalogJ.png","language":"Go","funding_links":[],"categories":["Go","Bastion Host","others"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/AnalogJ/drawbridge\"\u003e\n  \u003cimg width=\"300\" alt=\"drawbridge_view\" src=\"https://rawgit.com/AnalogJ/drawbridge/master/logo.svg\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n# Drawbridge\n\n[![Circle CI](https://img.shields.io/circleci/project/github/AnalogJ/drawbridge.svg?style=flat-square)](https://circleci.com/gh/AnalogJ/drawbridge)\n[![Coverage Status](https://img.shields.io/codecov/c/github/AnalogJ/drawbridge.svg?style=flat-square)](https://codecov.io/gh/AnalogJ/drawbridge)\n[![GitHub license](https://img.shields.io/github/license/AnalogJ/drawbridge.svg?style=flat-square)](https://github.com/AnalogJ/drawbridge/blob/master/LICENSE)\n[![Godoc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](https://godoc.org/github.com/analogj/drawbridge)\n[![Go Report Card](https://goreportcard.com/badge/github.com/AnalogJ/drawbridge?style=flat-square)](https://goreportcard.com/report/github.com/AnalogJ/drawbridge)\n[![GitHub release](http://img.shields.io/github/release/AnalogJ/drawbridge.svg?style=flat-square)](https://github.com/AnalogJ/drawbridge/releases)\n[![Github All Releases](https://img.shields.io/github/downloads/analogj/drawbridge/total.svg?style=flat-square)](https://github.com/AnalogJ/drawbridge/releases)\n\nBastion/Jumphost tunneling made easy\n\n# Introduction\n\u003e A Jump/Bastion host is a special purpose computer on a network specifically designed and configured to withstand attacks.\n\u003e The computer generally hosts a single application, for example a proxy server, and all other services are removed or limited to reduce the threat to the computer.\n\u003e It is hardened in this manner primarily due to its location and purpose, which is either on the outside of a firewall or in a demilitarized zone (DMZ) and usually involves access from untrusted networks or computers.\n\u003e - [Bastion Host - Wikipedia](https://en.wikipedia.org/wiki/Bastion_host)\n\nIn secure cloud architectures, jump/bastion hosts are the primary method to access the internal/protected network.\nThis means that all traffic can be audited, and that a single server can be shut down in the event that the network is compromised.\n\n\nHowever as this architecture is scaled up and deployed across multiple environments (testing, staging, production), it can\nbe complicated to maintain a single `~/.ssh/config` file that allows you to tunnel into your various jump host protected internal networks.\n\nDrawbridge aims to solve this problem in a flexible and scalable way.\n\n\n# Features\n\n- Single binary (available for macOS and linux), only depends on `ssh`, `ssh-agent` and `scp`\n- Uses customizable templates to ensure that Drawbridge can be used by any organization, in any configuraton\n- Helps organize your SSH config files and PEM files\n- Generates SSH Config files for your servers spread across multiple environments and stacks.\n\t- multiple ssh users/keypairs\n\t- multiple environments\n\t- multiple stacks per environment\n\t- etc..\n- Can be used to SSH directly into an internal node, routing though bastion, leveraging SSH-Agent\n- Able to download files from internal hosts (through the jump/bastion host) using SCP syntax\n- Supports HTTP proxy to access internal stack urls.\n- Lists all managed config files in a heirarchy that makes sense to your organization\n- Custom templated files can be automatically generated when a new SSH config is created.\n\t- eg. Chef knife.rb configs, Pac/Proxy files, etc.\n- Cleanup utility is built-in\n- `drawbridge update` lets you update the binary inplace.\n- Pretty colors. The CLI is all colorized to make it easy to skim for errors/warnings\n- Assign memorable aliases to commonly used configurations\n\n# Getting Started\n\n1. Download the latest release binary from the [Releases](https://github.com/AnalogJ/drawbridge/releases) page for your OS. (Mac, Windows \u0026 Linux available)\n2. Rename the downloaded binary to `drawbridge`\n3. Run `chmod +x drawbridge`\n4. Move the renamed binary into your path, eg. `/usr/bin/local`\n5. Run `drawbridge help` from a terminal to confirm it was installed correctly\n6. Add a configuration file to `~/drawbridge.yaml`. See [Configuration](#configuration) section.\n\n# Usage\n\n```\n$ drawbridge help\n ____  ____    __    _    _  ____  ____  ____  ____    ___  ____\n(  _ \\(  _ \\  /__\\  ( \\/\\/ )(  _ \\(  _ \\(_  _)(  _ \\  / __)( ___)\n )(_) ))   / /(__)\\  )    (  ) _ \u003c )   / _)(_  )(_) )( (_-. )__)\n(____/(_)\\_)(__)(__)(__/\\__)(____/(_)\\_)(____)(____/  \\___/(____)\ngithub.com/AnalogJ/drawbridge                 darwin.amd64-1.0.10\n\nNAME:\n   drawbridge - Bastion/Jumphost tunneling made easy\n\nUSAGE:\n   drawbridge [global options] command [command options] [arguments...]\n\nVERSION:\n   1.0.10\n\nAUTHOR:\n   Jason Kulatunga \u003cjason@thesparktree.com\u003e\n\nCOMMANDS:\n     create         Create a drawbridge managed ssh config \u0026 associated files\n     list           List all drawbridge managed ssh configs\n     connect        Connect to a drawbridge managed ssh config\n     alias          Create a named alias for a drawbridge config\n     download, scp  Download a file from an internal server using drawbridge managed ssh config, syntax is similar to scp command.\n     delete         Delete drawbridge managed ssh config(s)\n     proxy          Build/Rebuild a Proxy auto-config (PAC) file to access websites through Drawbridge tunnels\n     update         Update drawbridge to the latest version\n     help, h        Shows a list of commands or help for one command\n\nGLOBAL OPTIONS:\n   --help, -h     show help (default: false)\n   --version, -v  print the version (default: false)\n\n```\n\n# Actions\n\n## Create\n\nUsing the `questions` \u0026 `config_template` defined in the configuration file (`~/drawbridge.yaml`) Drawbridge will attempt to\ngenerate a managed ssh config file. Drawbrige will prompt the user for any questions which it is unable to determine an\nanswer (no default value and no flag value specified).\n\nQuestions \u0026 Templates can be customized completely to match your organization.\n\n```\n$ drawbridge create --environment prod --shard us-west-2\n\nCurrent Answers:\nenvironment: prod\nshard: us-west-2\nstack_name: app\nPlease enter a value for `shard_type` [string] - Is this a live (green) or idle (blue) stack?:\nidle\nPlease enter a value for `username` [string] - What username do you use to login to this stack?:\naws\nWARNING: PEM file missing. Place it at the following location before attempting to connect. /Users/jason/.ssh/drawbridge/pem/prod/aws-prod.pem\nWriting template to /Users/jason/.ssh/drawbridge/prod-app-idle-us-west-2\n\n```\n\nYou can also enable `DRYRUN` mode to see exactly what files Drawbrige would generate, without actually writing any files.\n\n```\n$ drawbridge create --environment prod --dryrun\n...\n2018/04/22 23:56:23 Writing template to /Users/jason/.ssh/drawbridge/prod-app-idle-us-west-1\n[DRYRUN] Would have written content to /Users/jason/.ssh/drawbridge/prod-app-idle-us-west-1:\n\n# This file was automatically generated by Drawbridge\n# Do not modify.\n#\n...\n```\n\n\n## Connect\n```\n$ drawbridge connect\nRendered Drawbridge Configs:\n├── [prod]  environment\n│   └── [app]  stack_name\n│       ├── [us-east-1]  shard\n│       │   ├── [1]  shard_type: idle, username: aws\n│       │   └── [2]  shard_type: live, username: aws\n│       └── [us-east-2]  shard\n│           ├── [3]  shard_type: idle, username: aws\n│           └── [4]  shard_type: live, username: aws\n├── [stage]  environment\n│   └── [app]  stack_name\n│       └── [us-east-2]  shard\n│           ├── [5]  shard_type: idle, username: aws\n│           └── [6]  shard_type: live, username: aws\n└── [test]  environment\n    └── [app]  stack_name\n        ├── [us-east-1]  shard\n        │   ├── [7]  shard_type: idle, username: aws\n        │   └── [8]  shard_type: live, username: aws\n        └── [us-east-2]  shard\n            ├── [9]  shard_type: idle, username: aws\n            └── [10]  shard_type: live, username: aws\n\nEnter number of drawbridge config you would like to connect to (1-10, alias):\n```\n\n`drawbridge connect` will connect you to the bastion/jump host using a specified Drawbridge config file. It'll also add\nthe associated PEM key to your `ssh-agent`.\n\nIf you want to connect directly to a internal server, you can do so by selecting a config id and specifying the hostname/short name\n\n`drawbridge connect 1 database-1`\n\nYou can also connect directly to a environment using an alias\n\n`drawbridge connect my_custom_alias database-1`\n\n## Alias\n\nYou can assign an alias to a commonly used drawbridge configuration by using the `drawbridge alias` command.\n\n```\n$ drawbridge alias\n...\n        └── [us-east-2]  shard\n            ├── [9]  shard_type: idle, username: aws\n            └── [10]  shard_type: live, username: aws\n\nEnter drawbridge config number to create alias for (1-2, alias):\n10\nPlease provide an alias for the configuration above (a-zA-Z0-9-_.):\nmy_new_alias\nSetting alias (my_new_alias) for config (10)\n\n```\nNow when you run `drawbridge connect`, `drawbridge list` or most other drawbridge commands, you can use the alias instead of the id.\n\n```\n$ drawbridge list\n...\n        └── [us-east-2]  shard\n            ├── [9]  shard_type: idle, username: aws\n            └── [10, my_new_alias]  shard_type: live, username: aws\n\n\n$ drawbridge connect my_new_alias\n...\n```\n\nYou can also set the alias for a configuration in one command:\n\n```\n$ drawbridge alias 10 my_custom_alias\n\nSetting alias (my_custom_alias) for config (10)\nWarning: replacing existing alias (my_new_alias) with new value: my_custom_alias\n```\n\n## Delete\n\n```\n$ drawbridge delete\n...\n        └── [us-east-2]  shard\n            ├── [9]  shard_type: idle, username: aws\n            └── [10]  shard_type: live, username: aws\n\nEnter number of drawbridge config you would like to delete:\n10\nAre you sure you would like to delete this config and associated templates? (PEM files will not be deleted)\n\nenvironment: test\nshard: us-east-2\nshard_type: live\nstack_name: app\nusername: aws\n\nPlease confirm [true/false]:\ntrue\nDeleting config file: /Users/jason/.ssh/drawbridge/test-app-live-us-east-2\nDeleting answers file\nFinished\n\n```\n\nYou can use the `--force` flag to disable the confirm prompt. The `--all` flag can be used to delete all Drawbridge managed\nconfigs in one command.\n\nYou can use the following command to completely wipe out all Drawbridge files and start over.\n\n`drawbridge delete --all --force`\n\n\n## Update\n\n```\n$ drawbridge update\n\nUpdate drawbridge to the latest version\nCurrent: v1.0.9 [2018-04-26]. Available: v1.0.10 [2018-04-27]\nRelease notes are available here: https://github.com/AnalogJ/drawbridge/releases/tag/v1.0.10\nAre you sure you would like to update drawbridge to v1.0.10?\nPlease confirm [yes/no]:\n\n```\n\n## Download\n\n```\n$ drawbridge scp 1 database-1:/tmp/test-file.txt ~/test-file.text\n\nDownload a file from an internal server using drawbridge managed ssh config, syntax is similar to scp command. \nAdding PEM key to ssh-agent\nBegin downloading file through bastion\ntest-file.text                                                      100% 4099     4.4KB/s   00:00    \n\n```\n\nDownloading files through the bastion is simple and easy. \n\n## Proxy\n\n```\n$ drawbridge proxy\nBuild/Rebuild a Proxy auto-config (PAC) file to access websites through Drawbridge tunnels\nPac file already exists, updating.\n2018/04/27 15:31:55 Writing template to ~/drawbridge.pac\n```\n\nPAC files, when used with a compatible browser, allow you to access internal dashboards and websites as you would any publicly accessible site. \n \nAs you create Drawbride configurations, just run `drawbridge proxy` to update the PAC file, written to `~/drawbridge.pac` by default. \n\n\n# Configuration\nWe support a global YAML configuration file that must be located at `~/drawbridge.yaml`\n\nCheck the [example.drawbridge.yml](https://github.com/AnalogJ/drawbridge/blob/master/example.drawbridge.yaml) file for a fully commented version.\n\n# Testing [![Circle CI](https://img.shields.io/circleci/project/github/AnalogJ/drawbridge.svg?style=flat-square)](https://circleci.com/gh/AnalogJ/drawbridge)\nDrawbridge provides an extensive test-suite based on `go test`.\nYou can run all the integration \u0026 unit tests with `go test $(go list ./... | grep -v /vendor/)`\n\nCircleCI is used for continuous integration testing: https://circleci.com/gh/AnalogJ/drawbridge\n\n# Contributing\nIf you'd like to help improve Drawbridge, clone the project with Git and install dependencies by running:\n\n```\n$ git clone git://github.com/AnalogJ/drawbridge\n$ go mod vendor\n```\n\nWork your magic and then submit a pull request. We love pull requests!\n\nIf you find the documentation lacking, help us out and update this README.md.\nIf you don't have the time to work on Drawbridge, but found something we should know about, please submit an issue.\n\n\n# To-Do List\n\nWe're actively looking for pull requests in the following areas:\n\n- RDP/VNC generation \u0026 viewer.\n- Secure storage of PEM keys in keychain/keyring\n\n\n# Versioning\nWe use SemVer for versioning. For the versions available, see the tags on this repository.\n\n# Authors\nJason Kulatunga - Initial Development - @AnalogJ\n\n# License\n\n- MIT\n- [Logo: Castle by Jemis mali from the Noun Project](https://thenounproject.com/search/?q=castle\u0026i=1063814)\n\n\n# References\n\n- https://github.com/moul/awesome-ssh/blob/master/README.md\n- https://github.com/dbrady/ssh-config\n- https://github.com/k4m4/terminals-are-sexy\n- https://github.com/n1trux/awesome-sysadmin\n- https://github.com/cjbarber/ToolsOfTheTrade\n- https://github.com/dastergon/awesome-sre\n- https://stackoverflow.com/questions/17355667/replace-current-process\n- https://stats.stackexchange.com/questions/26344/how-to-uniformly-project-a-hash-to-a-fixed-number-of-buckets\n- moul/advanced-ssh-config\n- https://github.com/emre/storm\n- https://stackoverflow.com/questions/12484398/global-template-data\n- https://stackoverflow.com/questions/35612456/how-to-use-golang-template-missingkey-option\n- https://medium.com/@dgryski/consistent-hashing-algorithmic-tradeoffs-ef6b8e2fcae8\n- https://github.com/mitchellh/go-homedir\n- https://gobyexample.com/execing-processes\n- https://groob.io/posts/golang-execve/\n- https://www.digitalocean.com/community/tutorials/how-to-configure-custom-connection-options-for-your-ssh-client\n- https://github.com/zalando/go-keyring\n- https://github.com/tmc/keyring\n- https://github.com/jaraco/keyring\n- https://github.com/99designs/keyring\n- https://unix.stackexchange.com/questions/64795/must-i-store-a-private-key-in-a-file\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAnalogJ%2Fdrawbridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAnalogJ%2Fdrawbridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAnalogJ%2Fdrawbridge/lists"}