Skip to content

Commit 1913868

Browse files
author
pyama86
committed
init
0 parents  commit 1913868

File tree

8 files changed

+288
-0
lines changed

8 files changed

+288
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.test

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
## 0.1.0 (2020-01-30)
2+
3+
Initial release
4+
5+
### Added
6+
7+
- Add Fundamental features
8+
9+
### Deprecated
10+
11+
- Nothing
12+
13+
### Removed
14+
15+
- Nothing
16+
17+
### Fixed
18+
19+
- Nothing

Makefile

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
VERSION := $(shell git tag | tail -n1 | sed 's/v//g')
2+
REVISION := $(shell git rev-parse --short HEAD)
3+
INFO_COLOR=\033[1;34m
4+
RESET=\033[0m
5+
BOLD=\033[1m
6+
ifeq ("$(shell uname)","Darwin")
7+
GO ?= GO111MODULE=on go
8+
else
9+
GO ?= GO111MODULE=on /usr/local/go/bin/go
10+
endif
11+
12+
TEST ?= $(shell $(GO) list ./... | grep -v -e vendor -e keys -e tmp)
13+
build:
14+
$(GO) build -o nke -ldflags "-X main.Version=$(VERSION)-$(REVISION)"
15+
16+
deps:
17+
go get -u golang.org/x/lint/golint
18+
19+
git-semv:
20+
brew tap linyows/git-semv
21+
brew install git-semv
22+
23+
goreleaser:
24+
brew install goreleaser/tap/goreleaser
25+
brew install goreleaser
26+
27+
ci: unit_test lint
28+
lint: deps
29+
@echo "$(INFO_COLOR)==> $(RESET)$(BOLD)Linting$(RESET)"
30+
golint -min_confidence 1.1 -set_exit_status $(TEST)
31+
32+
unit_test: ## Run test
33+
@echo "$(INFO_COLOR)==> $(RESET)$(BOLD)Testing$(RESET)"
34+
$(GO) test -v $(TEST) -timeout=30s -parallel=4 -coverprofile cover.out.tmp
35+
cat cover.out.tmp | grep -v -e "main.go" -e "cmd.go" -e "_mock.go" > cover.out
36+
$(GO) tool cover -func cover.out
37+
$(GO) test -race $(TEST)
38+
39+
release: releasedeps
40+
git semv patch --bump
41+
goreleaser --rm-dist
42+
run:
43+
$(GO) run main.go version.go cli.go

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# pam-google-web-oauth
2+
3+
4+
5+
## Description
6+
7+
## Usage
8+
9+
## Install
10+
11+
To install, use `go get`:
12+
13+
```bash
14+
$ go get -d github.com/pyama86/pam-google-web-oauth
15+
```
16+
17+
## Contribution
18+
19+
1. Fork ([https://github.com/pyama86/pam-google-web-oauth/fork](https://github.com/pyama86/pam-google-web-oauth/fork))
20+
1. Create a feature branch
21+
1. Commit your changes
22+
1. Rebase your local changes against the master branch
23+
1. Run test suite with the `go test ./...` command and confirm that it passes
24+
1. Run `gofmt -s`
25+
1. Create a new Pull Request
26+
27+
## Author
28+
29+
[pyama86](https://github.com/pyama86)

cli.go

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"flag"
7+
"fmt"
8+
"io"
9+
"io/ioutil"
10+
"log"
11+
"net/url"
12+
"os"
13+
"os/user"
14+
"path/filepath"
15+
16+
"github.com/sirupsen/logrus"
17+
"golang.org/x/oauth2"
18+
"golang.org/x/oauth2/google"
19+
)
20+
21+
// Exit codes are int values that represent an exit code for a particular error.
22+
const (
23+
ExitCodeOK int = 0
24+
ExitCodeError int = 1 + iota
25+
)
26+
27+
// CLI is the command line object
28+
type CLI struct {
29+
// outStream and errStream are the stdout and stderr
30+
// to write message from the CLI.
31+
outStream, errStream io.Writer
32+
}
33+
34+
// Run invokes the CLI with the given arguments.
35+
func (cli *CLI) Run(args []string) int {
36+
var (
37+
config string
38+
version bool
39+
)
40+
41+
flags := flag.NewFlagSet(Name, flag.ContinueOnError)
42+
flags.SetOutput(cli.errStream)
43+
44+
flags.StringVar(&config, "config", "/etc/pam-google-web-oauth/client_secret.json", "Config file path")
45+
flags.StringVar(&config, "c", "/etc/pam-google-web-oauth/client_secret.json", "Config file path(Short)")
46+
47+
flags.BoolVar(&version, "version", false, "Print version information and quit.")
48+
49+
// Parse commandline flag
50+
if err := flags.Parse(args[1:]); err != nil {
51+
return ExitCodeError
52+
}
53+
54+
// Show version
55+
if version {
56+
fmt.Fprintf(cli.errStream, "%s version %s\n", Name, Version)
57+
return ExitCodeOK
58+
}
59+
if err := cli.run(config); err != nil {
60+
logrus.Error(err)
61+
return ExitCodeError
62+
}
63+
return ExitCodeOK
64+
65+
}
66+
func (cli *CLI) run(config string) error {
67+
ctx := context.Background()
68+
b, err := ioutil.ReadFile(config)
69+
if err != nil {
70+
log.Fatalf("Unable to read client secret file: %s", config)
71+
}
72+
73+
gconfig, err := google.ConfigFromJSON(b, "profile")
74+
if err != nil {
75+
fmt.Errorf("Unable to parse client secret file to config: %v", err)
76+
}
77+
err = auth(ctx, gconfig)
78+
if err != nil {
79+
return err
80+
}
81+
82+
return nil
83+
84+
}
85+
86+
func auth(ctx context.Context, c *oauth2.Config) error {
87+
cacheFile, err := tokenCacheFile()
88+
if err != nil {
89+
return err
90+
}
91+
tok, err := tokenFromFile(cacheFile)
92+
if err != nil || !tok.Valid() {
93+
tok, err := getTokenFromWeb(c)
94+
if err != nil {
95+
return err
96+
}
97+
return saveToken(cacheFile, tok)
98+
}
99+
return nil
100+
}
101+
102+
func getTokenFromWeb(c *oauth2.Config) (*oauth2.Token, error) {
103+
authURL := c.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
104+
fmt.Printf("Go to the following link in your browser then type the "+
105+
"authorization code: \n\n%v\n\nPlease type code:", authURL)
106+
107+
var code string
108+
if _, err := fmt.Scan(&code); err != nil {
109+
return nil, fmt.Errorf("Unable to read authorization code %v", err)
110+
}
111+
112+
tok, err := c.Exchange(oauth2.NoContext, code)
113+
if err != nil {
114+
return nil, fmt.Errorf("Unable to retrieve token from web %v", err)
115+
}
116+
return tok, nil
117+
}
118+
119+
func tokenCacheFile() (string, error) {
120+
userInfo, err := user.Lookup(os.Getenv("PAM_USER"))
121+
if err != nil {
122+
return "", err
123+
}
124+
tokenCacheDir := filepath.Join(userInfo.HomeDir, ".credentials")
125+
err = os.MkdirAll(tokenCacheDir, 0700)
126+
if err != nil {
127+
return "", err
128+
}
129+
return filepath.Join(tokenCacheDir, url.QueryEscape("google_oauth.json")), nil
130+
}
131+
132+
func tokenFromFile(file string) (*oauth2.Token, error) {
133+
f, err := os.Open(file)
134+
if err != nil {
135+
return nil, err
136+
}
137+
t := &oauth2.Token{}
138+
err = json.NewDecoder(f).Decode(t)
139+
defer f.Close()
140+
return t, err
141+
}
142+
143+
func saveToken(file string, token *oauth2.Token) error {
144+
fmt.Printf("Saving credential file to: %s\n", file)
145+
f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
146+
if err != nil {
147+
log.Fatalf("Unable to cache oauth token: %v", err)
148+
}
149+
defer f.Close()
150+
return json.NewEncoder(f).Encode(token)
151+
}

cli_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"strings"
7+
"testing"
8+
)
9+
10+
func TestRun_versionFlag(t *testing.T) {
11+
outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
12+
cli := &CLI{outStream: outStream, errStream: errStream}
13+
args := strings.Split("./pam-google-web-oauth -version", " ")
14+
15+
status := cli.Run(args)
16+
if status != ExitCodeOK {
17+
t.Errorf("expected %d to eq %d", status, ExitCodeOK)
18+
}
19+
20+
expected := fmt.Sprintf("pam-google-web-oauth version %s", Version)
21+
if !strings.Contains(errStream.String(), expected) {
22+
t.Errorf("expected %q to eq %q", errStream.String(), expected)
23+
}
24+
}
25+
26+
func TestRun_configFlag(t *testing.T) {
27+
outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
28+
cli := &CLI{outStream: outStream, errStream: errStream}
29+
args := strings.Split("./pam-google-web-oauth -config", " ")
30+
31+
status := cli.Run(args)
32+
_ = status
33+
}

main.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package main
2+
3+
import "os"
4+
5+
func main() {
6+
cli := &CLI{outStream: os.Stdout, errStream: os.Stderr}
7+
os.Exit(cli.Run(os.Args))
8+
}

version.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package main
2+
3+
const Name string = "pam-google-web-oauth"
4+
const Version string = "0.1.0"

0 commit comments

Comments
 (0)