Skip to content

Commit

Permalink
Introduce version subcommand
Browse files Browse the repository at this point in the history
* Pull OIDC options into subcommands
* Remove Docker based build, rely on GitHub Actions
  • Loading branch information
twz123 committed Jun 3, 2020
1 parent 87bdd22 commit ab9a530
Show file tree
Hide file tree
Showing 13 changed files with 124 additions and 96 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0 # fetch also tag info, relevant for detecting the version
- name: Setup go
uses: actions/setup-go@v2
with:
go-version: 1.14.4
- name: Build binary
run: go build -v -ldflags="-s -w" ./cmd/oidc-token-ferry
run: make
- name: Compress binary
uses: svenstaro/upx-action@v1-release
with:
Expand Down
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
/oidc-token-ferry
/oidc-token-ferry.darwin-amd64
/oidc-token-ferry.linux-amd64
/oidc-token-ferry.windows-amd64
/oidc-token-ferry.exe
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2018 Tom Wieczorek
Copyright (c) 2018-2020 Tom Wieczorek

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
36 changes: 9 additions & 27 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,33 +1,15 @@
PROGRAM = oidc-token-ferry
GO_PACKAGE = github.com/twz123/$(PROGRAM)
BUILDER_IMAGE = docker.io/golang:1.14.4-alpine3.12

# binaries
DOCKER = docker
GO = go
DEP = dep
GO = go

OS_ARCH_PROGRAMS =
PROGRAM_DEPENDENCIES = Makefile go.mod go.sum $(shell find pkg/ cmd/ -type f -name \*.go -print)
VERSION := $(shell git describe --tags --always)
GIT_UNTRACKEDCHANGES := $(shell git status --porcelain)
ifneq ($(GIT_UNTRACKEDCHANGES),)
VERSION := $(VERSION)-dirty
endif

$(PROGRAM): $(PROGRAM_DEPENDENCIES)
$(GO) build ./cmd/oidc-token-ferry

define _os_arch_program =
OS_ARCH_PROGRAMS += $(PROGRAM).$(1)-$(2)
oidc-token-ferry.$(1)-$(2): $(PROGRAM_DEPENDENCIES)
$(DOCKER) run --rm -e GOOS=$(1) -e GOARCH=$(2) -e CGO_ENABLED=0 -v "$(shell pwd -P):/go/src/$(GO_PACKAGE):ro" -w "/go/src/$(GO_PACKAGE)/cmd/$(PROGRAM)" $(BUILDER_IMAGE) \
sh -c 'go build -ldflags="-s -w" -o /tmp/go.out && apk add --no-cache upx 1>&2 && upx -o /tmp/go.out.upx /tmp/go.out 1>&2 && cat /tmp/go.out.upx' > $(PROGRAM).$(1)-$(2) || { rm $(PROGRAM).$(1)-$(2); exit 1; }
chmod +x $(PROGRAM).$(1)-$(2)
endef

$(eval $(call _os_arch_program,linux,amd64))
$(eval $(call _os_arch_program,darwin,amd64))
$(eval $(call _os_arch_program,windows,amd64))

.PHONY: all
all: $(OS_ARCH_PROGRAMS)

.PHONY: clean
clean:
rm -f $(PROGRAM) $(OS_ARCH_PROGRAMS)
.PHONY: build
build: Makefile go.mod go.sum $(shell find pkg/ cmd/ -type f -name \*.go -print)
$(GO) build -ldflags="-s -w -X $(GO_PACKAGE)/cmd/$(PROGRAM)/version.VERSION=$(VERSION)" ./cmd/$(PROGRAM)
60 changes: 42 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# OpenID Connect Token Ferry

