Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
pyama86 committed Jan 30, 2020
0 parents commit 1913868
Show file tree
Hide file tree
Showing 8 changed files with 288 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.test
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## 0.1.0 (2020-01-30)

Initial release

### Added

- Add Fundamental features

### Deprecated

- Nothing

### Removed

- Nothing

### Fixed

- Nothing
43 changes: 43 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
VERSION := $(shell git tag | tail -n1 | sed 's/v//g')
REVISION := $(shell git rev-parse --short HEAD)
INFO_COLOR=\033[1;34m
RESET=\033[0m
BOLD=\033[1m
ifeq ("$(shell uname)","Darwin")
GO ?= GO111MODULE=on go
else
GO ?= GO111MODULE=on /usr/local/go/bin/go
endif

TEST ?= $(shell $(GO) list ./... | grep -v -e vendor -e keys -e tmp)
build:
$(GO) build -o nke -ldflags "-X main.Version=$(VERSION)-$(REVISION)"

deps:
go get -u golang.org/x/lint/golint

git-semv:
brew tap linyows/git-semv
brew install git-semv

goreleaser:
brew install goreleaser/tap/goreleaser
brew install goreleaser

ci: unit_test lint
lint: deps
@echo "$(INFO_COLOR)==> $(RESET)$(BOLD)Linting$(RESET)"
golint -min_confidence 1.1 -set_exit_status $(TEST)

unit_test: ## Run test
@echo "$(INFO_COLOR)==> $(RESET)$(BOLD)Testing$(RESET)"
$(GO) test -v $(TEST) -timeout=30s -parallel=4 -coverprofile cover.out.tmp
cat cover.out.tmp | grep -v -e "main.go" -e "cmd.go" -e "_mock.go" > cover.out
$(GO) tool cover -func cover.out
$(GO) test -race $(TEST)

release: releasedeps
git semv patch --bump
goreleaser --rm-dist
run:
$(GO) run main.go version.go cli.go
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# pam-google-web-oauth



## Description

## Usage

## Install

To install, use `go get`:

```bash
$ go get -d github.com/pyama86/pam-google-web-oauth
```

## Contribution

1. Fork ([https://github.com/pyama86/pam-google-web-oauth/fork](https://github.com/pyama86/pam-google-web-oauth/fork))
1. Create a feature branch
1. Commit your changes
1. Rebase your local changes against the master branch
1. Run test suite with the `go test ./...` command and confirm that it passes
1. Run `gofmt -s`
1. Create a new Pull Request

## Author

[pyama86](https://github.com/pyama86)
151 changes: 151 additions & 0 deletions cli.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package main

import (
"context"
"encoding/json"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"net/url"
"os"
"os/user"
"path/filepath"

"github.com/sirupsen/logrus"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)

// Exit codes are int values that represent an exit code for a particular error.
const (
ExitCodeOK int = 0
ExitCodeError int = 1 + iota
)

// CLI is the command line object
type CLI struct {
// outStream and errStream are the stdout and stderr
// to write message from the CLI.
outStream, errStream io.Writer
}

// Run invokes the CLI with the given arguments.
func (cli *CLI) Run(args []string) int {
var (
config string
version bool
)

flags := flag.NewFlagSet(Name, flag.ContinueOnError)
flags.SetOutput(cli.errStream)

flags.StringVar(&config, "config", "/etc/pam-google-web-oauth/client_secret.json", "Config file path")
flags.StringVar(&config, "c", "/etc/pam-google-web-oauth/client_secret.json", "Config file path(Short)")

flags.BoolVar(&version, "version", false, "Print version information and quit.")

// Parse commandline flag
if err := flags.Parse(args[1:]); err != nil {
return ExitCodeError
}

// Show version
if version {
fmt.Fprintf(cli.errStream, "%s version %s\n", Name, Version)
return ExitCodeOK
}
if err := cli.run(config); err != nil {
logrus.Error(err)
return ExitCodeError
}
return ExitCodeOK

}
func (cli *CLI) run(config string) error {
ctx := context.Background()
b, err := ioutil.ReadFile(config)
if err != nil {
log.Fatalf("Unable to read client secret file: %s", config)
}

gconfig, err := google.ConfigFromJSON(b, "profile")
if err != nil {
fmt.Errorf("Unable to parse client secret file to config: %v", err)
}
err = auth(ctx, gconfig)
if err != nil {
return err
}

return nil

}

func auth(ctx context.Context, c *oauth2.Config) error {
cacheFile, err := tokenCacheFile()
if err != nil {
return err
}
tok, err := tokenFromFile(cacheFile)
if err != nil || !tok.Valid() {
tok, err := getTokenFromWeb(c)
if err != nil {
return err
}
return saveToken(cacheFile, tok)
}
return nil
}

func getTokenFromWeb(c *oauth2.Config) (*oauth2.Token, error) {
authURL := c.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
fmt.Printf("Go to the following link in your browser then type the "+
"authorization code: \n\n%v\n\nPlease type code:", authURL)

var code string
if _, err := fmt.Scan(&code); err != nil {
return nil, fmt.Errorf("Unable to read authorization code %v", err)
}

tok, err := c.Exchange(oauth2.NoContext, code)
if err != nil {
return nil, fmt.Errorf("Unable to retrieve token from web %v", err)
}
return tok, nil
}

func tokenCacheFile() (string, error) {
userInfo, err := user.Lookup(os.Getenv("PAM_USER"))
if err != nil {
return "", err
}
tokenCacheDir := filepath.Join(userInfo.HomeDir, ".credentials")
err = os.MkdirAll(tokenCacheDir, 0700)
if err != nil {
return "", err
}
return filepath.Join(tokenCacheDir, url.QueryEscape("google_oauth.json")), nil
}

func tokenFromFile(file string) (*oauth2.Token, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
t := &oauth2.Token{}
err = json.NewDecoder(f).Decode(t)
defer f.Close()
return t, err
}

func saveToken(file string, token *oauth2.Token) error {
fmt.Printf("Saving credential file to: %s\n", file)
f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
log.Fatalf("Unable to cache oauth token: %v", err)
}
defer f.Close()
return json.NewEncoder(f).Encode(token)
}
33 changes: 33 additions & 0 deletions cli_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main

import (
"bytes"
"fmt"
"strings"
"testing"
)

func TestRun_versionFlag(t *testing.T) {
outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
cli := &CLI{outStream: outStream, errStream: errStream}
args := strings.Split("./pam-google-web-oauth -version", " ")

status := cli.Run(args)
if status != ExitCodeOK {
t.Errorf("expected %d to eq %d", status, ExitCodeOK)
}

expected := fmt.Sprintf("pam-google-web-oauth version %s", Version)
if !strings.Contains(errStream.String(), expected) {
t.Errorf("expected %q to eq %q", errStream.String(), expected)
}
}

func TestRun_configFlag(t *testing.T) {
outStream, errStream := new(bytes.Buffer), new(bytes.Buffer)
cli := &CLI{outStream: outStream, errStream: errStream}
args := strings.Split("./pam-google-web-oauth -config", " ")

status := cli.Run(args)
_ = status
}
8 changes: 8 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package main

import "os"

func main() {
cli := &CLI{outStream: os.Stdout, errStream: os.Stderr}
os.Exit(cli.Run(os.Args))
}
4 changes: 4 additions & 0 deletions version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package main

const Name string = "pam-google-web-oauth"
const Version string = "0.1.0"

0 comments on commit 1913868

Please sign in to comment.