- Go 93.7%
- HTML 3.4%
- JavaScript 2.4%
- CSS 0.4%
- Ruby 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| app/concourse | ||
| cmd/concourse | ||
| internal/concourse | ||
| media | ||
| schemas | ||
| sql | ||
| sqlc | ||
| .gitignore | ||
| .golangci.yml | ||
| .goreleaser.yaml | ||
| .markdownlint.yaml | ||
| .svu.yml | ||
| Brewfile | ||
| CHANGELOG.md | ||
| commitlint.config.mjs | ||
| CONFIG.md | ||
| CREDENTIALS.md | ||
| eslint.config.js | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| sqlc.yaml | ||
| stave.yaml | ||
| stavefile.go | ||
concourse
Downloading
Just grab release for your specific architecture and OS from https://fergie.omer.land/omer/concourse/releases.
And you can of course also build from source!
Burning questions
What are the default/initial login credentials for the web UI???
Stop. Take a deep breath.
This is gonna be a bit more complicated than you're probably used to. But don't worry, it's not really that complicated.
concourse is a security tool. As such, it does not make sense to let whoever-happens-to-grab-the-reins-of-the-web-UI-first to be able to, through some "first use" flow, set the admin credentials & thus gain permanent access to / control of the system.
We want to make sure that the person who installed concourse is also the one who gets to set the admin credentials.
But how? Certainly, just putting the credentials in plaintext in some config file would not do. That's trouble. As is placing the credentials in plaintext in an environment variable, since environment variables are fairly easy to exfiltrate.
That's why, in concourse, you initialize the admin credentials this way.
Okay, so how do I configure this thing?
Awesome. How do I configure my TOTP?
Using the web API. (You can configure the bind-address like this, and the server also prints the URL to stdout when it's done starting up.)
Okay, enough with the rapid-fire questions. What does this thing even do?
What it does
Concourse is a sort of SSH-proxy meets SSH-bastion.
It is (heavily!) inspired by Warpgate, but it works a little differently:
- Concourse runs on your computer AS a particular user.
- You
sshinto Concourse with a username like<username>%<eventual_target_machine>@<host_where_concourse_is_running>. (Though there are other options.) - There are then two layers of authentication:
-
You authenticate with Concourse -
- Using the password you have configured
- Or using a private key, whose public-key counterpart is in the
authorized_keysof the user you're running Concourse as, on the machine where Concourse is running.
-
Concourse then proxies your SSH session to a session on
<eventual_target_machine>.- If there is a private key, available to the user you're running Concourse as, on the machine where Concourse is running, that can be used to authenticate with
<eventual_target_machine>, it will be used. - Otherwise, password (or other keyboard-interactive) authentication will be used.
- If there is a private key, available to the user you're running Concourse as, on the machine where Concourse is running, that can be used to authenticate with
-
Why you might want it
OKAY, WHAT DOES THIS GIVE ME, ABOVE & BEYOND REGULAR, DIRECT SSH...?
Two big things:
- Rate-limiting.
- Policy-driven TOTP, alongside password or private-public key authentication.
Rate-limiting
Concourse has highly configurable rate-limiters keyed on the following properties of SSH sessions:
- IP that the original SSH request is coming from
- IP of
<eventual_target_machine> - Account on
<eventual_target_machine>
As well as on the following properties of web sessions (used for creating & managing TOTP configs):
- IP that the HTTP request is coming from
- Account for web UI login
TOTPs (Temporary One-Time Passwords)
Concourse can add a TOTP layer above & beyond the password or private-public key authentication.
It supports:
- Defining multiple "TOTP configs" (meaning, TOTPs with different secrets).
- Configuring whether a TOTP will be required - and if so, which config it will be validated against - based on the IP or CIDR the SSH login is coming from.
- The TOTP rules configuration evaluates IP/CIDR rules in order, which allows defining rules for entire subnets that will apply only if an earlier IP-specific rule was not matched. (See here for an example.)
TOTPs are configured through the web UI -
- a QR is displayed when a new TOTP config is created (alongside a textual representation of the secret)
- which you can use with an authenticator app to set up a generator for your new TOTP config
If you leave the "Name" field of the TOTP config empty, future logins to this account via the web API will also require a matching TOTP. (Though the empty-named TOTP config can also be used for second-factor SSH authentication, like any other, named TOTP config).
Note
By default, the Concourse web-server only binds to
localhost:9923.It is only intended for the kind of local setup discussed here, and use-cases for remote access to the web UI are rather unlikely.
For that reason, Concourse serves this web UI over plain HTTP.
If you absolutely need to serve this web UI non-locally, it is HIGHLY recommended to place it behind a reverse proxy (such as caddy) that does TLS termination - otherwise your security posture will be severely compromised.
For instructions on how to set the initial login credentials for the web UI - which will also be the credentials for the first hop of your SSH session, should a password be required – see CREDENTIALS.md.
SSH address binding, and whitelisting
In addition to the TOTP-specific rules, you can set the bind_address for the SSH server. (It defaults to localhost:2223, which is probably not of much use unless you set it to something broader.)
Furthermore, there is support for whitelisting. By default, the whitelist is empty, which means the whitelisting functionality is disabled. But if you populate it with one or more entries, only source IPs matching those entries (which can be IP addressed or CIDRs, with both IPv4 and IPv6 supported)will be allowed to log in to the SSH server. This is separate from the server binding to a particular address, and offers another line of defense.
A typical setup
With all of the above in mind, a typical way to use Concourse is as follows:
- Restrict the standard
sshdrunning on the machines on your LAN so that it only accepts connections fromlocalhostand the LAN IP of the machine where Concourse is running.- Example:
AllowUsers *@localhost *@127.0.0.1 *@::1 192.168.1.42
- Run Concourse with a broader
bind_address(and whitelist, if applicable), and when away from your LAN,sshto your machines through Concourse - which will provide both rate-limiting and TOTP protection.
Composite usernames & their interpretation
In the discussion above, an example of a composite username of the following form was given:
<username>%<eventual_target_machine>@<host_where_concourse_is_running>
The composite username - the portion prior to the @ - is considerably more flexible.
Delimiters
The following delimiters are supported (and can be mixed & matched as you please):
- percentage sign (
%) - hash mark (
#) - colon (
:)
Note
While all three delimiters work with the
sshCLI, at least some versions of thescpCLI require that you use%in particular.Which is why the examples in this document all use
%.
Pre-@ fields
None
SSH targets of the form <hostname> (with no @ nor, obviously any pre-@ fields) are interpreted as:
| CONCOURSE USER: | same as $USER on the source machine |
| CONCOURSE HOST: | <hostname> |
| DESTINATION HOST: | <hostname> (i.e., same host) |
| DESTINATION USER on DESTINATION HOST: | same as $USER on the source machine |
| DESTINATION PORT on DESTINATION HOST: | 22 |
One
SSH targets of the form foo@<hostname> are interpreted as:
| CONCOURSE USER: | foo |
| CONCOURSE HOST: | <hostname> |
| DESTINATION HOST: | <hostname> (i.e., same host) |
| DESTINATION USER on DESTINATION HOST: | foo |
| DESTINATION PORT on DESTINATION HOST: | 22 |
Two
SSH targets of the form foo%bar@<hostname> are interpreted as:
| CONCOURSE USER: | foo |
| CONCOURSE HOST: | <hostname> |
| DESTINATION HOST: | bar |
| DESTINATION USER on DESTINATION HOST: | foo |
| DESTINATION PORT on DESTINATION HOST: | 22 |
Three
SSH targets of the form foo%bar%baz@<hostname> are interpreted as:
| CONCOURSE USER: | baz |
| CONCOURSE HOST: | <hostname> |
| DESTINATION HOST: | bar |
| DESTINATION USER on DESTINATION HOST: | foo |
| DESTINATION PORT on DESTINATION HOST: | 22 |
Four
SSH targets of the form foo%bar%12345%baz@<hostname> are interpreted as:
| CONCOURSE USER: | baz |
| CONCOURSE HOST: | <hostname> |
| DESTINATION HOST: | bar |
| DESTINATION USER on DESTINATION HOST: | foo |
| DESTINATION PORT on DESTINATION HOST: | 12345 |
Building from source
Concourse uses stave (a fork of mage) as its build system.
To build this project from source:
- Clone the repo.
- Grab
stave. - Run
stave buildto build Concourse from source. - Or run
stave -lto see other things you can do.
License
This software is released under the Apache License 2.0.