mirror of
https://github.com/argoproj/argo-cd
synced 2026-04-21 17:07:16 +00:00
Gzip JWTs and Adds New User Info Page (#2204)
This commit is contained in:
parent
e322750265
commit
cbf9585d84
44 changed files with 1191 additions and 351 deletions
|
|
@ -240,6 +240,7 @@ jobs:
|
|||
ARGOCD_FAKE_IN_CLUSTER: "true"
|
||||
ARGOCD_SSH_DATA_PATH: "/tmp/argo-e2e/app/config/ssh"
|
||||
ARGOCD_TLS_DATA_PATH: "/tmp/argo-e2e/app/config/tls"
|
||||
ARGOCD_ZJWT_FEATURE_FLAG: "always"
|
||||
- run:
|
||||
name: Start Test Git
|
||||
command: |
|
||||
|
|
|
|||
5
Makefile
5
Makefile
|
|
@ -186,6 +186,8 @@ start-e2e: cli
|
|||
# set paths for locally managed ssh known hosts and tls certs data
|
||||
ARGOCD_SSH_DATA_PATH=/tmp/argo-e2e/app/config/ssh \
|
||||
ARGOCD_TLS_DATA_PATH=/tmp/argo-e2e/app/config/tls \
|
||||
ARGOCD_E2E_DISABLE_AUTH=false \
|
||||
ARGOCD_ZJWT_FEATURE_FLAG=always \
|
||||
goreman start
|
||||
|
||||
# Cleans VSCode debug.test files from sub-dirs to prevent them from being included in packr boxes
|
||||
|
|
@ -204,7 +206,8 @@ start:
|
|||
docker version
|
||||
kubectl create ns argocd || true
|
||||
kubens argocd
|
||||
goreman start
|
||||
ARGOCD_ZJWT_FEATURE_FLAG=always \
|
||||
goreman start
|
||||
|
||||
.PHONY: pre-commit
|
||||
pre-commit: dep-ensure codegen build lint test
|
||||
|
|
|
|||
2
Procfile
2
Procfile
|
|
@ -1,5 +1,5 @@
|
|||
controller: sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true go run ./cmd/argocd-application-controller/main.go --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081}"
|
||||
api-server: sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true go run ./cmd/argocd-server/main.go --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --disable-auth --insecure --dex-server http://localhost:${ARGOCD_E2E_DEX_PORT:-5556} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --port ${ARGOCD_E2E_APISERVER_PORT:-8080} --staticassets ui/dist/app"
|
||||
api-server: sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true go run ./cmd/argocd-server/main.go --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --disable-auth=${ARGOCD_E2E_DISABLE_AUTH:-'true'} --insecure --dex-server http://localhost:${ARGOCD_E2E_DEX_PORT:-5556} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --port ${ARGOCD_E2E_APISERVER_PORT:-8080} --staticassets ui/dist/app"
|
||||
dex: sh -c "go run ./cmd/argocd-util/main.go gendexcfg -o `pwd`/dist/dex.yaml && docker run --rm -p ${ARGOCD_E2E_DEX_PORT:-5556}:${ARGOCD_E2E_DEX_PORT:-5556} -v `pwd`/dist/dex.yaml:/dex.yaml quay.io/dexidp/dex:v2.14.0 serve /dex.yaml"
|
||||
redis: docker run --rm --name argocd-redis -i -p ${ARGOCD_E2E_REDIS_PORT:-6379}:${ARGOCD_E2E_REDIS_PORT:-6379} redis:5.0.3-alpine --save "" --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}
|
||||
repo-server: sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true go run ./cmd/argocd-repo-server/main.go --loglevel debug --port ${ARGOCD_E2E_REPOSERVER_PORT:-8081} --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379}"
|
||||
|
|
|
|||
|
|
@ -1494,6 +1494,23 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/session/userinfo": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"SessionService"
|
||||
],
|
||||
"summary": "Get the current user's info",
|
||||
"operationId": "GetUserInfo",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "(empty)",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/sessionGetUserInfoResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/settings": {
|
||||
"get": {
|
||||
"tags": [
|
||||
|
|
@ -2086,6 +2103,28 @@
|
|||
"repositoryRepoResponse": {
|
||||
"type": "object"
|
||||
},
|
||||
"sessionGetUserInfoResponse": {
|
||||
"type": "object",
|
||||
"title": "The current user's userInfo info",
|
||||
"properties": {
|
||||
"groups": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"iss": {
|
||||
"type": "string"
|
||||
},
|
||||
"loggedIn": {
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sessionSessionCreateRequest": {
|
||||
"description": "SessionCreateRequest is for logging in.",
|
||||
"type": "object",
|
||||
|
|
|
|||
|
|
@ -2,16 +2,21 @@ package commands
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
|
||||
"github.com/argoproj/argo-cd/errors"
|
||||
argocdclient "github.com/argoproj/argo-cd/pkg/apiclient"
|
||||
accountpkg "github.com/argoproj/argo-cd/pkg/apiclient/account"
|
||||
"github.com/argoproj/argo-cd/pkg/apiclient/session"
|
||||
"github.com/argoproj/argo-cd/util"
|
||||
"github.com/argoproj/argo-cd/util/cli"
|
||||
"github.com/argoproj/argo-cd/util/localconfig"
|
||||
|
|
@ -27,6 +32,7 @@ func NewAccountCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
|||
},
|
||||
}
|
||||
command.AddCommand(NewAccountUpdatePasswordCommand(clientOpts))
|
||||
command.AddCommand(NewAccountGetUserInfoCommand(clientOpts))
|
||||
return command
|
||||
}
|
||||
|
||||
|
|
@ -93,3 +99,48 @@ func NewAccountUpdatePasswordCommand(clientOpts *argocdclient.ClientOptions) *co
|
|||
command.Flags().StringVar(&newPassword, "new-password", "", "new password you want to update to")
|
||||
return command
|
||||
}
|
||||
|
||||
func NewAccountGetUserInfoCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var (
|
||||
output string
|
||||
)
|
||||
var command = &cobra.Command{
|
||||
Use: "get-user-info",
|
||||
Short: "Get user info",
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
if len(args) != 0 {
|
||||
c.HelpFunc()(c, args)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
conn, client := argocdclient.NewClientOrDie(clientOpts).NewSessionClientOrDie()
|
||||
defer util.Close(conn)
|
||||
|
||||
ctx := context.Background()
|
||||
response, err := client.GetUserInfo(ctx, &session.GetUserInfoRequest{})
|
||||
errors.CheckError(err)
|
||||
|
||||
switch output {
|
||||
case "yaml":
|
||||
yamlBytes, err := yaml.Marshal(response)
|
||||
errors.CheckError(err)
|
||||
fmt.Println(string(yamlBytes))
|
||||
case "json":
|
||||
jsonBytes, err := json.MarshalIndent(response, "", " ")
|
||||
errors.CheckError(err)
|
||||
fmt.Println(string(jsonBytes))
|
||||
case "":
|
||||
fmt.Printf("Logged In: %v\n", response.LoggedIn)
|
||||
if response.LoggedIn {
|
||||
fmt.Printf("Username: %s\n", response.Username)
|
||||
fmt.Printf("Issuer: %s\n", response.Iss)
|
||||
fmt.Printf("Groups: %v\n", strings.Join(response.Groups, ","))
|
||||
}
|
||||
default:
|
||||
log.Fatalf("Unknown output format: %s", output)
|
||||
}
|
||||
},
|
||||
}
|
||||
command.Flags().StringVarP(&output, "output", "o", "", "Output format. One of: yaml, json")
|
||||
return command
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,23 +3,16 @@
|
|||
|
||||
package account // import "github.com/argoproj/argo-cd/pkg/apiclient/account"
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
import _ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
math "math"
|
||||
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
context "golang.org/x/net/context"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
|
||||
io "io"
|
||||
)
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
|
|||
|
|
@ -9,33 +9,22 @@ package application // import "github.com/argoproj/argo-cd/pkg/apiclient/applica
|
|||
Application Service API performs CRUD actions against application resources
|
||||
*/
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
import apiclient "github.com/argoproj/argo-cd/reposerver/apiclient"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
import _ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
import v11 "k8s.io/api/core/v1"
|
||||
import v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
math "math"
|
||||
import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto"
|
||||
|
||||
v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
|
||||
apiclient "github.com/argoproj/argo-cd/reposerver/apiclient"
|
||||
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
v11 "k8s.io/api/core/v1"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
context "golang.org/x/net/context"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
|
||||
github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto"
|
||||
|
||||
io "io"
|
||||
)
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
|
|||
|
|
@ -10,25 +10,17 @@ package certificate // import "github.com/argoproj/argo-cd/pkg/apiclient/certifi
|
|||
resources.
|
||||
*/
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
import _ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
math "math"
|
||||
|
||||
v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
context "golang.org/x/net/context"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
|
||||
io "io"
|
||||
)
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
|
|||
|
|
@ -9,27 +9,18 @@ package cluster // import "github.com/argoproj/argo-cd/pkg/apiclient/cluster"
|
|||
Cluster Service API performs CRUD actions against cluster resources
|
||||
*/
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
import _ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
import _ "k8s.io/api/core/v1"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
math "math"
|
||||
|
||||
v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
_ "k8s.io/api/core/v1"
|
||||
|
||||
context "golang.org/x/net/context"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
|
||||
io "io"
|
||||
)
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
|
|||
|
|
@ -9,29 +9,19 @@ package project // import "github.com/argoproj/argo-cd/pkg/apiclient/project"
|
|||
Project Service API performs CRUD actions against project resources
|
||||
*/
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
import _ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
import v1 "k8s.io/api/core/v1"
|
||||
import _ "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
math "math"
|
||||
|
||||
v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
|
||||
_ "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
context "golang.org/x/net/context"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
|
||||
io "io"
|
||||
)
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
|
|||
|
|
@ -9,29 +9,19 @@ package repository // import "github.com/argoproj/argo-cd/pkg/apiclient/reposito
|
|||
Repository Service API performs CRUD actions against repository resources
|
||||
*/
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
import apiclient "github.com/argoproj/argo-cd/reposerver/apiclient"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
import _ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
import _ "k8s.io/api/core/v1"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
math "math"
|
||||
|
||||
v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
|
||||
apiclient "github.com/argoproj/argo-cd/reposerver/apiclient"
|
||||
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
_ "k8s.io/api/core/v1"
|
||||
|
||||
context "golang.org/x/net/context"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
|
||||
io "io"
|
||||
)
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
|
|||
|
|
@ -9,27 +9,18 @@ package session // import "github.com/argoproj/argo-cd/pkg/apiclient/session"
|
|||
Session Service API performs CRUD actions against session resources
|
||||
*/
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import _ "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
import _ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
import _ "k8s.io/api/core/v1"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
math "math"
|
||||
|
||||
_ "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
_ "k8s.io/api/core/v1"
|
||||
|
||||
context "golang.org/x/net/context"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
|
||||
io "io"
|
||||
)
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
@ -56,7 +47,7 @@ func (m *SessionCreateRequest) Reset() { *m = SessionCreateRequest{} }
|
|||
func (m *SessionCreateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*SessionCreateRequest) ProtoMessage() {}
|
||||
func (*SessionCreateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_session_8fc70660de77cae0, []int{0}
|
||||
return fileDescriptor_session_7576be4936f004e2, []int{0}
|
||||
}
|
||||
func (m *SessionCreateRequest) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
|
@ -117,7 +108,7 @@ func (m *SessionDeleteRequest) Reset() { *m = SessionDeleteRequest{} }
|
|||
func (m *SessionDeleteRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*SessionDeleteRequest) ProtoMessage() {}
|
||||
func (*SessionDeleteRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_session_8fc70660de77cae0, []int{1}
|
||||
return fileDescriptor_session_7576be4936f004e2, []int{1}
|
||||
}
|
||||
func (m *SessionDeleteRequest) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
|
@ -158,7 +149,7 @@ func (m *SessionResponse) Reset() { *m = SessionResponse{} }
|
|||
func (m *SessionResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*SessionResponse) ProtoMessage() {}
|
||||
func (*SessionResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_session_8fc70660de77cae0, []int{2}
|
||||
return fileDescriptor_session_7576be4936f004e2, []int{2}
|
||||
}
|
||||
func (m *SessionResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
|
|
@ -194,10 +185,124 @@ func (m *SessionResponse) GetToken() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// Get the current user's userInfo info
|
||||
type GetUserInfoRequest struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *GetUserInfoRequest) Reset() { *m = GetUserInfoRequest{} }
|
||||
func (m *GetUserInfoRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*GetUserInfoRequest) ProtoMessage() {}
|
||||
func (*GetUserInfoRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_session_7576be4936f004e2, []int{3}
|
||||
}
|
||||
func (m *GetUserInfoRequest) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *GetUserInfoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_GetUserInfoRequest.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalTo(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (dst *GetUserInfoRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GetUserInfoRequest.Merge(dst, src)
|
||||
}
|
||||
func (m *GetUserInfoRequest) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *GetUserInfoRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GetUserInfoRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GetUserInfoRequest proto.InternalMessageInfo
|
||||
|
||||
// The current user's userInfo info
|
||||
type GetUserInfoResponse struct {
|
||||
LoggedIn bool `protobuf:"varint,1,opt,name=loggedIn,proto3" json:"loggedIn,omitempty"`
|
||||
Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
|
||||
Iss string `protobuf:"bytes,3,opt,name=iss,proto3" json:"iss,omitempty"`
|
||||
Groups []string `protobuf:"bytes,4,rep,name=groups" json:"groups,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *GetUserInfoResponse) Reset() { *m = GetUserInfoResponse{} }
|
||||
func (m *GetUserInfoResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*GetUserInfoResponse) ProtoMessage() {}
|
||||
func (*GetUserInfoResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_session_7576be4936f004e2, []int{4}
|
||||
}
|
||||
func (m *GetUserInfoResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *GetUserInfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_GetUserInfoResponse.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalTo(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (dst *GetUserInfoResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GetUserInfoResponse.Merge(dst, src)
|
||||
}
|
||||
func (m *GetUserInfoResponse) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *GetUserInfoResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GetUserInfoResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GetUserInfoResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *GetUserInfoResponse) GetLoggedIn() bool {
|
||||
if m != nil {
|
||||
return m.LoggedIn
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *GetUserInfoResponse) GetUsername() string {
|
||||
if m != nil {
|
||||
return m.Username
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *GetUserInfoResponse) GetIss() string {
|
||||
if m != nil {
|
||||
return m.Iss
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *GetUserInfoResponse) GetGroups() []string {
|
||||
if m != nil {
|
||||
return m.Groups
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*SessionCreateRequest)(nil), "session.SessionCreateRequest")
|
||||
proto.RegisterType((*SessionDeleteRequest)(nil), "session.SessionDeleteRequest")
|
||||
proto.RegisterType((*SessionResponse)(nil), "session.SessionResponse")
|
||||
proto.RegisterType((*GetUserInfoRequest)(nil), "session.GetUserInfoRequest")
|
||||
proto.RegisterType((*GetUserInfoResponse)(nil), "session.GetUserInfoResponse")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
@ -211,6 +316,8 @@ const _ = grpc.SupportPackageIsVersion4
|
|||
// Client API for SessionService service
|
||||
|
||||
type SessionServiceClient interface {
|
||||
// Get the current user's info
|
||||
GetUserInfo(ctx context.Context, in *GetUserInfoRequest, opts ...grpc.CallOption) (*GetUserInfoResponse, error)
|
||||
// Create a new JWT for authentication and set a cookie if using HTTP.
|
||||
Create(ctx context.Context, in *SessionCreateRequest, opts ...grpc.CallOption) (*SessionResponse, error)
|
||||
// Delete an existing JWT cookie if using HTTP.
|
||||
|
|
@ -225,6 +332,15 @@ func NewSessionServiceClient(cc *grpc.ClientConn) SessionServiceClient {
|
|||
return &sessionServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *sessionServiceClient) GetUserInfo(ctx context.Context, in *GetUserInfoRequest, opts ...grpc.CallOption) (*GetUserInfoResponse, error) {
|
||||
out := new(GetUserInfoResponse)
|
||||
err := c.cc.Invoke(ctx, "/session.SessionService/GetUserInfo", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sessionServiceClient) Create(ctx context.Context, in *SessionCreateRequest, opts ...grpc.CallOption) (*SessionResponse, error) {
|
||||
out := new(SessionResponse)
|
||||
err := c.cc.Invoke(ctx, "/session.SessionService/Create", in, out, opts...)
|
||||
|
|
@ -246,6 +362,8 @@ func (c *sessionServiceClient) Delete(ctx context.Context, in *SessionDeleteRequ
|
|||
// Server API for SessionService service
|
||||
|
||||
type SessionServiceServer interface {
|
||||
// Get the current user's info
|
||||
GetUserInfo(context.Context, *GetUserInfoRequest) (*GetUserInfoResponse, error)
|
||||
// Create a new JWT for authentication and set a cookie if using HTTP.
|
||||
Create(context.Context, *SessionCreateRequest) (*SessionResponse, error)
|
||||
// Delete an existing JWT cookie if using HTTP.
|
||||
|
|
@ -256,6 +374,24 @@ func RegisterSessionServiceServer(s *grpc.Server, srv SessionServiceServer) {
|
|||
s.RegisterService(&_SessionService_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _SessionService_GetUserInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetUserInfoRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SessionServiceServer).GetUserInfo(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/session.SessionService/GetUserInfo",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SessionServiceServer).GetUserInfo(ctx, req.(*GetUserInfoRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SessionService_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SessionCreateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
|
|
@ -296,6 +432,10 @@ var _SessionService_serviceDesc = grpc.ServiceDesc{
|
|||
ServiceName: "session.SessionService",
|
||||
HandlerType: (*SessionServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetUserInfo",
|
||||
Handler: _SessionService_GetUserInfo_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Create",
|
||||
Handler: _SessionService_Create_Handler,
|
||||
|
|
@ -396,6 +536,85 @@ func (m *SessionResponse) MarshalTo(dAtA []byte) (int, error) {
|
|||
return i, nil
|
||||
}
|
||||
|
||||
func (m *GetUserInfoRequest) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *GetUserInfoRequest) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *GetUserInfoResponse) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *GetUserInfoResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.LoggedIn {
|
||||
dAtA[i] = 0x8
|
||||
i++
|
||||
if m.LoggedIn {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i++
|
||||
}
|
||||
if len(m.Username) > 0 {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintSession(dAtA, i, uint64(len(m.Username)))
|
||||
i += copy(dAtA[i:], m.Username)
|
||||
}
|
||||
if len(m.Iss) > 0 {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintSession(dAtA, i, uint64(len(m.Iss)))
|
||||
i += copy(dAtA[i:], m.Iss)
|
||||
}
|
||||
if len(m.Groups) > 0 {
|
||||
for _, s := range m.Groups {
|
||||
dAtA[i] = 0x22
|
||||
i++
|
||||
l = len(s)
|
||||
for l >= 1<<7 {
|
||||
dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
|
||||
l >>= 7
|
||||
i++
|
||||
}
|
||||
dAtA[i] = uint8(l)
|
||||
i++
|
||||
i += copy(dAtA[i:], s)
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeVarintSession(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
|
|
@ -448,6 +667,41 @@ func (m *SessionResponse) Size() (n int) {
|
|||
return n
|
||||
}
|
||||
|
||||
func (m *GetUserInfoRequest) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *GetUserInfoResponse) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.LoggedIn {
|
||||
n += 2
|
||||
}
|
||||
l = len(m.Username)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovSession(uint64(l))
|
||||
}
|
||||
l = len(m.Iss)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovSession(uint64(l))
|
||||
}
|
||||
if len(m.Groups) > 0 {
|
||||
for _, s := range m.Groups {
|
||||
l = len(s)
|
||||
n += 1 + l + sovSession(uint64(l))
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovSession(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
|
|
@ -730,6 +984,215 @@ func (m *SessionResponse) Unmarshal(dAtA []byte) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
func (m *GetUserInfoRequest) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowSession
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: GetUserInfoRequest: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: GetUserInfoRequest: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipSession(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthSession
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *GetUserInfoResponse) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowSession
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: GetUserInfoResponse: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: GetUserInfoResponse: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field LoggedIn", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowSession
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.LoggedIn = bool(v != 0)
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Username", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowSession
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthSession
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Username = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Iss", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowSession
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthSession
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Iss = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Groups", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowSession
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthSession
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Groups = append(m.Groups, string(dAtA[iNdEx:postIndex]))
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipSession(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthSession
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipSession(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
|
|
@ -836,32 +1299,38 @@ var (
|
|||
)
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("server/session/session.proto", fileDescriptor_session_8fc70660de77cae0)
|
||||
proto.RegisterFile("server/session/session.proto", fileDescriptor_session_7576be4936f004e2)
|
||||
}
|
||||
|
||||
var fileDescriptor_session_8fc70660de77cae0 = []byte{
|
||||
// 360 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0x4f, 0x4b, 0xe3, 0x40,
|
||||
0x18, 0xc6, 0x99, 0x2e, 0xdb, 0xdd, 0x9d, 0xc3, 0x96, 0x0d, 0x61, 0x0d, 0xa1, 0x16, 0xc9, 0x45,
|
||||
0x29, 0x98, 0x21, 0x7a, 0x11, 0x2f, 0x82, 0x7a, 0xf1, 0xda, 0xde, 0x0a, 0x1e, 0xa6, 0xc9, 0x4b,
|
||||
0x3a, 0x36, 0x9d, 0x77, 0x9c, 0x99, 0xc6, 0xbb, 0x5f, 0xc1, 0x2f, 0x25, 0x78, 0x11, 0xfc, 0x02,
|
||||
0x52, 0xfc, 0x20, 0xd2, 0x49, 0x52, 0xb5, 0x15, 0xf1, 0x94, 0x79, 0xe6, 0x99, 0xfc, 0x9e, 0xf7,
|
||||
0x0f, 0xed, 0x1a, 0xd0, 0x25, 0x68, 0x66, 0xc0, 0x18, 0x81, 0xb2, 0xf9, 0xc6, 0x4a, 0xa3, 0x45,
|
||||
0xef, 0x57, 0x2d, 0x43, 0x3f, 0xc7, 0x1c, 0xdd, 0x1d, 0x5b, 0x9e, 0x2a, 0x3b, 0xec, 0xe6, 0x88,
|
||||
0x79, 0x01, 0x8c, 0x2b, 0xc1, 0xb8, 0x94, 0x68, 0xb9, 0x15, 0x28, 0x4d, 0xed, 0x46, 0xd3, 0x23,
|
||||
0x13, 0x0b, 0x74, 0x6e, 0x8a, 0x1a, 0x58, 0x99, 0xb0, 0x1c, 0x24, 0x68, 0x6e, 0x21, 0xab, 0xdf,
|
||||
0x5c, 0xe4, 0xc2, 0x4e, 0xe6, 0xe3, 0x38, 0xc5, 0x19, 0xe3, 0xda, 0x45, 0x5c, 0xb9, 0xc3, 0x7e,
|
||||
0x9a, 0x31, 0x35, 0xcd, 0x97, 0x3f, 0x1b, 0xc6, 0x95, 0x2a, 0x44, 0xea, 0xe0, 0xac, 0x4c, 0x78,
|
||||
0xa1, 0x26, 0x7c, 0x03, 0x15, 0x65, 0xd4, 0x1f, 0x56, 0xd5, 0x9e, 0x69, 0xe0, 0x16, 0x06, 0x70,
|
||||
0x3d, 0x07, 0x63, 0xbd, 0x90, 0xfe, 0x9e, 0x1b, 0xd0, 0x92, 0xcf, 0x20, 0x20, 0x3b, 0x64, 0xef,
|
||||
0xcf, 0x60, 0xa5, 0x97, 0x9e, 0xe2, 0xc6, 0xdc, 0xa0, 0xce, 0x82, 0x56, 0xe5, 0x35, 0xda, 0xf3,
|
||||
0xe9, 0x4f, 0x8b, 0x53, 0x90, 0xc1, 0x0f, 0x67, 0x54, 0x22, 0xfa, 0xbf, 0x4a, 0x39, 0x87, 0x02,
|
||||
0x56, 0x29, 0xd1, 0x2e, 0xed, 0xd4, 0xf7, 0x03, 0x30, 0x0a, 0xa5, 0x81, 0x37, 0x00, 0x79, 0x07,
|
||||
0x38, 0x78, 0x20, 0xf4, 0x6f, 0xfd, 0x72, 0x08, 0xba, 0x14, 0x29, 0x78, 0x97, 0xb4, 0x5d, 0x95,
|
||||
0xec, 0x6d, 0xc7, 0xcd, 0xfc, 0x3f, 0x6b, 0x25, 0x0c, 0xd6, 0xed, 0x26, 0x2b, 0x0a, 0x6f, 0x9f,
|
||||
0x5e, 0xee, 0x5a, 0x7e, 0xd4, 0x71, 0xd3, 0x2e, 0x93, 0x66, 0x8f, 0xc7, 0xa4, 0xef, 0x8d, 0x68,
|
||||
0xbb, 0xaa, 0x75, 0x13, 0xff, 0xa1, 0x87, 0x2f, 0xf0, 0x5b, 0x0e, 0xff, 0xaf, 0xbf, 0x8e, 0x3f,
|
||||
0x3d, 0xb9, 0x5f, 0xf4, 0xc8, 0xe3, 0xa2, 0x47, 0x9e, 0x17, 0x3d, 0x32, 0x4a, 0xbe, 0xb1, 0xcd,
|
||||
0xb4, 0x10, 0x20, 0x6d, 0x03, 0x18, 0xb7, 0xdd, 0xf2, 0x0e, 0x5f, 0x03, 0x00, 0x00, 0xff, 0xff,
|
||||
0x65, 0x59, 0xd0, 0x9d, 0x88, 0x02, 0x00, 0x00,
|
||||
var fileDescriptor_session_7576be4936f004e2 = []byte{
|
||||
// 453 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xcf, 0x8e, 0xd3, 0x30,
|
||||
0x10, 0xc6, 0x95, 0x16, 0x4a, 0xd7, 0x48, 0x2c, 0x98, 0x68, 0x89, 0x42, 0xa9, 0xaa, 0x5c, 0x58,
|
||||
0xad, 0x44, 0xad, 0xc2, 0x05, 0x71, 0x41, 0x02, 0x24, 0xd4, 0x6b, 0x56, 0x5c, 0x56, 0xe2, 0xe0,
|
||||
0x4d, 0x06, 0xaf, 0xb7, 0x59, 0x8f, 0xb1, 0xdd, 0xec, 0x9d, 0x57, 0xe0, 0x61, 0x78, 0x05, 0x8e,
|
||||
0x48, 0xbc, 0x00, 0xaa, 0x78, 0x10, 0x14, 0xe7, 0x0f, 0xdb, 0xb4, 0x42, 0x9c, 0xe2, 0x99, 0x2f,
|
||||
0xfe, 0x7d, 0x9f, 0x35, 0x43, 0x26, 0x16, 0x4c, 0x09, 0x86, 0x59, 0xb0, 0x56, 0xa2, 0x6a, 0xbf,
|
||||
0x73, 0x6d, 0xd0, 0x21, 0xbd, 0xd3, 0x94, 0x71, 0x28, 0x50, 0xa0, 0xef, 0xb1, 0xea, 0x54, 0xcb,
|
||||
0xf1, 0x44, 0x20, 0x8a, 0x02, 0x18, 0xd7, 0x92, 0x71, 0xa5, 0xd0, 0x71, 0x27, 0x51, 0xd9, 0x46,
|
||||
0x4d, 0x56, 0x2f, 0xed, 0x5c, 0xa2, 0x57, 0x33, 0x34, 0xc0, 0xca, 0x05, 0x13, 0xa0, 0xc0, 0x70,
|
||||
0x07, 0x79, 0xf3, 0xcf, 0x52, 0x48, 0x77, 0xb1, 0x3e, 0x9f, 0x67, 0x78, 0xc5, 0xb8, 0xf1, 0x16,
|
||||
0x97, 0xfe, 0xf0, 0x2c, 0xcb, 0x99, 0x5e, 0x89, 0xea, 0xb2, 0x65, 0x5c, 0xeb, 0x42, 0x66, 0x1e,
|
||||
0xce, 0xca, 0x05, 0x2f, 0xf4, 0x05, 0xdf, 0x41, 0x25, 0x39, 0x09, 0x4f, 0xeb, 0xb4, 0x6f, 0x0d,
|
||||
0x70, 0x07, 0x29, 0x7c, 0x5e, 0x83, 0x75, 0x34, 0x26, 0xe3, 0xb5, 0x05, 0xa3, 0xf8, 0x15, 0x44,
|
||||
0xc1, 0x2c, 0x38, 0x3e, 0x48, 0xbb, 0xba, 0xd2, 0x34, 0xb7, 0xf6, 0x1a, 0x4d, 0x1e, 0x0d, 0x6a,
|
||||
0xad, 0xad, 0x69, 0x48, 0x6e, 0x3b, 0x5c, 0x81, 0x8a, 0x86, 0x5e, 0xa8, 0x8b, 0xe4, 0xa8, 0x73,
|
||||
0x79, 0x07, 0x05, 0x74, 0x2e, 0xc9, 0x53, 0x72, 0xd8, 0xf4, 0x53, 0xb0, 0x1a, 0x95, 0x85, 0xbf,
|
||||
0x80, 0xe0, 0x26, 0x20, 0x24, 0xf4, 0x3d, 0xb8, 0x0f, 0x16, 0xcc, 0x52, 0x7d, 0xc2, 0xf6, 0xfa,
|
||||
0x35, 0x79, 0xb8, 0xd5, 0x6d, 0x10, 0x31, 0x19, 0x17, 0x28, 0x04, 0xe4, 0xcb, 0x9a, 0x32, 0x4e,
|
||||
0xbb, 0x7a, 0xeb, 0x5d, 0x83, 0xde, 0xbb, 0xee, 0x93, 0xa1, 0xb4, 0xb6, 0x49, 0x5e, 0x1d, 0xe9,
|
||||
0x11, 0x19, 0x09, 0x83, 0x6b, 0x6d, 0xa3, 0x5b, 0xb3, 0xe1, 0xf1, 0x41, 0xda, 0x54, 0xcf, 0xbf,
|
||||
0x0d, 0xc8, 0xbd, 0x26, 0xf8, 0x29, 0x98, 0x52, 0x66, 0x40, 0x2f, 0xc9, 0xdd, 0x1b, 0x59, 0xe8,
|
||||
0xe3, 0x79, 0xbb, 0x13, 0xbb, 0xb9, 0xe3, 0xc9, 0x7e, 0xb1, 0x8e, 0x9f, 0xcc, 0xbe, 0xfc, 0xfc,
|
||||
0xfd, 0x75, 0x10, 0xd3, 0xc8, 0xef, 0x40, 0xb9, 0xe8, 0xb6, 0xac, 0x0a, 0x2a, 0x2b, 0xf8, 0x47,
|
||||
0x32, 0xaa, 0xa7, 0x45, 0x9f, 0x74, 0xa4, 0x7d, 0x53, 0x8c, 0xa3, 0xbe, 0xdc, 0x99, 0xc4, 0xde,
|
||||
0x24, 0x4c, 0x0e, 0x7b, 0x26, 0xaf, 0x82, 0x13, 0x7a, 0x46, 0x46, 0xf5, 0x98, 0x76, 0xf1, 0x5b,
|
||||
0xe3, 0xfb, 0x07, 0xfe, 0x91, 0xc7, 0x3f, 0x38, 0xe9, 0xe3, 0xdf, 0xbc, 0xfe, 0xbe, 0x99, 0x06,
|
||||
0x3f, 0x36, 0xd3, 0xe0, 0xd7, 0x66, 0x1a, 0x9c, 0x2d, 0xfe, 0x63, 0x91, 0xb3, 0x42, 0x82, 0x72,
|
||||
0x2d, 0xe0, 0x7c, 0xe4, 0xf7, 0xf6, 0xc5, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8f, 0xb6, 0x16,
|
||||
0x68, 0x83, 0x03, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,15 @@ var _ status.Status
|
|||
var _ = runtime.String
|
||||
var _ = utilities.NewDoubleArray
|
||||
|
||||
func request_SessionService_GetUserInfo_0(ctx context.Context, marshaler runtime.Marshaler, client SessionServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GetUserInfoRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := client.GetUserInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_SessionService_Create_0(ctx context.Context, marshaler runtime.Marshaler, client SessionServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq SessionCreateRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
|
@ -88,6 +97,35 @@ func RegisterSessionServiceHandler(ctx context.Context, mux *runtime.ServeMux, c
|
|||
// "SessionServiceClient" to call the correct interceptors.
|
||||
func RegisterSessionServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client SessionServiceClient) error {
|
||||
|
||||
mux.Handle("GET", pattern_SessionService_GetUserInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
if cn, ok := w.(http.CloseNotifier); ok {
|
||||
go func(done <-chan struct{}, closed <-chan bool) {
|
||||
select {
|
||||
case <-done:
|
||||
case <-closed:
|
||||
cancel()
|
||||
}
|
||||
}(ctx.Done(), cn.CloseNotify())
|
||||
}
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_SessionService_GetUserInfo_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_SessionService_GetUserInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_SessionService_Create_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
|
|
@ -150,12 +188,16 @@ func RegisterSessionServiceHandlerClient(ctx context.Context, mux *runtime.Serve
|
|||
}
|
||||
|
||||
var (
|
||||
pattern_SessionService_GetUserInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "session", "userinfo"}, ""))
|
||||
|
||||
pattern_SessionService_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "session"}, ""))
|
||||
|
||||
pattern_SessionService_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "session"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_SessionService_GetUserInfo_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_SessionService_Create_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_SessionService_Delete_0 = runtime.ForwardResponseMessage
|
||||
|
|
|
|||
|
|
@ -9,27 +9,18 @@ package settings // import "github.com/argoproj/argo-cd/pkg/apiclient/settings"
|
|||
Settings Service API retrieves Argo CD settings
|
||||
*/
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
import oidc "github.com/argoproj/argo-cd/server/settings/oidc"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
import _ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
math "math"
|
||||
|
||||
v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
|
||||
oidc "github.com/argoproj/argo-cd/server/settings/oidc"
|
||||
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
context "golang.org/x/net/context"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
|
||||
io "io"
|
||||
)
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
|
|||
|
|
@ -9,23 +9,16 @@ package version // import "github.com/argoproj/argo-cd/pkg/apiclient/version"
|
|||
Version Service API returns the version of the API server.
|
||||
*/
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import empty "github.com/golang/protobuf/ptypes/empty"
|
||||
import _ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
math "math"
|
||||
|
||||
empty "github.com/golang/protobuf/ptypes/empty"
|
||||
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
context "golang.org/x/net/context"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
|
||||
io "io"
|
||||
)
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
|
|||
|
|
@ -3,27 +3,21 @@
|
|||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
import v11 "k8s.io/api/core/v1"
|
||||
import v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
math "math"
|
||||
import k8s_io_apimachinery_pkg_watch "k8s.io/apimachinery/pkg/watch"
|
||||
|
||||
v11 "k8s.io/api/core/v1"
|
||||
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
|
||||
k8s_io_apimachinery_pkg_watch "k8s.io/apimachinery/pkg/watch"
|
||||
|
||||
github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
|
||||
strings "strings"
|
||||
|
||||
reflect "reflect"
|
||||
|
||||
io "io"
|
||||
)
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
|
|||
|
|
@ -3,27 +3,18 @@
|
|||
|
||||
package apiclient // import "github.com/argoproj/argo-cd/reposerver/apiclient"
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
import _ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
import _ "k8s.io/api/core/v1"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
import context "golang.org/x/net/context"
|
||||
import grpc "google.golang.org/grpc"
|
||||
|
||||
math "math"
|
||||
|
||||
v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
|
||||
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
|
||||
_ "k8s.io/api/core/v1"
|
||||
|
||||
context "golang.org/x/net/context"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
|
||||
io "io"
|
||||
)
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package account
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
|
|
@ -11,7 +10,6 @@ import (
|
|||
|
||||
"github.com/argoproj/argo-cd/common"
|
||||
"github.com/argoproj/argo-cd/pkg/apiclient/account"
|
||||
jwtutil "github.com/argoproj/argo-cd/util/jwt"
|
||||
"github.com/argoproj/argo-cd/util/password"
|
||||
"github.com/argoproj/argo-cd/util/session"
|
||||
"github.com/argoproj/argo-cd/util/settings"
|
||||
|
|
@ -34,9 +32,9 @@ func NewServer(sessionMgr *session.SessionManager, settingsMgr *settings.Setting
|
|||
|
||||
// UpdatePassword updates the password of the local admin superuser.
|
||||
func (s *Server) UpdatePassword(ctx context.Context, q *account.UpdatePasswordRequest) (*account.UpdatePasswordResponse, error) {
|
||||
username := getAuthenticatedUser(ctx)
|
||||
if username != common.ArgoCDAdminUsername {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "password can only be changed for local users, not user %q", username)
|
||||
sub := session.Sub(ctx)
|
||||
if sub != common.ArgoCDAdminUsername {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "password can only be changed for local users, not user %q", sub)
|
||||
}
|
||||
|
||||
cdSettings, err := s.settingsMgr.GetSettings()
|
||||
|
|
@ -44,7 +42,7 @@ func (s *Server) UpdatePassword(ctx context.Context, q *account.UpdatePasswordRe
|
|||
return nil, err
|
||||
}
|
||||
|
||||
err = s.sessionMgr.VerifyUsernamePassword(username, q.CurrentPassword)
|
||||
err = s.sessionMgr.VerifyUsernamePassword(sub, q.CurrentPassword)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "current password does not match")
|
||||
}
|
||||
|
|
@ -61,24 +59,7 @@ func (s *Server) UpdatePassword(ctx context.Context, q *account.UpdatePasswordRe
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Infof("user '%s' updated password", username)
|
||||
log.Infof("user '%s' updated password", sub)
|
||||
return &account.UpdatePasswordResponse{}, nil
|
||||
|
||||
}
|
||||
|
||||
// getAuthenticatedUser returns the currently authenticated user (via JWT 'sub' field)
|
||||
func getAuthenticatedUser(ctx context.Context) string {
|
||||
claimsIf := ctx.Value("claims")
|
||||
if claimsIf == nil {
|
||||
return ""
|
||||
}
|
||||
claims, ok := claimsIf.(jwt.Claims)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
mapClaims, err := jwtutil.MapClaims(claims)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return jwtutil.GetField(mapClaims, "sub")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ func newTestAccountServer(ctx context.Context) (*fake.Clientset, *Server, *sessi
|
|||
})
|
||||
settingsMgr := settings.NewSettingsManager(ctx, kubeclientset, testNamespace)
|
||||
sessionMgr := sessionutil.NewSessionManager(settingsMgr, "")
|
||||
return kubeclientset, NewServer(sessionMgr, settingsMgr), session.NewServer(sessionMgr)
|
||||
return kubeclientset, NewServer(sessionMgr, settingsMgr), session.NewServer(sessionMgr, nil)
|
||||
}
|
||||
|
||||
func TestUpdatePassword(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ import (
|
|||
"github.com/argoproj/argo-cd/util/healthz"
|
||||
httputil "github.com/argoproj/argo-cd/util/http"
|
||||
jsonutil "github.com/argoproj/argo-cd/util/json"
|
||||
"github.com/argoproj/argo-cd/util/jwt/zjwt"
|
||||
"github.com/argoproj/argo-cd/util/kube"
|
||||
"github.com/argoproj/argo-cd/util/oidc"
|
||||
"github.com/argoproj/argo-cd/util/rbac"
|
||||
|
|
@ -426,7 +427,7 @@ func (a *ArgoCDServer) newGRPCServer() *grpc.Server {
|
|||
sOpts = append(sOpts, grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
|
||||
grpc_logrus.StreamServerInterceptor(a.log),
|
||||
grpc_prometheus.StreamServerInterceptor,
|
||||
grpc_auth.StreamServerInterceptor(a.authenticate),
|
||||
grpc_auth.StreamServerInterceptor(a.Authenticate),
|
||||
grpc_util.UserAgentStreamServerInterceptor(common.ArgoCDUserAgentName, clientConstraint),
|
||||
grpc_util.PayloadStreamServerInterceptor(a.log, true, func(ctx netCtx.Context, fullMethodName string, servingObject interface{}) bool {
|
||||
return !sensitiveMethods[fullMethodName]
|
||||
|
|
@ -438,7 +439,7 @@ func (a *ArgoCDServer) newGRPCServer() *grpc.Server {
|
|||
bug21955WorkaroundInterceptor,
|
||||
grpc_logrus.UnaryServerInterceptor(a.log),
|
||||
grpc_prometheus.UnaryServerInterceptor,
|
||||
grpc_auth.UnaryServerInterceptor(a.authenticate),
|
||||
grpc_auth.UnaryServerInterceptor(a.Authenticate),
|
||||
grpc_util.UserAgentUnaryServerInterceptor(common.ArgoCDUserAgentName, clientConstraint),
|
||||
grpc_util.PayloadUnaryServerInterceptor(a.log, true, func(ctx netCtx.Context, fullMethodName string, servingObject interface{}) bool {
|
||||
return !sensitiveMethods[fullMethodName]
|
||||
|
|
@ -450,7 +451,7 @@ func (a *ArgoCDServer) newGRPCServer() *grpc.Server {
|
|||
db := db.NewDB(a.Namespace, a.settingsMgr, a.KubeClientset)
|
||||
clusterService := cluster.NewServer(db, a.enf, a.Cache)
|
||||
repoService := repository.NewServer(a.RepoClientset, db, a.enf, a.Cache, a.settingsMgr)
|
||||
sessionService := session.NewServer(a.sessionMgr)
|
||||
sessionService := session.NewServer(a.sessionMgr, a)
|
||||
projectLock := util.NewKeyLock()
|
||||
applicationService := application.NewServer(a.Namespace, a.KubeClientset, a.AppClientset, a.RepoClientset, a.Cache, kube.KubectlCmd{}, db, a.enf, projectLock, a.settingsMgr)
|
||||
projectService := project.NewServer(a.Namespace, a.KubeClientset, a.AppClientset, a.enf, projectLock, a.sessionMgr)
|
||||
|
|
@ -479,12 +480,18 @@ func (a *ArgoCDServer) translateGrpcCookieHeader(ctx context.Context, w http.Res
|
|||
if !a.Insecure {
|
||||
flags = append(flags, "Secure")
|
||||
}
|
||||
cookie, err := httputil.MakeCookieMetadata(common.AuthCookieName, sessionResp.Token, flags...)
|
||||
if err != nil {
|
||||
return err
|
||||
token := sessionResp.Token
|
||||
if token != "" {
|
||||
token, err := zjwt.ZJWT(token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cookie, err := httputil.MakeCookieMetadata(common.AuthCookieName, token, flags...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.Header().Set("Set-Cookie", cookie)
|
||||
}
|
||||
|
||||
w.Header().Set("Set-Cookie", cookie)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -708,7 +715,7 @@ func mustRegisterGWHandler(register registerFunc, ctx context.Context, mux *runt
|
|||
}
|
||||
|
||||
// Authenticate checks for the presence of a valid token when accessing server-side resources.
|
||||
func (a *ArgoCDServer) authenticate(ctx context.Context) (context.Context, error) {
|
||||
func (a *ArgoCDServer) Authenticate(ctx context.Context) (context.Context, error) {
|
||||
if a.DisableAuth {
|
||||
return ctx, nil
|
||||
}
|
||||
|
|
@ -758,7 +765,10 @@ func getToken(md metadata.MD) string {
|
|||
request := http.Request{Header: header}
|
||||
token, err := request.Cookie(common.AuthCookieName)
|
||||
if err == nil {
|
||||
return token.Value
|
||||
value, err := zjwt.JWT(token.Value)
|
||||
if err == nil {
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ func TestAuthenticate(t *testing.T) {
|
|||
ctx = metadata.NewIncomingContext(context.Background(), metadata.Pairs(apiclient.MetaDataTokenKey, token))
|
||||
}
|
||||
|
||||
_, err := argocd.authenticate(ctx)
|
||||
_, err := argocd.Authenticate(ctx)
|
||||
if testData.errorMsg != "" {
|
||||
assert.Errorf(t, err, testData.errorMsg)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -12,14 +12,17 @@ import (
|
|||
|
||||
// Server provides a Session service
|
||||
type Server struct {
|
||||
mgr *sessionmgr.SessionManager
|
||||
mgr *sessionmgr.SessionManager
|
||||
authenticator Authenticator
|
||||
}
|
||||
|
||||
type Authenticator interface {
|
||||
Authenticate(ctx context.Context) (context.Context, error)
|
||||
}
|
||||
|
||||
// NewServer returns a new instance of the Session service
|
||||
func NewServer(mgr *sessionmgr.SessionManager) *Server {
|
||||
return &Server{
|
||||
mgr: mgr,
|
||||
}
|
||||
func NewServer(mgr *sessionmgr.SessionManager, authenticator Authenticator) *Server {
|
||||
return &Server{mgr, authenticator}
|
||||
}
|
||||
|
||||
// Create generates a JWT token signed by Argo CD intended for web/CLI logins of the admin user
|
||||
|
|
@ -52,5 +55,16 @@ func (s *Server) Delete(ctx context.Context, q *session.SessionDeleteRequest) (*
|
|||
// Since this service is generally invoked when the user has _no_ credentials, that would create a
|
||||
// chicken-and-egg situation if we didn't place this here to allow traffic to pass through.
|
||||
func (s *Server) AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error) {
|
||||
// this authenticates the user, but ignores any error, so that we have claims populated
|
||||
ctx, _ = s.authenticator.Authenticate(ctx)
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (s *Server) GetUserInfo(ctx context.Context, q *session.GetUserInfoRequest) (*session.GetUserInfoResponse, error) {
|
||||
return &session.GetUserInfoResponse{
|
||||
LoggedIn: sessionmgr.LoggedIn(ctx),
|
||||
Username: sessionmgr.Username(ctx),
|
||||
Iss: sessionmgr.Iss(ctx),
|
||||
Groups: sessionmgr.Groups(ctx),
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ option go_package = "github.com/argoproj/argo-cd/pkg/apiclient/session";
|
|||
|
||||
// Session Service
|
||||
//
|
||||
// Session Service API performs CRUD actions against session resources
|
||||
// Session Service API performs CRUD actions against session resources
|
||||
package session;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
|
|
@ -27,9 +27,26 @@ message SessionResponse {
|
|||
string token = 1;
|
||||
}
|
||||
|
||||
// Get the current user's userInfo info
|
||||
message GetUserInfoRequest {
|
||||
}
|
||||
|
||||
// The current user's userInfo info
|
||||
message GetUserInfoResponse {
|
||||
bool loggedIn = 1;
|
||||
string username = 2;
|
||||
string iss = 3;
|
||||
repeated string groups = 4;
|
||||
}
|
||||
|
||||
// SessionService
|
||||
service SessionService {
|
||||
|
||||
// Get the current user's info
|
||||
rpc GetUserInfo (GetUserInfoRequest) returns (GetUserInfoResponse) {
|
||||
option (google.api.http).get = "/api/v1/session/userinfo";
|
||||
}
|
||||
|
||||
// Create a new JWT for authentication and set a cookie if using HTTP.
|
||||
rpc Create(SessionCreateRequest) returns (SessionResponse) {
|
||||
option (google.api.http) = {
|
||||
|
|
|
|||
|
|
@ -3,15 +3,11 @@
|
|||
|
||||
package oidc // import "github.com/argoproj/argo-cd/server/settings/oidc"
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
|
||||
math "math"
|
||||
|
||||
io "io"
|
||||
)
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ func EnsureCleanState(t *testing.T) {
|
|||
FailOnErr(Run("", "kubectl", "create", "ns", DeploymentNamespace()))
|
||||
FailOnErr(Run("", "kubectl", "label", "ns", DeploymentNamespace(), testingLabel+"=true"))
|
||||
|
||||
log.WithFields(log.Fields{"duration": time.Since(start), "name": name, "id": id}).Info("clean state")
|
||||
log.WithFields(log.Fields{"duration": time.Since(start), "name": name, "id": id, "username": "admin", "password": "password"}).Info("clean state")
|
||||
}
|
||||
|
||||
func RunCli(args ...string) (string, error) {
|
||||
|
|
|
|||
21
test/e2e/user_info_test.go
Normal file
21
test/e2e/user_info_test.go
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package e2e
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
. "github.com/argoproj/argo-cd/test/e2e/fixture"
|
||||
)
|
||||
|
||||
func TestUserInfo(t *testing.T) {
|
||||
EnsureCleanState(t)
|
||||
|
||||
output, err := RunCli("account", "get-user-info")
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, `Logged In: true
|
||||
Username: admin
|
||||
Issuer: argocd
|
||||
Groups: `, output)
|
||||
}
|
||||
|
|
@ -16,7 +16,6 @@
|
|||
"@types/deepmerge": "^2.2.0",
|
||||
"@types/git-url-parse": "^9.0.0",
|
||||
"@types/js-yaml": "^3.11.2",
|
||||
"@types/jwt-decode": "^2.2.1",
|
||||
"@types/minimatch": "^3.0.3",
|
||||
"@types/prop-types": "^15.5.2",
|
||||
"@types/react": "^16.8.5",
|
||||
|
|
@ -46,7 +45,6 @@
|
|||
"jscs": "^3.0.7",
|
||||
"json-merge-patch": "^0.2.3",
|
||||
"jsondiffpatch": "^0.3.5",
|
||||
"jwt-decode": "^2.2.0",
|
||||
"minimatch": "^3.0.4",
|
||||
"moment": "^2.24.0",
|
||||
"monaco-editor": "^0.15.6",
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@ import {
|
|||
PopupManager,
|
||||
PopupProps,
|
||||
} from 'argo-ui';
|
||||
import * as cookie from 'cookie';
|
||||
import {createBrowserHistory} from 'history';
|
||||
import * as jwtDecode from 'jwt-decode';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import * as React from 'react';
|
||||
import {Helmet} from 'react-helmet';
|
||||
|
|
@ -25,6 +23,7 @@ import {Provider} from './shared/context';
|
|||
import {services} from './shared/services';
|
||||
import requests from './shared/services/requests';
|
||||
import {hashCode} from './shared/utils';
|
||||
import userInfo from './user-info';
|
||||
|
||||
services.viewPreferences.init();
|
||||
const bases = document.getElementsByTagName('base');
|
||||
|
|
@ -36,6 +35,7 @@ const routes: {[path: string]: { component: React.ComponentType<RouteComponentPr
|
|||
'/login': { component: login.component as any, noLayout: true },
|
||||
'/applications': { component: applications.component },
|
||||
'/settings': { component: settings.component },
|
||||
'/user-info': { component: userInfo.component },
|
||||
'/help': { component: help.component },
|
||||
};
|
||||
|
||||
|
|
@ -47,6 +47,10 @@ const navItems = [{
|
|||
title: 'Manage your repositories, projects, settings',
|
||||
path: '/settings',
|
||||
iconClassName: 'argo-icon-settings',
|
||||
}, {
|
||||
title: 'User Info',
|
||||
path: '/user-info',
|
||||
iconClassName: 'fa fa-user-circle',
|
||||
}, {
|
||||
title: 'Read the documentation, and get help and assistance.',
|
||||
path: '/help',
|
||||
|
|
@ -55,13 +59,10 @@ const navItems = [{
|
|||
|
||||
async function isExpiredSSO() {
|
||||
try {
|
||||
const token = cookie.parse(document.cookie)['argocd.token'];
|
||||
if (token) {
|
||||
const jwtToken = jwtDecode(token) as any;
|
||||
if (jwtToken.iss && jwtToken.iss !== 'argocd') {
|
||||
const authSettings = await services.authService.settings();
|
||||
return (authSettings.dexConfig && authSettings.dexConfig.connectors || []).length > 0 || authSettings.oidcConfig;
|
||||
}
|
||||
const {loggedIn, iss} = await services.users.get();
|
||||
if (loggedIn && iss !== 'argocd') {
|
||||
const authSettings = await services.authService.settings();
|
||||
return (authSettings.dexConfig && authSettings.dexConfig.connectors || []).length > 0 || authSettings.oidcConfig;
|
||||
}
|
||||
} catch {
|
||||
return false;
|
||||
|
|
@ -108,20 +109,15 @@ export class App extends React.Component<{}, { popupProps: PopupProps, error: Er
|
|||
|
||||
public async componentDidMount() {
|
||||
this.popupManager.popupProps.subscribe((popupProps) => this.setState({ popupProps }));
|
||||
const gaSettings = await services.authService.settings().then((item) => item.googleAnalytics || { trackingID: '', anonymizeUsers: true });
|
||||
const { trackingID, anonymizeUsers } = gaSettings;
|
||||
const { trackingID, anonymizeUsers } = await services.authService.settings().then((item) => item.googleAnalytics || { trackingID: '', anonymizeUsers: true });
|
||||
const {loggedIn, username} = await services.users.get();
|
||||
if (trackingID) {
|
||||
const ga = await import('react-ga');
|
||||
ga.initialize(trackingID);
|
||||
let userId = '';
|
||||
const trackPageView = () => {
|
||||
let nextUserId = services.authService.getCurrentUserId();
|
||||
if (anonymizeUsers) {
|
||||
nextUserId = hashCode(nextUserId).toString();
|
||||
}
|
||||
if (nextUserId !== userId) {
|
||||
userId = nextUserId;
|
||||
ga.set({ userId });
|
||||
if (loggedIn) {
|
||||
const userId = !anonymizeUsers ? username : hashCode(username).toString();
|
||||
ga.set({userId});
|
||||
}
|
||||
ga.pageview(location.pathname + location.search);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { DataLoader, Page as ArgoPage, Toolbar, Utils } from 'argo-ui';
|
||||
import {DataLoader, Page as ArgoPage, Toolbar, Utils} from 'argo-ui';
|
||||
import { parse } from 'cookie';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import * as React from 'react';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { AppContext } from '../context';
|
||||
import { services } from '../services';
|
||||
import {Observable} from 'rxjs';
|
||||
import {AppContext} from '../context';
|
||||
import {services} from '../services';
|
||||
|
||||
export class Page extends React.Component<{ title: string, toolbar?: Toolbar | Observable<Toolbar> }> {
|
||||
public static contextTypes = {
|
||||
|
|
@ -18,7 +18,8 @@ export class Page extends React.Component<{ title: string, toolbar?: Toolbar | O
|
|||
toolbar = toolbar || {};
|
||||
toolbar.tools = [
|
||||
toolbar.tools,
|
||||
services.authService.getCurrentUserId() ?
|
||||
// this is a crummy check, as the token maybe expired, but it is better than flashing user interface
|
||||
parse(document.cookie)['argocd.token'] ?
|
||||
<a key='logout' onClick={() => this.goToLogin(true)}>Logout</a> :
|
||||
<a key='login' onClick={() => this.goToLogin(false)}>Login</a>,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -340,6 +340,13 @@ export interface AuthSettings {
|
|||
};
|
||||
}
|
||||
|
||||
export interface UserInfo {
|
||||
loggedIn: boolean;
|
||||
username: string;
|
||||
iss: string;
|
||||
groups: string[];
|
||||
}
|
||||
|
||||
export type ConnectionStatus = 'Unknown' | 'Successful' | 'Failed';
|
||||
|
||||
export const ConnectionStatuses = {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
import { parse } from 'cookie';
|
||||
import * as jwt from 'jwt-decode';
|
||||
|
||||
import { AuthSettings } from '../models';
|
||||
import requests from './requests';
|
||||
|
||||
|
|
@ -8,11 +5,4 @@ export class AuthService {
|
|||
public settings(): Promise<AuthSettings> {
|
||||
return requests.get('/settings').then((res) => res.body as AuthSettings);
|
||||
}
|
||||
|
||||
public getCurrentUserId(): string {
|
||||
const cookies = parse(document.cookie);
|
||||
const token = cookies['argocd.token'];
|
||||
const user: any = token && jwt(token) || null;
|
||||
return (user && (user.email || user.sub)) || '';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import {UserInfo} from '../models';
|
||||
import requests from './requests';
|
||||
|
||||
export class UserService {
|
||||
|
|
@ -8,4 +9,8 @@ export class UserService {
|
|||
public logout(): Promise<boolean> {
|
||||
return requests.delete('/session').then((res) => true);
|
||||
}
|
||||
|
||||
public get(): Promise<UserInfo> {
|
||||
return requests.get('/session/userinfo').then((res) => res.body as UserInfo);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
10
ui/src/app/user-info/components/user-info-container.tsx
Normal file
10
ui/src/app/user-info/components/user-info-container.tsx
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import * as React from 'react';
|
||||
import { Route, RouteComponentProps, Switch } from 'react-router';
|
||||
|
||||
import { UserInfoOverview } from './user-info-overview/user-info-overview';
|
||||
|
||||
export const UserInfoContainer = (props: RouteComponentProps<any>) => (
|
||||
<Switch>
|
||||
<Route exact={true} path={`${props.match.path}`} component={UserInfoOverview}/>
|
||||
</Switch>
|
||||
);
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
@import 'node_modules/argo-ui/src/app/shared/styles/config';
|
||||
|
||||
.user-info-overview {
|
||||
&__panel {
|
||||
margin: 18px 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import {DataLoader, Page} from '../../../shared/components';
|
||||
import {services} from '../../../shared/services';
|
||||
|
||||
require('./user-info-overview.scss');
|
||||
|
||||
export const UserInfoOverview = () => (
|
||||
<Page title='User Info' toolbar={{breadcrumbs: [{title: 'User Info'}]}}>
|
||||
<div className='user-info'>
|
||||
<div className='argo-container'>
|
||||
<div className='user-info-overview__panel white-box'>
|
||||
<DataLoader key='userInfo' load={() => services.users.get()}>{(userInfo) => (
|
||||
userInfo.loggedIn ? (
|
||||
<React.Fragment key='userInfoInner'>
|
||||
<p key='username'>Username: {userInfo.username}</p>
|
||||
<p key='iss'>Issuer: {userInfo.iss}</p>
|
||||
{userInfo.groups && (<React.Fragment key='userInfo4'><p>Groups:</p>
|
||||
<ul>
|
||||
{userInfo.groups.map((group) => (
|
||||
<li key={group}>{group}</li>
|
||||
))}
|
||||
</ul>
|
||||
</React.Fragment>)}
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<p key='loggedOutMessage'>You are not logged in</p>
|
||||
)
|
||||
)}</DataLoader>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Page>
|
||||
);
|
||||
5
ui/src/app/user-info/index.ts
Normal file
5
ui/src/app/user-info/index.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { UserInfoContainer } from './components/user-info-container';
|
||||
|
||||
export default {
|
||||
component: UserInfoContainer,
|
||||
};
|
||||
10
ui/yarn.lock
10
ui/yarn.lock
|
|
@ -431,11 +431,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.1.tgz#5c6f4a1eabca84792fbd916f0cb40847f123c656"
|
||||
integrity sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA==
|
||||
|
||||
"@types/jwt-decode@^2.2.1":
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/jwt-decode/-/jwt-decode-2.2.1.tgz#afdf5c527fcfccbd4009b5fd02d1e18241f2d2f2"
|
||||
integrity sha512-aWw2YTtAdT7CskFyxEX2K21/zSDStuf/ikI3yBqmwpwJF0pS+/IX5DWv+1UFffZIbruP6cnT9/LAJV1gFwAT1A==
|
||||
|
||||
"@types/minimatch@*", "@types/minimatch@^3.0.3":
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
||||
|
|
@ -5213,11 +5208,6 @@ jsprim@^1.2.2:
|
|||
json-schema "0.2.3"
|
||||
verror "1.10.0"
|
||||
|
||||
jwt-decode@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-2.2.0.tgz#7d86bd56679f58ce6a84704a657dd392bba81a79"
|
||||
integrity sha1-fYa9VmefWM5qhHBKZX3TkruoGnk=
|
||||
|
||||
killable@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ func IsMember(claims jwtgo.Claims, groups []string) bool {
|
|||
}
|
||||
// TODO: groups is hard-wired but we should really be honoring the 'scopes' section in argocd-rbac-cm.
|
||||
// O(n^2) loop
|
||||
for _, userGroup := range GetScopeValues(mapClaims, []string{"groups"}) {
|
||||
for _, userGroup := range GetGroups(mapClaims) {
|
||||
for _, group := range groups {
|
||||
if userGroup == group {
|
||||
return true
|
||||
|
|
@ -97,3 +97,7 @@ func IsMember(claims jwtgo.Claims, groups []string) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GetGroups(mapClaims jwtgo.MapClaims) []string {
|
||||
return GetScopeValues(mapClaims, []string{"groups"})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,3 +31,8 @@ func TestIsMember(t *testing.T) {
|
|||
assert.False(t, IsMember(jwt.MapClaims{"groups": []string{"my-group"}}, []string{""}))
|
||||
assert.True(t, IsMember(jwt.MapClaims{"groups": []string{"my-group"}}, []string{"my-group"}))
|
||||
}
|
||||
|
||||
func TestGetGroups(t *testing.T) {
|
||||
assert.Empty(t, GetGroups(jwt.MapClaims{}))
|
||||
assert.Equal(t, []string{"foo"}, GetGroups(jwt.MapClaims{"groups": []string{"foo"}}))
|
||||
}
|
||||
|
|
|
|||
110
util/jwt/zjwt/zjwt.go
Normal file
110
util/jwt/zjwt/zjwt.go
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
// The package provides a way to create compact JWTs, "zJWT".
|
||||
//
|
||||
// zJWTs for JWT with a large payload can be 1/3 the size of the original.
|
||||
// This is achieved by gzipping the payload before base 64 encoding it.
|
||||
//
|
||||
// zJWTs are only compact if they are smaller than the original JWTs.
|
||||
// as long as they are smaller than the zJWT representation.
|
||||
//
|
||||
// To help differentiate, zJWTs start with "zJWT/v1:"
|
||||
package zjwt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var encoding = base64.RawStdEncoding
|
||||
|
||||
// some magic text that is easy to search the Internet for and find your way to docs
|
||||
var magicNumber = "zJWT/v1"
|
||||
|
||||
// when to use ZJWT
|
||||
// - "never" - never use it - good for it goes wrong
|
||||
// - "" - when better
|
||||
// - "always" - always use it - good for forcing this on for testing
|
||||
var featureFlag = os.Getenv("ARGOCD_ZJWT_FEATURE_FLAG")
|
||||
|
||||
// the smallest size JWT we'll compress, 3k chosen as cookies max out at 4k
|
||||
var minSize = 3000
|
||||
|
||||
// ZJWT turns a JWT into either a zJWT or return the original JWT, whichever is smaller.
|
||||
func ZJWT(text string) (string, error) {
|
||||
if featureFlag == "never" || featureFlag != "always" && len(text) < minSize {
|
||||
return text, nil
|
||||
}
|
||||
parts := strings.SplitN(text, ".", 3)
|
||||
if len(parts) != 3 {
|
||||
return "", fmt.Errorf("JWT '%s' should have 3 dot-delimited parts", text)
|
||||
}
|
||||
header := parts[0]
|
||||
payload := parts[1]
|
||||
signature := parts[2]
|
||||
decodedPayload, err := encoding.DecodeString(payload)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
w := gzip.NewWriter(&buf)
|
||||
_, err = w.Write(decodedPayload)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = w.Close()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
compressedPayload := encoding.EncodeToString(buf.Bytes())
|
||||
zJWT := fmt.Sprintf("%s.%s.%s.%s", magicNumber, header, compressedPayload, signature)
|
||||
if featureFlag == "always" || len(zJWT) < len(text) {
|
||||
return zJWT, nil
|
||||
} else {
|
||||
return text, nil
|
||||
}
|
||||
}
|
||||
|
||||
// JWT expands either a zJWT or a JWT to a JWT.
|
||||
func JWT(text string) (string, error) {
|
||||
parts := strings.SplitN(text, ".", 4)
|
||||
if len(parts) == 3 {
|
||||
return text, nil
|
||||
}
|
||||
if len(parts) != 4 {
|
||||
return "", fmt.Errorf("zJWT '%s' should have 4 dot-delimited parts", text)
|
||||
}
|
||||
part0 := parts[0]
|
||||
if part0 != magicNumber {
|
||||
return "", fmt.Errorf("the first part of the zJWT '%s' does not equal '%s'", part0, magicNumber)
|
||||
}
|
||||
header := parts[1]
|
||||
payload := parts[2]
|
||||
signature := parts[3]
|
||||
decodedPayload, err := encoding.DecodeString(payload)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
r, err := gzip.NewReader(bytes.NewReader(decodedPayload))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
uncompressedPayload, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = r.Close()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
encodedPayload := encoding.EncodeToString(uncompressedPayload)
|
||||
jwt := fmt.Sprintf("%s.%s.%s", header, encodedPayload, signature)
|
||||
return jwt, nil
|
||||
}
|
||||
49
util/jwt/zjwt/zjwt_test.go
Normal file
49
util/jwt/zjwt/zjwt_test.go
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
package zjwt
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func init() {
|
||||
minSize = 0
|
||||
}
|
||||
|
||||
func TestCompactor(t *testing.T) {
|
||||
t.Run("Small", func(t *testing.T) {
|
||||
jwt := `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.EpM5XBzTJZ4J8AfoJEcJrjth8pfH28LWdjLo90sYb9g`
|
||||
compactJWT, err := ZJWT(jwt)
|
||||
assert.NoError(t, err)
|
||||
expandedJWT, err := JWT(compactJWT)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, jwt, expandedJWT)
|
||||
assert.Equal(t, jwt, compactJWT)
|
||||
assert.Equal(t, 100, 100*len(compactJWT)/len(jwt))
|
||||
})
|
||||
t.Run("Large", func(t *testing.T) {
|
||||
jwt := `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJncm91cHMiOlsiU0JHIiwiU0JHOk1lbWJlcnMiLCJTQkc6dWkiLCJTQkc6emlvbiIsIlNCRzpoYXJtb255LXVpLWNvbXBvbmVudHMtZXh0ZW5kZWQiLCJTQkc6bmV4Z2VuLXNlcnZpY2VzLXRlYW0iLCJTQkc6c2JnLXFhLXdyaXRlIiwiU0JHOmFkbWluLXFiYS11aS1hdXRvbWF0aW9uIiwiU0JHOnNiZy9xYm8tYXV0b21hdGlvbi10ZWFtLWFkbWluIiwiU0JHOmdpdGxhYi10b29scy13cml0ZSIsIlNCRzpTQkctT2ZmZXJpbmdzLVFFIiwiU0JHOnFiby1iaWxsaW5nLXRlc3QtcWUtdGVhbSIsIlNCRzpxYm8tYmlsbGluZy10ZXN0LWFkbWluIiwiU0JHOnFiYS1xdWFsaXR5LXRlYW0iLCJTQkc6cWJvLWZ0dS1xdWFsaXR5LWFkbWluLXRlYW0iLCJTQkc6cWJhLW1pZ3JhdGlvbi10b29scy10ZWFtIiwiU0JHOlhjZWxsZW5jZUZvcnVtSlMiLCJTQkc6dHJpbml0eWpzLW1vYmlsZSIsIm1vbmV5LWFuZC1tYWdpYyIsIm1vbmV5LWFuZC1tYWdpYzpPd25lcnMiLCJtb25leS1hbmQtbWFnaWM6TSAmIE0gU2NydW0gVGVhbSIsInBheXJvbGwiLCJwYXlyb2xsOkRFUFJFQ0FURURfT3duZXJzIiwicGF5cm9sbDpQYXlyb2xsQWxsIiwiU0JHLVBDUy1DSUNEIiwiU0JHLVBDUy1DSUNEOk93bmVycyIsIlNCLVFCTy1RRS1PZmZlcmluZ3MiLCJTQi1RQk8tUUUtT2ZmZXJpbmdzOk93bmVycyIsIlNCLVFCTy1RRS1PZmZlcmluZ3M6cWJvLWxxYS1hZG1pbiIsIlNCLVFCTy1RRS1PZmZlcmluZ3M6UUUtR3JvdXAiLCJTQi1RQk8tUUUtUGF5bWVudHMiLCJTQi1RQk8tUUUtUGF5bWVudHM6T3duZXJzIiwiU0ItUUJPLVFFLVBheW1lbnRzOnFiby1wYXltZW50cy1xZS10ZWFtIiwiU0ItUUJPLVFFLVBheXJvbGwiLCJTQi1RQk8tUUUtUGF5cm9sbDpPd25lcnMiLCJTQi1RQk8tUUUtUGF5cm9sbDpTQi1RQk8tUUUtUGF5cm9sbCIsIlNCLVFCTy1RRS1QYXlyb2xsOnBheXJvbGwtcWUtdGVhbSIsIml0YWciLCJpdGFnOml0YWctdWkiLCJpdGFnOml0YWctd3MiLCJpdGFnOm1hcnRpbmktanMiLCJnaXRsYWItbWlncmF0aW9uLTAwMDEiLCJnaXRsYWItbWlncmF0aW9uLTAwMDE6T3duZXJzIiwiZ2l0bGFiLW1pZ3JhdGlvbi0wMDAyIiwiZ2l0bGFiLW1pZ3JhdGlvbi0wMDAyOk93bmVycyIsImdpdGxhYi1taWdyYXRpb24tMDA0NSIsImdpdGxhYi1taWdyYXRpb24tMDA0NTpPd25lcnMiLCJnaXRsYWItbWlncmF0aW9uLTAwNDYiLCJnaXRsYWItbWlncmF0aW9uLTAwNDY6T3duZXJzIiwiU0JHLVBsdWdpbnMiLCJTQkctUGx1Z2luczpDb3JlIiwiU0JHLVBsdWdpbnM6aW1wcm92ZWQtaW52ZW50b3J5IiwiU0JHLVBsdWdpbnM6d2ludm9pY2UtZ21haWwiLCJBbHRpbWV0cmlrIiwiQWx0aW1ldHJpazpBbHRpbWV0cmlrIiwiU0ItUUJPLVFFLU9mZmVyaW5ncy1Nb2JpbGUiLCJTQi1RQk8tUUUtT2ZmZXJpbmdzLU1vYmlsZTpPd25lcnMiLCJRQk8tQ29yZSIsIlFCTy1Db3JlOnFiby1qYXZhLW1vbm9saXRoLXdyaXRlLWFjY2VzcyIsIlFCTy1JbnZlbnRvcnkiLCJRQk8tSW52ZW50b3J5OkFkbWlucyIsIlFCTy1JbnZlbnRvcnk6Q29udHJpYnV0b3JzIiwiUUJPLUludmVudG9yeTpDSUNEIiwiUUJPLUJpbGxpbmciLCJRQk8tQmlsbGluZzpCaWxsaW5nLVVJLUFkbWluIiwiU0JHLVFFIiwiZmFicmljLWFwcC1zaGVsbHMiLCJmYWJyaWMtYXBwLXNoZWxsczpNb2JpbGUgU2hlbGwiLCJmYWJyaWMtYXBwLXVpLWNvbXBvbmVudHMiLCJmYWJyaWMtYXBwLXVpLWNvbXBvbmVudHM6ZmFicmljLWFwcC11aS1jb21wb25lbnRzLW1lbWJlcnMiLCJmYWJyaWMtYXBwLXVpLWNvbXBvbmVudHM6SURTIEV4dGVuZGVkIENvcmUgVGVhbSIsImRldi10ZXN0IiwiZGV2LXRlc3Q6VEVQIiwidGVzdC1wbGF0Zm9ybSIsInRlc3QtcGxhdGZvcm06dGVzdC1wbGF0Zm9ybS1vcmctYWRtaW5zIiwidGVzdC1wbGF0Zm9ybTpvdmVyd2F0Y2gtY29yZSIsIm9wZW4tdWktY29tcG9uZW50cyIsIlNCU0VHLUVQSUMiLCJhY2NvdW50aW5nLWNvcmUiLCJhY2NvdW50aW5nLWNvcmU6YWNjb3VudGluZy1jb3JlLXFiby1jYXNlY2VudGVyLXVpIiwia3ViZXJuZXRlcyIsImt1YmVybmV0ZXM6c2Jnc2VnLWNkcC10ZWFtIiwic3ZjLXNic2VnLWNkcCIsIlNVRFMiLCJTVURTOlNVRFMiLCJhcHAtc2hlbGwiLCJhcHAtc2hlbGw6YXJnb2NkLWFkbWlucyIsIlNCRy1UcmlhZ2VCb3QiLCJzYW5kYm94LXNhbmRib3giLCJzYW5kYm94LXNhbmRib3g6dXgtd29ya3Nob3AtcmFqIiwic2FuZGJveC1zYW5kYm94OnV4LXdzLXJhaiIsInNhbmRib3gtc2FuZGJveDpyYWotdGVzdC13cyIsInBheXJvbGwtcGF5Y2hlY2siLCJwYXlyb2xsLXBheWNoZWNrOlNCR1NDVEVQIiwiYXBwLXVpY29tcG9uZW50cyIsImFwcC11aWNvbXBvbmVudHM6UGxheWdyb3VuZC1ydmFzaWthcmxhIiwiYXBwLXVpY29tcG9uZW50czphcHAtdWljb21wb25lbnRzLWlkcy1kYXNoYm9hcmQtdWkiLCJhcHAtdWljb21wb25lbnRzOmlkcy1wbGF5Z3JvdW5kLXVpIiwiVVgtSW5mcmEiLCJVWC1JbmZyYTpDb3JlIiwiZGVzaWduLXN5c3RlbXMiXX0.XDozAEiz9AIVkA3DFbPOKG6msM43gT5zup3oxsHg_4Q`
|
||||
compactJWT, err := ZJWT(jwt)
|
||||
assert.NoError(t, err)
|
||||
expandedJWT, err := JWT(compactJWT)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, jwt, expandedJWT)
|
||||
assert.Equal(t, 37, 100*len(compactJWT)/len(jwt))
|
||||
})
|
||||
}
|
||||
|
||||
func TestCompact(t *testing.T) {
|
||||
_, err := ZJWT(".")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestExpand(t *testing.T) {
|
||||
_, err := JWT(".")
|
||||
assert.Error(t, err)
|
||||
_, err = JWT("...")
|
||||
assert.Error(t, err)
|
||||
_, err = JWT("zJWT/v1:...")
|
||||
assert.Error(t, err)
|
||||
_, err = JWT("zJWT/v1:..!.")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/argoproj/argo-cd/util/cache"
|
||||
"github.com/argoproj/argo-cd/util/dex"
|
||||
httputil "github.com/argoproj/argo-cd/util/http"
|
||||
"github.com/argoproj/argo-cd/util/jwt/zjwt"
|
||||
"github.com/argoproj/argo-cd/util/rand"
|
||||
"github.com/argoproj/argo-cd/util/settings"
|
||||
)
|
||||
|
|
@ -249,13 +250,20 @@ func (a *ClientApp) HandleCallback(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
cookie, err := httputil.MakeCookieMetadata(common.AuthCookieName, idTokenRAW, flags...)
|
||||
if err != nil {
|
||||
claimsJSON, _ := json.Marshal(claims)
|
||||
http.Error(w, fmt.Sprintf("claims=%s, err=%v", claimsJSON, err), http.StatusInternalServerError)
|
||||
return
|
||||
if idTokenRAW != "" {
|
||||
idTokenRAW, err = zjwt.ZJWT(idTokenRAW)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
cookie, err := httputil.MakeCookieMetadata(common.AuthCookieName, idTokenRAW, flags...)
|
||||
if err != nil {
|
||||
claimsJSON, _ := json.Marshal(claims)
|
||||
http.Error(w, fmt.Sprintf("claims=%s, err=%v", claimsJSON, err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Set-Cookie", cookie)
|
||||
}
|
||||
w.Header().Set("Set-Cookie", cookie)
|
||||
|
||||
claimsJSON, _ := json.Marshal(claims)
|
||||
log.Infof("Web login successful. Claims: %s", claimsJSON)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
jwt "github.com/dgrijalva/jwt-go"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
|
@ -197,16 +197,16 @@ func (mgr *SessionManager) provider() (oidcutil.Provider, error) {
|
|||
return mgr.prov, nil
|
||||
}
|
||||
|
||||
func LoggedIn(ctx context.Context) bool {
|
||||
return Sub(ctx) != ""
|
||||
}
|
||||
|
||||
// Username is a helper to extract a human readable username from a context
|
||||
func Username(ctx context.Context) string {
|
||||
claims, ok := ctx.Value("claims").(jwt.Claims)
|
||||
mapClaims, ok := mapClaims(ctx)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
mapClaims, err := jwtutil.MapClaims(claims)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
switch jwtutil.GetField(mapClaims, "iss") {
|
||||
case SessionManagerClaimsIssuer:
|
||||
return jwtutil.GetField(mapClaims, "sub")
|
||||
|
|
@ -214,3 +214,39 @@ func Username(ctx context.Context) string {
|
|||
return jwtutil.GetField(mapClaims, "email")
|
||||
}
|
||||
}
|
||||
|
||||
func Iss(ctx context.Context) string {
|
||||
mapClaims, ok := mapClaims(ctx)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return jwtutil.GetField(mapClaims, "iss")
|
||||
}
|
||||
|
||||
func Sub(ctx context.Context) string {
|
||||
mapClaims, ok := mapClaims(ctx)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return jwtutil.GetField(mapClaims, "sub")
|
||||
}
|
||||
|
||||
func Groups(ctx context.Context) []string {
|
||||
mapClaims, ok := mapClaims(ctx)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return jwtutil.GetGroups(mapClaims)
|
||||
}
|
||||
|
||||
func mapClaims(ctx context.Context) (jwt.MapClaims, bool) {
|
||||
claims, ok := ctx.Value("claims").(jwt.Claims)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
mapClaims, err := jwtutil.MapClaims(claims)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return mapClaims, true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
package session_test
|
||||
package session
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
jwt "github.com/dgrijalva/jwt-go"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
|
||||
"github.com/argoproj/argo-cd/errors"
|
||||
"github.com/argoproj/argo-cd/util/password"
|
||||
sessionutil "github.com/argoproj/argo-cd/util/session"
|
||||
"github.com/argoproj/argo-cd/util/settings"
|
||||
)
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ func TestSessionManager(t *testing.T) {
|
|||
})
|
||||
|
||||
settingsMgr := settings.NewSettingsManager(context.Background(), kubeclientset, "argocd")
|
||||
mgr := sessionutil.NewSessionManager(settingsMgr, "")
|
||||
mgr := NewSessionManager(settingsMgr, "")
|
||||
|
||||
token, err := mgr.Create(defaultSubject, 0)
|
||||
if err != nil {
|
||||
|
|
@ -61,3 +61,30 @@ func TestSessionManager(t *testing.T) {
|
|||
t.Errorf("Token claim subject \"%s\" does not match expected subject \"%s\".", subject, defaultSubject)
|
||||
}
|
||||
}
|
||||
|
||||
var loggedOutContext = context.Background()
|
||||
var loggedInContext = context.WithValue(context.Background(), "claims", &jwt.MapClaims{"iss": "qux", "sub": "foo", "email": "bar", "groups": []string{"baz"}})
|
||||
|
||||
func TestIss(t *testing.T) {
|
||||
assert.Empty(t, Iss(loggedOutContext))
|
||||
assert.Equal(t, "qux", Iss(loggedInContext))
|
||||
}
|
||||
func TestLoggedIn(t *testing.T) {
|
||||
assert.False(t, LoggedIn(loggedOutContext))
|
||||
assert.True(t, LoggedIn(loggedInContext))
|
||||
}
|
||||
|
||||
func TestUsername(t *testing.T) {
|
||||
assert.Empty(t, Username(loggedOutContext))
|
||||
assert.Equal(t, "bar", Username(loggedInContext))
|
||||
}
|
||||
|
||||
func TestSub(t *testing.T) {
|
||||
assert.Empty(t, Sub(loggedOutContext))
|
||||
assert.Equal(t, "foo", Sub(loggedInContext))
|
||||
}
|
||||
|
||||
func TestGroups(t *testing.T) {
|
||||
assert.Empty(t, Groups(loggedOutContext))
|
||||
assert.Equal(t, []string{"baz"}, Groups(loggedInContext))
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue