Skip to content

Commit

Permalink
Merge pull request #24 from seanmarpo/smarpo--add-totp-support
Browse files Browse the repository at this point in the history
Adding support for otp codes automatically
  • Loading branch information
tillson authored May 19, 2020
2 parents e44944c + fffcd36 commit 1d492bc
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 9 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ More information on methodologies is available in the [accompanying blog post](h
## Setup

1. Download the [latest release of GitHound](https://github.com/tillson/git-hound/releases)
2. Create a `./config.yml` or `~/.githound/config.yml` with your GitHub username and password. See [config.example.yml](config.example.yml).
2. Create a `./config.yml` or `~/.githound/config.yml` with your GitHub username and password. Optionally, include your 2FA TOTP seed. See [config.example.yml](config.example.yml).
1. If it's your first time using the account on the system, you may receieve an account verification email.
3. `echo "tillsongalloway.com" | git-hound`

Expand Down Expand Up @@ -67,6 +67,7 @@ For files that encode secrets, decodes base64 strings and searches the encoded s
* `--no-files` - Don't flag interesting file extensions
* `--only-filtered` - Only search filtered queries (languages)
* `--debug` - Print verbose debug messages.
* `--otp-code` - Github account 2FA code for sign-in. (Only use if you have authenticator 2FA setup on your Github account)

## User feedback
These are discussions about how people use GitHound in their workflows and how we can GitHound to fufill those needs. If you use GitHound, consider leaving a note in one of the active issues.
Expand Down
2 changes: 2 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func InitializeFlags() {
rootCmd.PersistentFlags().BoolVar(&app.GetFlags().NoGists, "no-gists", false, "Don't search Gists")
rootCmd.PersistentFlags().BoolVar(&app.GetFlags().NoRepos, "no-repos", false, "Don't search repos")
rootCmd.PersistentFlags().BoolVar(&app.GetFlags().Debug, "debug", false, "Enables verbose debug logging.")
rootCmd.PersistentFlags().StringVar(&app.GetFlags().OTPCode, "otp-code", "", "Github account 2FA token used for sign-in. (Only use if you have 2FA enabled on your account via authenticator app)")
}

var rootCmd = &cobra.Command{
Expand Down Expand Up @@ -72,6 +73,7 @@ var rootCmd = &cobra.Command{
client, err := app.LoginToGitHub(app.GitHubCredentials{
Username: viper.GetString("github_username"),
Password: viper.GetString("github_password"),
OTP: viper.GetString("github_totp_seed"),
})
// if client.
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions config.example.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Required
github_username: tillson
github_password: a8ueifjq4jkasdfoiulk
# Optional
github_totp_seed: ABCDEF1234567890 # Obtained via https://github.com/settings/two_factor_authentication/verify
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/go-git/go-git/v5 v5.0.0
github.com/google/go-github v17.0.0+incompatible
github.com/google/go-querystring v1.0.0 // indirect
github.com/pquerna/otp v1.2.0
github.com/spf13/cobra v0.0.7
github.com/spf13/viper v1.6.3
github.com/waigani/diffparser v0.0.0-20190828052634-7391f219313d
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
Expand Down Expand Up @@ -112,6 +114,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok=
github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
Expand Down
37 changes: 29 additions & 8 deletions internal/app/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ import (
"regexp"
"strconv"
"strings"
"time"

"github.com/google/go-github/github"
"github.com/pquerna/otp/totp"
)

// GitHubCredentials stores a GitHub username and password
type GitHubCredentials struct {
Username string
Password string
OTP string
}

// SearchOptions are the options that the GitHub search will use.
Expand Down Expand Up @@ -60,15 +63,9 @@ func LoginToGitHub(credentials GitHubCredentials) (httpClient *http.Client, err
if err != nil {
return nil, err
}
tty, err := os.Open("/dev/tty")
if err != nil {
log.Fatalf("can't open /dev/tty: %s", err)
}

fmt.Printf("Enter your GitHub 2FA code: ")
scanner := bufio.NewScanner(tty)
_ = scanner.Scan()
otp := scanner.Text()
otp := HandleOTPCode(credentials)

if strings.Index(resp.Request.URL.String(), "verified-device") > -1 {
resp, err = client.PostForm("https://github.com/sessions/verified-device", url.Values{

Expand All @@ -90,6 +87,30 @@ func LoginToGitHub(credentials GitHubCredentials) (httpClient *http.Client, err
return &client, err
}

// HandleOTPCode returns a user's OTP code for authenticating with Github by searching
// config values, then CLI arguments, then prompting the user for input
func HandleOTPCode(credentials GitHubCredentials) string {
var otp string
if credentials.OTP != "" {
// Generate a TOTP code based on TOTP seed in config
otp, _ = totp.GenerateCode(credentials.OTP, time.Now())
} else if GetFlags().OTPCode != "" {
// Use the provided CLI argument (--otp-code) for OTP code
otp = GetFlags().OTPCode
} else {
// Prompt the user for OTP code
tty, err := os.Open("/dev/tty")
if err != nil {
log.Fatalf("can't open /dev/tty: %s", err)
}
fmt.Printf("Enter your GitHub 2FA code: ")
scanner := bufio.NewScanner(tty)
_ = scanner.Scan()
otp = scanner.Text()
}
return otp
}

// GrabCSRFToken grabs the CSRF token from a GitHub page
func GrabCSRFToken(csrfURL string, client *http.Client) (token string, err error) {
resp, err := client.Get(csrfURL)
Expand Down
1 change: 1 addition & 0 deletions internal/app/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type Flags struct {
NoGists bool
NoRepos bool
ManyResults bool
OTPCode string
}

var flags Flags
Expand Down

0 comments on commit 1d492bc

Please sign in to comment.