Skip to content

Commit

Permalink
define concept of tokenV2
Browse files Browse the repository at this point in the history
  • Loading branch information
wpjunior committed Feb 23, 2024
1 parent a13be1a commit 77c699c
Show file tree
Hide file tree
Showing 12 changed files with 348 additions and 86 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ require (
github.com/tsuru/gnuflag v0.0.0-20151217162021-86b8c1b864aa
github.com/tsuru/go-tsuruclient v0.0.0-20231124151049-7b8d8ea2ee30
github.com/tsuru/tablecli v0.0.0-20190131152944-7ded8a3383c6
github.com/tsuru/tsuru v0.0.0-20240220172434-1ffd178d4e76
github.com/tsuru/tsuru v0.0.0-20240223131311-f019b455de1a
golang.org/x/net v0.20.0
golang.org/x/oauth2 v0.16.0
golang.org/x/sys v0.16.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -679,8 +679,8 @@ github.com/tsuru/go-tsuruclient v0.0.0-20231124151049-7b8d8ea2ee30 h1:lPzNgSgTz+
github.com/tsuru/go-tsuruclient v0.0.0-20231124151049-7b8d8ea2ee30/go.mod h1:BmePxHey9hxrxk0kzTMHFFr7aJWXSxtlrUx6FIeV0Ic=
github.com/tsuru/tablecli v0.0.0-20190131152944-7ded8a3383c6 h1:1XDdWFAjIbCSG1OjN9v9KdWhuM8UtYlFcfHe/Ldkchk=
github.com/tsuru/tablecli v0.0.0-20190131152944-7ded8a3383c6/go.mod h1:ztYpOhW+u1k21FEqp7nZNgpWbr0dUKok5lgGCZi+1AQ=
github.com/tsuru/tsuru v0.0.0-20240220172434-1ffd178d4e76 h1:Tqusq+Wr/Kc06nXvSHmRXrfj8CB1ILcDTgd20sDqH2Q=
github.com/tsuru/tsuru v0.0.0-20240220172434-1ffd178d4e76/go.mod h1:QxMVXEjpb6mPnlaLMQdxJ3XCg+vOa4/MwZWLk3/naec=
github.com/tsuru/tsuru v0.0.0-20240223131311-f019b455de1a h1:+pe07oMZF5ZndprvAEugJVoWyK4X1yy/rhGBbKfiNZg=
github.com/tsuru/tsuru v0.0.0-20240223131311-f019b455de1a/go.mod h1:QxMVXEjpb6mPnlaLMQdxJ3XCg+vOa4/MwZWLk3/naec=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
Expand Down
6 changes: 5 additions & 1 deletion tsuru/admin/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ func (s *S) TearDownTest(c *check.C) {
}

func (s *S) setupFakeTransport(rt http.RoundTripper) {
tsuruHTTP.AuthenticatedClient = tsuruHTTP.NewTerminalClient(rt, nil, "test", "0.1.0", 0)
tsuruHTTP.AuthenticatedClient = tsuruHTTP.NewTerminalClient(tsuruHTTP.TerminalClientOptions{
RoundTripper: rt,
ClientName: "test",
ClientVersion: "0.1.0",
})
}

var _ = check.Suite(&S{})
Expand Down
42 changes: 29 additions & 13 deletions tsuru/auth/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package auth

import (
stdContext "context"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"time"

"github.com/tsuru/tsuru-client/tsuru/config"
"github.com/tsuru/tsuru/cmd"
authTypes "github.com/tsuru/tsuru/types/auth"
"golang.org/x/oauth2"
Expand All @@ -16,7 +17,7 @@ import (
func oidcLogin(ctx *cmd.Context, loginInfo *authTypes.SchemeInfo) error {
pkceVerifier := oauth2.GenerateVerifier()

fmt.Fprintln(ctx.Stdout, "Starting OIDC login")
fmt.Fprintln(ctx.Stderr, "Starting OIDC login")

l, err := net.Listen("tcp", port(loginInfo))
if err != nil {
Expand All @@ -27,7 +28,7 @@ func oidcLogin(ctx *cmd.Context, loginInfo *authTypes.SchemeInfo) error {
return err
}

config := oauth2.Config{
oautn2Config := oauth2.Config{
ClientID: loginInfo.Data.ClientID,
Scopes: loginInfo.Data.Scopes,
RedirectURL: fmt.Sprintf("http://localhost:%s", port),
Expand All @@ -37,7 +38,7 @@ func oidcLogin(ctx *cmd.Context, loginInfo *authTypes.SchemeInfo) error {
},
}

authURL := config.AuthCodeURL("", oauth2.S256ChallengeOption(pkceVerifier))
authURL := oautn2Config.AuthCodeURL("", oauth2.S256ChallengeOption(pkceVerifier))

finish := make(chan bool)

Expand All @@ -47,25 +48,35 @@ func oidcLogin(ctx *cmd.Context, loginInfo *authTypes.SchemeInfo) error {
finish <- true
}()

t, err := config.Exchange(stdContext.Background(), r.URL.Query().Get("code"), oauth2.VerifierOption(pkceVerifier))
t, err := oautn2Config.Exchange(stdContext.Background(), r.URL.Query().Get("code"), oauth2.VerifierOption(pkceVerifier))

w.Header().Add("Content-Type", "text/html")

if err != nil {
msg := fmt.Sprintf(errorMarkup, err.Error())
fmt.Fprintf(w, callbackPage, msg)
writeHTMLError(w, err)
return
}

fmt.Fprintln(ctx.Stdout, "Successfully logged in!")
fmt.Fprintf(ctx.Stdout, "The token will expiry in %s\n", time.Since(t.Expiry)*-1)
fmt.Fprintln(ctx.Stderr, "Successfully logged in via OIDC!")
fmt.Fprintf(ctx.Stderr, "The OIDC token will expiry in %s\n", time.Since(t.Expiry)*-1)

json.NewEncoder(ctx.Stdout).Encode(t)
err = config.WriteTokenV2(config.TokenV2{
Scheme: "oidc",
OAuth2Token: t,
})

fmt.Println("TODO write token: ", t.AccessToken)
fmt.Println("TODO write refresh token: ", t.RefreshToken)
if err != nil {
writeHTMLError(w, err)
return
}

fmt.Printf("%#v\n", t)
// legacy token
err = config.WriteToken(t.AccessToken)

if err != nil {
writeHTMLError(w, err)
return
}

fmt.Fprintf(w, callbackPage, successMarkup)

Expand All @@ -83,3 +94,8 @@ func oidcLogin(ctx *cmd.Context, loginInfo *authTypes.SchemeInfo) error {
server.Shutdown(timedCtx)
return nil
}

func writeHTMLError(w io.Writer, err error) {
msg := fmt.Sprintf(errorMarkup, err.Error())
fmt.Fprintf(w, callbackPage, msg)
}
6 changes: 5 additions & 1 deletion tsuru/client/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,9 @@ func Test(t *testing.T) {
}

func (s *S) setupFakeTransport(rt http.RoundTripper) {
tsuruHTTP.AuthenticatedClient = tsuruHTTP.NewTerminalClient(rt, nil, "test", "0.1.0", 0)
tsuruHTTP.AuthenticatedClient = tsuruHTTP.NewTerminalClient(tsuruHTTP.TerminalClientOptions{
RoundTripper: rt,
ClientName: "test",
ClientVersion: "0.1.0",
})
}
56 changes: 56 additions & 0 deletions tsuru/config/token_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2024 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package config

import (
"io"

"github.com/tsuru/tsuru/fs/fstest"
"gopkg.in/check.v1"
)

func (s *S) TestWriteToken(c *check.C) {
rfs := &fstest.RecordingFs{}
SetFileSystem(rfs)
defer func() {
ResetFileSystem()
}()
err := WriteToken("abc")
c.Assert(err, check.IsNil)
tokenPath := JoinWithUserDir(".tsuru", "token")
c.Assert(rfs.HasAction("create "+tokenPath), check.Equals, true)
fil, _ := Filesystem().Open(tokenPath)
b, _ := io.ReadAll(fil)
c.Assert(string(b), check.Equals, "abc")
}

func (s *S) TestWriteTokenWithTarget(c *check.C) {
rfs := &fstest.RecordingFs{}
SetFileSystem(rfs)
initTestTarget()

defer func() {
ResetFileSystem()
}()
err := WriteToken("abc")
c.Assert(err, check.IsNil)
tokenPath1 := JoinWithUserDir(".tsuru", "token")
c.Assert(rfs.HasAction("create "+tokenPath1), check.Equals, true)
tokenPath2 := JoinWithUserDir(".tsuru", "token.d", "test")
c.Assert(rfs.HasAction("create "+tokenPath2), check.Equals, true)
fil, _ := Filesystem().Open(tokenPath1)
b, _ := io.ReadAll(fil)
c.Assert(string(b), check.Equals, "abc")
fil, _ = Filesystem().Open(tokenPath2)
b, _ = io.ReadAll(fil)
c.Assert(string(b), check.Equals, "abc")
}

func initTestTarget() {
f, _ := Filesystem().Create(JoinWithUserDir(".tsuru", "target"))
f.Write([]byte("http://localhost"))
f.Close()
WriteOnTargetList("test", "http://localhost")
}
48 changes: 48 additions & 0 deletions tsuru/config/token_v2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2024 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package config

import (
"encoding/json"

"golang.org/x/oauth2"
)

type TokenV2 struct {
Scheme string `json:"scheme"`
OAuth2Token *oauth2.Token `json:"oauth2_token"`
}

func WriteTokenV2(token TokenV2) error {
tokenPaths := []string{
JoinWithUserDir(".tsuru", "token-v2.json"),
}
targetLabel, err := GetTargetLabel()
if err == nil {
err := Filesystem().MkdirAll(JoinWithUserDir(".tsuru", "token-v2.d"), 0700)
if err != nil {
return err
}
tokenPaths = append(tokenPaths, JoinWithUserDir(".tsuru", "token-v2.d", targetLabel+".json"))
}

for _, tokenPath := range tokenPaths {
file, err := Filesystem().Create(tokenPath)
if err != nil {
return err
}
defer file.Close()

enc := json.NewEncoder(file)
enc.SetIndent(" ", " ")
err = enc.Encode(&token)

if err != nil {
return err
}

}
return nil
}
87 changes: 87 additions & 0 deletions tsuru/config/token_v2_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2024 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package config

import (
"encoding/json"
"time"

"github.com/tsuru/tsuru/fs/fstest"
"golang.org/x/oauth2"
"gopkg.in/check.v1"
)

func (s *S) TestWriteTokenV2(c *check.C) {
rfs := &fstest.RecordingFs{}
SetFileSystem(rfs)
defer func() {
ResetFileSystem()
}()
err := WriteTokenV2(TokenV2{
Scheme: "oidc",
OAuth2Token: &oauth2.Token{
AccessToken: "123",
Expiry: time.Now(),
RefreshToken: "321",
},
})
c.Assert(err, check.IsNil)
tokenPath := JoinWithUserDir(".tsuru", "token-v2.json")
c.Assert(rfs.HasAction("create "+tokenPath), check.Equals, true)
fil, err := Filesystem().Open(tokenPath)
c.Assert(err, check.IsNil)

t := TokenV2{}
err = json.NewDecoder(fil).Decode(&t)
c.Assert(err, check.IsNil)
c.Assert(t.Scheme, check.Equals, "oidc")
c.Assert(t.OAuth2Token.AccessToken, check.Equals, "123")
c.Assert(t.OAuth2Token.Expiry, check.Not(check.IsNil))
c.Assert(t.OAuth2Token.RefreshToken, check.Equals, "321")

}

func (s *S) TestWriteTokenV2WithTarget(c *check.C) {
rfs := &fstest.RecordingFs{}
SetFileSystem(rfs)
initTestTarget()

defer func() {
ResetFileSystem()
}()
err := WriteTokenV2(TokenV2{
Scheme: "oidc",
OAuth2Token: &oauth2.Token{
AccessToken: "123",
Expiry: time.Now(),
RefreshToken: "321",
},
})
c.Assert(err, check.IsNil)
tokenPath1 := JoinWithUserDir(".tsuru", "token-v2.json")
c.Assert(rfs.HasAction("create "+tokenPath1), check.Equals, true)
tokenPath2 := JoinWithUserDir(".tsuru", "token-v2.d", "test.json")
c.Assert(rfs.HasAction("create "+tokenPath2), check.Equals, true)

fil, err := Filesystem().Open(tokenPath1)
c.Assert(err, check.IsNil)
t := TokenV2{}
err = json.NewDecoder(fil).Decode(&t)
c.Assert(err, check.IsNil)
c.Assert(t.Scheme, check.Equals, "oidc")
c.Assert(t.OAuth2Token.AccessToken, check.Equals, "123")
c.Assert(t.OAuth2Token.Expiry, check.Not(check.IsNil))
c.Assert(t.OAuth2Token.RefreshToken, check.Equals, "321")

fil, err = Filesystem().Open(tokenPath2)
c.Assert(err, check.IsNil)
t = TokenV2{}
err = json.NewDecoder(fil).Decode(&t)
c.Assert(err, check.IsNil)
c.Assert(t.Scheme, check.Equals, "oidc")
c.Assert(t.OAuth2Token.AccessToken, check.Equals, "123")
c.Assert(t.OAuth2Token.Expiry, check.Not(check.IsNil))
c.Assert(t.OAuth2Token.RefreshToken, check.Equals, "321")
}
38 changes: 25 additions & 13 deletions tsuru/http/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,43 @@ import (

"github.com/tsuru/go-tsuruclient/pkg/tsuru"
"github.com/tsuru/tsuru-client/tsuru/config"
"github.com/tsuru/tsuru/cmd"
)

var AuthenticatedClient = &http.Client{}

func NewTerminalClient(rt http.RoundTripper, context *cmd.Context, clientName, clientVersion string, verbosity int) *http.Client {
var (
TerminalClientOnlyRequest = 1
TerminalClientVerbose = 2
)

type TerminalClientOptions struct {
RoundTripper http.RoundTripper
ClientName string
ClientVersion string
Stdout io.Writer
Stderr io.Writer
Verbosity *int
}

func NewTerminalClient(opts TerminalClientOptions) *http.Client {
stdout := io.Discard
stderr := io.Discard

if context != nil {
if context.Stdout != nil {
stdout = context.Stdout
}
if opts.Stdout != nil {
stdout = opts.Stdout
}

if context.Stderr != nil {
stderr = context.Stderr
}
if opts.Stderr != nil {
stderr = opts.Stderr
}

transport := &TerminalRoundTripper{
RoundTripper: rt,
RoundTripper: opts.RoundTripper,
Stdout: stdout,
Stderr: stderr,
Verbosity: &verbosity,
Progname: clientName,
CurrentVersion: clientVersion,
Verbosity: opts.Verbosity,
Progname: opts.ClientName,
CurrentVersion: opts.ClientVersion,
}
return &http.Client{Transport: transport}
}
Expand Down
Loading

0 comments on commit 77c699c

Please sign in to comment.