Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jvehent committed May 22, 2020
1 parent a843c2e commit 589ad9e
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 6 deletions.
23 changes: 20 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,27 @@ jobs:
- image: circleci/golang:1.14
steps:
- checkout
- run: gpg --import sops_functional_tests_key.asc
- run: gpg --allow-secret-key-import sops_functional_tests_key.asc
- run: go test
- run: go run main.go test1
lint:
docker:
- image: circleci/golang:1.14
steps:
- checkout
- run: go get -u golang.org/x/lint/golint
- run: golint .
vet:
docker:
- image: circleci/golang:1.14
steps:
- checkout
- run: go vet .

workflows:
version: 2
test:
all:
jobs:
- test
- test
- lint
- vet
15 changes: 13 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io/ioutil"
"log"
"os"
"regexp"
"time"

"github.com/xlzd/gotp"
Expand All @@ -16,32 +17,42 @@ import (
"gopkg.in/yaml.v2"
)

// Config is the structure of the yaml configuration file
type Config struct {
Accounts []Account
}

// Account is an item in the yaml configuration file
type Account struct {
Name string
TOTPSecret string
}

var accountNameRe = `^[a-zA-Z0-9-_\.]{5,64}`

func main() {
if len(os.Args) != 2 {
fmt.Println("usage: sotp <account_name>")
os.Exit(1)
}
accountName := os.Args[1]
if !regexp.MustCompile(accountNameRe).MatchString(accountName) {
log.Fatalf("account name %q does not comply to regular expression %q", accountName, accountNameRe)
}

cfg, err := decryptConfig("config.yaml")
if err != nil {
log.Fatal("failed to access configuration at 'config.yaml'", err)
}
var totpSecret string
for _, account := range cfg.Accounts {
if account.Name == os.Args[1] {
if account.Name == accountName {
totpSecret = account.TOTPSecret
break
}
}
if totpSecret == "" {
log.Fatal("no totp information found for account", os.Args[1])
log.Fatalf("no totp information found for account %q", accountName)
}
otp := gotp.NewDefaultTOTP(totpSecret)

Expand Down
52 changes: 51 additions & 1 deletion main_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,53 @@
package main

var testAwsMfaSecret = "YAGQP5IP77OO3HMPS3D2KPMSNLNDIB7EO22EGAN3JEGE3DAR37Z2U5YDGKGN44VA"
import (
"regexp"
"testing"
"time"

"github.com/xlzd/gotp"
)

func TestAccountNameRe(t *testing.T) {
accountNames := []struct {
accountName string
valid bool
}{
{"foobar", true},
{"foo-_bar", true},
{"foo-bar-1337", true},
{"foo=bar", false},
{"foo*bar", false},
}
for _, testData := range accountNames {
isValid := regexp.MustCompile(accountNameRe).MatchString(testData.accountName)
if isValid && !testData.valid {
t.Fatalf("account name %q passes regexp verification %q but was expected to fail", testData.accountName, accountNameRe)
} else if !isValid && testData.valid {
t.Fatalf("account name %q does not pass regexp verification %q but was expected to pass", testData.accountName, accountNameRe)
}
}
}

func TestDecryptConfig(t *testing.T) {
cfg, err := decryptConfig("config.yaml")
if err != nil {
t.Fatal("failed to access configuration at 'config.yaml'", err)
}
if cfg.Accounts[0].Name != "test1" {
t.Fatalf("expected account name `test1` but got %q", cfg.Accounts[0].Name)
}
}

func TestGetTOTP(t *testing.T) {
var testAwsMfaSecret = "YAGQP5IP77OO3HMPS3D2KPMSNLNDIB7EO22EGAN3JEGE3DAR37Z2U5YDGKGN44VA"
otp := gotp.NewDefaultTOTP(testAwsMfaSecret)
ts, err := time.Parse("2006-01-02", "2006-01-02")
if err != nil {
t.Fatal(err)
}
otpValue := otp.At(int(ts.Unix()))
if otpValue != "352864" {
t.Fatalf("expected otp value 352864 but got %q", otpValue)
}
}

0 comments on commit 589ad9e

Please sign in to comment.