[![Build](https://github.com/twz123/oidc-token-ferry/workflows/Build/badge.svg)](https://github.com/twz123/oidc-token-ferry/actions?query=workflow%3ABuild)

Performs an OpenID Connect Authentication Flow from the command line using an
"out of band" redirect URL. The OpenID Connect Issuer will provide a "code"
after the user has been authenticated. That code needs to be fed into this CLI.
Expand All @@ -11,55 +13,77 @@ solves this problem, but specifically for Google as Identity Provider.

## Usage

Usage:
oidc-token-ferry [OPTIONS] <patch-kubeconfig | render-go-template | render-json>
General usage:

OpenID Connect Options:
-u, --issuer-url= IdP Issuer URL to be contacted (default: https://accounts.google.com)
-i, --client-id= Client ID to be used
-s, --client-secret= Client Secret to be used
-r, --redirect-url= Redirect URL to be communicated to the IdP (needs to indicate "out of band") (default: urn:ietf:wg:oauth:2.0:oob)
-c, --claim= Additional claims to be requested
Usage:
oidc-token-ferry [OPTIONS] <command>

Help Options:
-h, --help Show this help message
-h, --help Show this help message

Available commands:
patch-kubeconfig patches Kubernetes kubeconfig files
render-go-template renders credentials using Go Templates
render-json renders credentials as JSON
version Show oidc-token-ferry version information

How to patch a kubeconfig:

Usage:
oidc-token-ferry [OPTIONS] patch-kubeconfig [patch-kubeconfig-OPTIONS] [KUBECONFIG_FILE] [OUTPUT_FILE]

Help Options:
-h, --help Show this help message

[patch-kubeconfig command options]
--user-name= User name to use when generating client configuration. Either user-name or user-claim-name may be specified.
--user-claim-name= Claim that defines the user name to use when generating client configuration. Either user-name or user-claim-name may be specified.
--no-open-url Don't open the redirect URL in a browser automatically

OpenID Connect Options:
-u, --issuer-url= IdP Issuer URL to be contacted (default: https://accounts.google.com)
-i, --client-id= Client ID to be used
-s, --client-secret= Client Secret to be used
-r, --redirect-url= Redirect URL to be communicated to the IdP (needs to indicate "out of band") (default: urn:ietf:wg:oauth:2.0:oob)
-c, --claim= Additional claims to be requested

[patch-kubeconfig command arguments]
KUBECONFIG_FILE: Path to the kubeconfig file to be patched. Uses the default discovery mechanism if omitted/empty. Special value '-' (hyphen) means read from STDIN.
OUTPUT_FILE: Path to the patched kubeconfig file to be written. Overwrites kubeconfig if omitted/empty. Special value '-' (hyphen) means write to STDOUT.

How to render credentials via go-template:

Usage:
oidc-token-ferry [OPTIONS] render-go-template [render-go-template-OPTIONS] TEMPLATE_STRING

Help Options:
-h, --help Show this help message

[render-go-template command options]
-o, --output-file= Output file to write (defaults to STDOUT if omitted)
--no-open-url Don't open the redirect URL in a browser automatically

OpenID Connect Options:
-u, --issuer-url= IdP Issuer URL to be contacted (default: https://accounts.google.com)
-i, --client-id= Client ID to be used
-s, --client-secret= Client Secret to be used
-r, --redirect-url= Redirect URL to be communicated to the IdP (needs to indicate "out of band") (default: urn:ietf:wg:oauth:2.0:oob)
-c, --claim= Additional claims to be requested

[render-go-template command arguments]
TEMPLATE_STRING: Go Template to be rendered. An empty template indicates that the template is to be read from STDIN.

[render-json command options]
-o, --output-file= Output file to write (defaults to STDOUT if omitted)

## Building

go build ./cmd/oidc-token-ferry

There's also a `Makefile` that'll build statically linked and compressed
binaries for darwin/linux amd64 using Go 1.9.2 inside a Docker container:
make

make all
This will build a statically linked binary.

## License

MIT License

Copyright (c) 2018 Tom Wieczorek
Copyright (c) 2018-2020 Tom Wieczorek

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
14 changes: 7 additions & 7 deletions cmd/oidc-token-ferry/kubeconfig/patchcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (

const useStdInOut = "-"

type patchCmd struct {
type PatchCmd struct {
UserName func(string) `long:"user-name" description:"User name to use when generating client configuration. Either user-name or user-claim-name may be specified."`
UserClaimName func(string) `long:"user-claim-name" description:"Claim that defines the user name to use when generating client configuration. Either user-name or user-claim-name may be specified."`

Expand All @@ -25,20 +25,20 @@ type patchCmd struct {
Outputconfig flags.Filename `positional-arg-name:"OUTPUT_FILE" description:"Path to the patched kubeconfig file to be written. Overwrites kubeconfig if omitted/empty. Special value '-' (hyphen) means write to STDOUT."`
} `positional-args:"yes"`

cli cli.CLI
cli.TokenFerryCmd

internalError error
determineUserName func(*api.TokenFerry) (string, error)
}

func PatchCmd(cli cli.CLI) interface{} {
cmd := &patchCmd{cli: cli}
func NewPatchCmd() *PatchCmd {
cmd := &PatchCmd{}
cmd.UserName = cmd.makeUserSelector(selectStaticUserName)
cmd.UserClaimName = cmd.makeUserSelector(selectUserNameFromClaim)
return cmd
}

func (cmd *patchCmd) Execute([]string) error {
func (cmd *PatchCmd) Execute([]string) error {
if cmd.internalError != nil {
return cmd.internalError
}
Expand All @@ -55,7 +55,7 @@ func (cmd *patchCmd) Execute([]string) error {
return errors.Wrap(err, "failed to patch kubeconfig")
}

ferry, err := cmd.cli.PerformChallenge()
ferry, err := cmd.TokenFerryCmd.PerformChallenge()
if err != nil {
return err
}
Expand Down Expand Up @@ -136,7 +136,7 @@ func loadClientConfig(kubeconfig string) (*clientcmdapi.Config, string, error) {
}
}

func (cmd *patchCmd) makeUserSelector(selector func(*api.TokenFerry, string) (string, error)) func(string) {
func (cmd *PatchCmd) makeUserSelector(selector func(*api.TokenFerry, string) (string, error)) func(string) {
return func(value string) {
if cmd.determineUserName != nil {
cmd.internalError = errors.New("either user-name or user-claim-name may be specified")
Expand Down
22 changes: 9 additions & 13 deletions cmd/oidc-token-ferry/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/twz123/oidc-token-ferry/cmd/oidc-token-ferry/kubeconfig"
"github.com/twz123/oidc-token-ferry/cmd/oidc-token-ferry/render"
"github.com/twz123/oidc-token-ferry/cmd/oidc-token-ferry/version"
)

const (
Expand All @@ -15,14 +16,15 @@ const (
xCLIUsage
)

func main() {
cli := &tokenFerryCmd{}

parser := flags.NewParser(cli, flags.Default)
type cli struct {
VersionCmd version.VersionCmd `command:"version" description:"Show oidc-token-ferry version information"`
JSONCmd render.JSONCmd `command:"render-json" description:"renders credentials as JSON"`
GoTemplateCmd render.GoTemplateCmd `command:"render-go-template" description:"renders credentials using Go Templates"`
PatchCmd *kubeconfig.PatchCmd `command:"patch-kubeconfig" description:"patches Kubernetes kubeconfig files"`
}

cmd(parser, render.JsonCmd(cli), "render-json", "renders credentials as JSON")
cmd(parser, render.GoTemplateCmd(cli), "render-go-template", "renders credentials using Go Templates")
cmd(parser, kubeconfig.PatchCmd(cli), "patch-kubeconfig", "patches Kubernetes kubeconfig files")
func main() {
parser := flags.NewParser(&cli{PatchCmd: kubeconfig.NewPatchCmd()}, flags.Default)

_, err := parser.Parse()
if err != nil {
Expand All @@ -39,9 +41,3 @@ func main() {

os.Exit(xOK)
}

func cmd(parser *flags.Parser, data interface{}, name, desc string) {
if _, err := parser.AddCommand(name, desc, "", data); err != nil {
panic(err)
}
}
12 changes: 5 additions & 7 deletions cmd/oidc-token-ferry/render/gotemplatecmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,23 @@ import (
"github.com/twz123/oidc-token-ferry/pkg/cli"
)

type goTemplateCmd struct {
type GoTemplateCmd struct {
cli.OutputTarget

Args struct {
TemplateString string `positional-arg-name:"TEMPLATE_STRING" description:"Go Template to be rendered. An empty template indicates that the template is to be read from STDIN."`
} `positional-args:"yes" required:"yes"`

cli cli.CLI
cli.TokenFerryCmd
}

func GoTemplateCmd(cli cli.CLI) interface{} { return &goTemplateCmd{cli: cli} }

func (cmd *goTemplateCmd) Execute(args []string) error {
func (cmd *GoTemplateCmd) Execute(args []string) error {
template, err := cmd.parseTemplate()
if err != nil {
return err
}

ferry, err := cmd.cli.PerformChallenge()
ferry, err := cmd.TokenFerryCmd.PerformChallenge()
if err != nil {
return err
}
Expand All @@ -39,7 +37,7 @@ func (cmd *goTemplateCmd) Execute(args []string) error {
})
}

func (cmd *goTemplateCmd) parseTemplate() (*template.Template, error) {
func (cmd *GoTemplateCmd) parseTemplate() (*template.Template, error) {
if cmd.Args.TemplateString == "" {
return parseTemplateFromStdin()
}
Expand Down
10 changes: 4 additions & 6 deletions cmd/oidc-token-ferry/render/jsoncmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ import (
"github.com/twz123/oidc-token-ferry/pkg/cli"
)

type jsonCmd struct {
type JSONCmd struct {
cli.OutputTarget
cli cli.CLI
cli.TokenFerryCmd
}

func JsonCmd(cli cli.CLI) interface{} { return &jsonCmd{cli: cli} }

func (cmd *jsonCmd) Execute(args []string) error {
ferry, err := cmd.cli.PerformChallenge()
func (cmd *JSONCmd) Execute(args []string) error {
ferry, err := cmd.TokenFerryCmd.PerformChallenge()
if err != nil {
return err
}
Expand Down
31 changes: 31 additions & 0 deletions cmd/oidc-token-ferry/version/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package version

import (
"fmt"
"runtime"
)

type Version struct {
Version string
GoVersion string
GoCompiler string
GoOs string
GoArch string
}

func NewVersion() Version {
return Version{
Version: VERSION,
GoVersion: runtime.Compiler,
GoOs: runtime.GOOS,
GoArch: runtime.GOARCH,
}
}

type VersionCmd struct {
}

func (cmd *VersionCmd) Execute(args []string) error {
_, err := fmt.Printf("oidc-token-ferry: %+v\n", NewVersion())
return err
}
4 changes: 4 additions & 0 deletions cmd/oidc-token-ferry/version/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package version

// VERSION indicates which version of the binary is running.
var VERSION string
9 changes: 0 additions & 9 deletions pkg/cli/cli.go

This file was deleted.

Loading

0 comments on commit ab9a530

Please sign in to comment.